Accept-Encoding と Content-Encoding を正しく理解する
はじめに
「圧縮して通信量を減らす」ことはもう当たり前。でもクライアントは何ができて、サーバは何を返しているのか?
ここを理解してないとトラブルの原因に。
この記事では、HTTP で使われる Accept-Encoding / Content-Encoding とは何か?
そして、クライアントやツールごとの挙動を実際に検証して整理します。
ゴール
- 両者の役割と違いが直感で分かる
- 圧縮問題が起きたときの調査方法が理解できる
- fetch / curl / Bruno の違いを使い分けられる
仕組み
| ヘッダ | 誰が送る? | 内容 | 一言まとめ |
|---|---|---|---|
| Accept-Encoding | クライアント → サーバ | 自分が 解凍できる圧縮方式のリスト | 「こういう圧縮ならOK!」 |
| Content-Encoding | サーバ → クライアント | 実際にサーバが 圧縮して返した方式 | 「gzip で返したよ!」 |

Accept-Encoding: の意味
例:
Accept-Encoding: gzip, deflate, br
=「gzip / deflate / br のどれでも解凍できるよ!」
サーバ側の Content-Encoding 決定ロジック
- Accept-Encoding のリストを見る
- サーバが対応している圧縮方式と照合
- 選ばれた方式で圧縮
- Content-Encoding を付与して返す
例:
Content-Encoding: gzip
=「gzipで圧縮したから解凍してね!」
圧縮方式の一覧とその意味
| 圧縮方式 | 何をするか / 特徴 |
|---|---|
gzip |
LZ77+Huffman コーディング (DEFLATE ベース) を使った汎用圧縮。テキストファイル(HTML, CSS, JS, JSON など)を効率よく圧縮可能で、歴史も長く、ほとんどすべてのブラウザ/サーバで広くサポートされている。(MDN Web Docs) |
deflate |
zlib 構造 (RFC 1950) + DEFLATE アルゴリズム (RFC 1951) による圧縮。gzip に近いが、ヘッダー/フッターの扱いや互換性に差異があり、現在は gzip の方が一般的。(MDN Web Docs) |
br (Brotli) |
より最新で高度な圧縮方式。LZ77 に加え、Huffman コーディングと第二次コンテキストモデリング + 定義済み 辞書 (common phrases, HTML/CSS/JS のよくあるパターンなど) を使う。gzip より高い圧縮率を出せることが多く、特に Web のテキスト資産 (HTML, CSS, JS) で効果大。(ウィキペディア) |
identity |
圧縮しない — 生 (raw) のまま送る/受け取ることを意味する「圧縮なし」の指定。圧縮を望まない、あるいは圧縮の効果が低いと判断された場合に使われる。(MDN Web Docs) |
その他(compress など) |
昔の圧縮方式。現在は非推奨、不安定、互換性問題のためあまり使われない。(MDN Web Docs) |
圧縮の目的
- 通信量(バイト量)の削減 → 帯域使用量を節約
- 通信速度の改善 → 転送データが小さければ、ネットワーク越しの遅延や待機時間が減る
- ユーザー体験の向上 → ページや API レスポンスの応答/ロードが速くなる
圧縮方式ごとのメリット/トレードオフ
| 圧縮方式 | 長所 | 短所・注意点 |
|---|---|---|
br (Brotli) |
非常に高い圧縮率 — ページ/レスポンスサイズを最大限小さくできる。特に HTML/CSS/JS などテキスト中心で効果大。(ウィキペディア) | 圧縮にかかる CPU 負荷がやや高め。古いクライアント/古いブラウザではサポートされていない可能性。(Kinsta®) |
gzip |
高い互換性。ほぼすべてのブラウザ/クライアント・サーバ環境で使える。圧縮・解凍も比較的高速。(MDN Web Docs) |
br に比べると圧縮率がやや低め。特に大きなテキストを多数送る場合は br に劣る。 |
deflate |
gzip に似た圧縮方式。gzip と比べてやや軽量かもしれない。(MDN Web Docs) |
サポート/互換性が若干 gzip に劣ることがあったり、設定や実装差異でトラブルがある場合がある。 |
identity |
圧縮なし — 圧縮/解凍のオーバーヘッドがなく、確実に動く。バイナリやすでに圧縮されたファイル (画像など) に対して安全。 | 通信量・転送サイズが大きくなるため、非効率。特にテキストが多い Web ページや API レスポンスではパフォーマンス劣化。 |
なぜ「複数の方式」が並列に指定されることが多いのか
- クライアント/サーバ間で互換性を保つため: クライアントは複数の方式を列挙しておくことで、「どの方式がサーバで使えるか分からない/状況が変わるかもしれない」場合に備える。
- フォールバック (fallback) を持たせるため: たとえば br, gzip, deflate, identity のようにしておけば、サーバが br に対応していない場合でも gzip、それもなければ identity で返すという柔軟性が保てる。
- コンテンツ種類に応じた圧縮の最適化: たとえば JSON / HTML / CSS / JS のようなテキストは高圧縮、画像や動画などすでに圧縮されているバイナリは圧縮しない (identity) — サーバが判断することで変な圧縮による逆効果を防げる。
圧縮方式で失敗するケース
圧縮方式や交渉の仕組みをきちんと理解していないと、次のようなトラブルが起きがちです:
-
クライアントが圧縮方式をサポートしていないのに、サーバが誤って圧縮 (e.g. gzip や br) した → クライアントで解凍できず文字化けやエラー
-
サーバ側で圧縮を強制したけど、クライアントが古い/非対応 — 互換性の問題
-
圧縮のオーバーヘッド (CPU負荷) によって逆にレスポンス遅延 — 特に高圧縮率の Brotli を多用する場合
ときどき起きる問題
状況:
- クライアントが Accept-Encoding を付けてない
- サーバが 勝手に圧縮 (Content-Encoding) して返す
- クライアントが 解凍処理をしない
結果:
- 文字化け
- JSON parse error
- Unexpected token エラー
- API クライアント落ちる

調査方法
以下にリクエストを送って、Headerを可視化することはできます。
curl
accept-encoding ヘッダーなし

bruno
accept-encoding ヘッダー自動付与

上記でそれぞれのリクエスト仕組みによって、Accept-encodingが変わることがあり得るので、debugする際には要注意です。
おわりに
今日、この世界にメッセージを送ろうとしている小さな存在がいます。
Web ではクライアントとサーバが互いの意思を伝えるように、
人と人も、理解し合うためには「伝え方」がとても大切です。
Accept-Encoding と Content-Encoding は、
「私はこう受け取れます」「ではこの形で届けます」という
優しいメッセージ交換の約束事。
いつかその小さな存在が誰かとコミュニケーションするときにも、
自分の形をすなおに伝え、相手の形を尊重できる人でありますように。🍼
世界のラストワンマイルを最適化する、OPTIMINDのテックブログです。「どの車両が、どの訪問先を、どの順に、どういうルートで回ると最適か」というラストワンマイルの配車最適化サービス、Loogiaを展開しています。recruit.optimind.tech/
Discussion