Content-Encodingとは
Content-Encodingは、representationへ適用されたcontent codingを示すrepresentation headerです。requestとresponseの両方に現れ得ますが、Web配信では主に、HTML、CSS、JavaScript、JSONなどを圧縮したresponseで目にします。
圧縮率は、内容、ファイルサイズ、方式、圧縮レベルによって変わります。「常にBrotliが最小」「必ず何%減る」とは決められないため、実際のコンテンツで測ることが重要です。
圧縮方式を決める流れ

クライアントとサーバーは、次のように圧縮方式を交渉します。
1. クライアントが候補を送る
クライアントはAccept-Encodingで、デコードできる方式を伝えます。
GET /app.js HTTP/1.1
Host: example.com
Accept-Encoding: gzip, br, zstd
実際の候補は、ブラウザ、OS、接続方法によって異なります。サーバーは一覧にない方式を一方的に選べません。
2. サーバーが1つ選ぶ
サーバーは、対応状況、コンテンツ、CPU負荷、事前圧縮ファイルの有無などから方式を選びます。
HTTP/1.1 200 OK
Content-Type: application/javascript
Content-Encoding: br
Vary: Accept-Encoding
Content-Encoding: brは、本文がBrotliで圧縮されていることを示します。ブラウザは本文を復元してからJavaScriptとして扱います。
適切な方式がない場合は、圧縮しないidentityで返せます。Accept-Encodingの品質値やidentity;q=0などの条件によっては、サーバーが受け入れ可能な表現を返せないこともあります。
3. キャッシュを分ける
同じURLでも、クライアントによってgzip、br、未圧縮の応答があり得ます。そのため、共有キャッシュへ次を伝えます。
Vary: Accept-Encoding
これがないと、あるクライアント向けの圧縮応答を、対応していないクライアントへ返す事故につながります。CDNやフレームワークが自動設定する場合も、実際の応答で確認します。
gzip・Brotli・Zstandardの選び方
| 方式 | 特徴 | 検討しやすい場面 |
|---|---|---|
gzip | 長く使われ、幅広い環境で扱いやすい | 互換性を重視する動的・静的コンテンツ |
br | テキストで良い圧縮結果を得られる場合がある | ビルド時に事前圧縮できる静的ファイル |
zstd | 圧縮・展開速度と圧縮率のバランスを調整しやすい | 対象クライアント、CDN、サーバーが対応する環境 |
ZstandardのHTTPコンテンツコーディングはRFC 8878で定義されています。ただし、規格があることと、利用中の全ブラウザ・CDN・Webサーバー・監視ツールが同じように対応することは別です。導入時点の対象環境で確認し、非対応クライアントにはgzipや未圧縮で返します。
deflateもHTTPのコンテンツコーディングとして定義されていますが、新しい構成で積極的に選ぶ理由は多くありません。既存システムとの互換性が必要な場合に、実装の挙動を確認して扱います。
圧縮レベルは高ければよいわけではない
多くの圧縮方式には、速度とサイズを調整するレベルがあります。高いレベルは小さくなる可能性がありますが、圧縮時間とCPU使用量も増えます。
静的ファイル
ビルド時に一度だけ圧縮し、.gzや.brを配信できるため、比較的時間をかけられます。ただし、最高レベルの追加時間に見合うサイズ差があるか測ります。
動的レスポンス
リクエストごとに圧縮するJSONやHTMLでは、圧縮処理が応答時間やサーバー容量へ影響します。低めのレベル、一定サイズ以上だけ圧縮、CDNでの圧縮などを比較します。
比較するときは、次を同じ条件で測ります。
- 元データと圧縮後のバイト数
- 圧縮と展開にかかる時間
- CPUとメモリ使用量
- キャッシュヒット率
- 対象ブラウザと中継機器での成功率
圧縮しないほうがよい内容
次の内容は、圧縮効果が小さいか、別の問題を生む場合があります。
- JPEG、WebP、AVIF、MP4、ZIPなど、すでに圧縮されているデータ
- ヘッダーを含めた追加処理に対して非常に小さい本文
- CPU負荷が高く、転送量削減より応答遅延が問題になるレスポンス
- 秘密情報と攻撃者が操作できる文字列を同じ応答に含む内容
最後のケースでは、圧縮後サイズの変化から秘密を推測するBREACHのような攻撃を考慮します。CSRF対策、秘密と入力の分離、該当応答の圧縮無効化などを、システムの脅威に合わせて検討します。
Content-Typeとの違い
Content-Typeは、復元後の本文が何であるかを示します。Content-Encodingは、その本文へどの変換を適用したかを示します。
Content-Type: application/json
Content-Encoding: gzip
この場合、転送された本文をgzipで展開するとJSONになります。
Content-Lengthが付く場合、その値は通常、転送される符号化後の本文サイズです。展開後のサイズではありません。
実際の応答を確認する
curlで、サーバーがどの方式を選ぶか確認できます。
curl --compressed -I https://example.com/app.js
特定の候補を送って比較する場合は、次のようにします。
curl -I \
-H 'Accept-Encoding: gzip, br, zstd' \
https://example.com/app.js
確認する主なヘッダーは次のとおりです。
Content-Encoding: br
Vary: Accept-Encoding
Content-Length: 18420
ブラウザのDevToolsでは、NetworkパネルでContent-Encodingと、転送サイズ・リソースサイズを確認します。Service Worker、ブラウザキャッシュ、CDNキャッシュが結果へ影響するため、キャッシュ条件をそろえて比較します。
まとめ
Accept-Encodingでクライアントが候補を示し、サーバーが1つ選ぶ- 選んだ方式を
Content-Encodingで示す - 圧縮方式ごとに応答が変わる場合は
Vary: Accept-Encodingが重要 - gzip、Brotli、Zstandardに絶対的な優劣はなく、内容と運用条件で選ぶ
- Zstandardは対象ブラウザ、CDN、サーバーの対応を導入時に確認する
- すでに圧縮済みのデータや小さな本文は、圧縮しないほうがよい場合がある
- 圧縮率だけでなく、CPU、応答時間、キャッシュも含めて測る
参考リソース
- MDN - Content-Encoding
- MDN - Accept-Encoding
- RFC 9110 - HTTP Semantics: Content Codings
- RFC 7932 - Brotli Compressed Data Format
- RFC 8878 - Zstandard Compression and the application/zstd Media Type