Accept-Encoding content request
Lists the compression algorithms the client supports — so the server knows which encoding to use on the response body.
What it does
Accept-Encoding tells the server which compression formats the client can decompress. The server picks the best supported encoding, compresses the response body, and declares its choice in Content-Encoding. This transparent compression typically cuts response sizes by 60–80% for text content.
Syntax
Accept-Encoding: gzip
Accept-Encoding: gzip, br
Accept-Encoding: gzip, deflate, br, zstd
Accept-Encoding: *
Accept-Encoding: identity
Accept-Encoding: gzip;q=1.0, deflate;q=0.5, *;q=0
Encoding values
| Value | Algorithm | Notes |
|---|---|---|
gzip |
GNU zip (LZ77 + CRC32) | Universal support, always safe to request |
br |
Brotli | Better compression than gzip, all modern browsers, HTTPS-only in browsers |
zstd |
Zstandard | Newer, excellent ratios, growing adoption |
deflate |
zlib/deflate | Avoid — ambiguous implementation, inconsistent across servers |
identity |
No encoding | Explicitly request uncompressed |
* |
Any encoding | Accept whatever the server prefers |
Quality values
Q-factors express preference, same as Accept:
Accept-Encoding: br;q=1.0, gzip;q=0.8, *;q=0.1
Prefer brotli, fall back to gzip, accept anything else as last resort.
Most clients just list supported encodings without q-factors and let the server choose optimally:
Accept-Encoding: gzip, deflate, br, zstd
What browsers send
A modern Chrome Accept-Encoding:
Accept-Encoding: gzip, deflate, br, zstd
The browser supports all four. The server typically picks br (best compression) or gzip (best compatibility) based on its configuration.
The Vary: Accept-Encoding requirement
This is the most important gotcha with Accept-Encoding. When a server compresses responses, it must include Vary: Accept-Encoding so caches store separate versions for clients with different encoding support:
HTTP/1.1 200 OK
Content-Type: text/html
Content-Encoding: br
Vary: Accept-Encoding
Cache-Control: public, max-age=3600
Without Vary: Accept-Encoding, a CDN might cache the brotli-compressed version and serve it to a client that sent Accept-Encoding: gzip only — the client receives brotli bytes it can't decode. Garbled content, no error message, very confusing to debug.
Most web servers (nginx, Apache, Caddy) set Vary: Accept-Encoding automatically when they compress. Application-level compression middleware usually does too. But if you're setting Content-Encoding manually, you're responsible.
Disabling compression
To explicitly request no compression:
Accept-Encoding: identity
Or exclude specific encodings:
Accept-Encoding: gzip;q=0, br;q=0, *;q=0
(q=0 means "not acceptable")
This is useful when debugging responses and you want to read the raw body, or when piping HTTP output to tools that can't decompress on the fly.
# curl — disable compression
curl --compressed-off https://example.com/api/data
# or
curl -H "Accept-Encoding: identity" https://example.com/api/data
How it interacts with Content-Encoding
These two headers form a negotiation pair:
- Client:
Accept-Encoding: gzip, br("I can handle these") - Server:
Content-Encoding: br("I compressed it with this")
The server should only use an encoding the client listed. If the client didn't list zstd and the server sends Content-Encoding: zstd anyway, the client can't decompress it.
Common mistakes and gotchas
Compressing already-compressed content. Applying gzip to JPEG images, ZIP archives, or MP4 videos adds CPU overhead and usually makes the response slightly larger. Most web servers skip compression for known binary formats. Application-level compression middleware may not — check your config.
Double compression. Application compresses with gzip, then nginx compresses again. The result: a file compressed twice, usually larger than once, and potentially requiring two decompressions. Ensure compression happens at exactly one layer.
Not sending Accept-Encoding in API clients. HTTP libraries usually send Accept-Encoding: gzip, deflate by default. Raw HTTP clients built from scratch might not. If your API client isn't receiving compressed responses, check whether it's sending Accept-Encoding.
Real-world examples
Browser request (all modern encodings):
GET /large-page HTTP/1.1
Host: example.com
Accept-Encoding: gzip, deflate, br, zstd
Server responding with brotli:
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Encoding: br
Vary: Accept-Encoding
Content-Length: 4821
curl with explicit encoding request:
curl -H "Accept-Encoding: br" -I https://example.com
FAQ
Why don't browsers use brotli over HTTP (only HTTPS)?
When brotli was introduced, Chrome's team found that some HTTP middleboxes (transparent proxies, network appliances) would corrupt content-encoded responses they didn't recognise. Since HTTPS traffic is opaque to these boxes, brotli over HTTPS is safe. Over HTTP, broken middleboxes could corrupt brotli responses silently. The HTTPS-only restriction was a pragmatic safety measure.
Does Accept-Encoding affect JSON API responses?
Yes — JSON compresses extremely well (often 80%+ reduction). Large API responses should be compressed. Most API clients (Python requests, axios, fetch) send Accept-Encoding: gzip, deflate by default and decompress transparently.
What happens if the server doesn't support any listed encoding?
The server should return the response uncompressed with no Content-Encoding header. It should not return 406 Not Acceptable — unlike Accept, an unsupported encoding doesn't warrant rejection of the whole request.
Fun fact
The web's adoption of brotli over gzip for static assets represents one of the most successful compression transitions in internet history. Google open-sourced brotli in 2015, and within 5 years it became the default choice for pre-compressed static assets on most major CDNs. A typical HTML/CSS/JS bundle compressed with brotli at level 11 is 15–25% smaller than the same bundle at gzip's best level — a meaningful bandwidth saving at web scale. The Accept-Encoding: br capability flag in billions of browser requests per second is what made this transition happen seamlessly and automatically.