Request header
> Accept-Encoding: gzip, br;q=0.9Accept-Encoding Header
Learn how Accept-Encoding tells servers which compression formats (gzip, br, deflate) your client supports to reduce bandwidth and speed up page loads.
- Direction
- Request
- Category
- Content negotiation
- Spec
- RFC 9110 §12.5.3
- JS can set it
- No: forbidden header name
On this page
TL;DR:
Accept-Encodingis the request header where a client lists the compression formats it can decode, such asgziporbr(Brotli). The server picks one, or none, and says which inContent-Encoding. Browsers set it for you and JavaScript can’t change it, so test with curl.
What is Accept-Encoding?
In a request, this field negotiates content codings. It’s separate from Transfer-Encoding, which frames an HTTP/1.1 message. Servers can send Accept-Encoding too, to advertise which codings they accept in request bodies, for example in a 415 response. MDN describes both uses.
How Accept-Encoding Works
Here’s a request and response with bodies omitted. Headers and outputs on this page are trimmed examples.
GET /report HTTP/1.1
Host: example.com
Accept-Encoding: gzip, br;q=0.8
HTTP/1.1 200 OK
Content-Type: application/json
Content-Encoding: gzip
Vary: Accept-Encoding
No Content-Encoding in the response means the body wasn’t compressed. That’s allowed: offering gzip doesn’t force the server to use it.
Common Compression Algorithms
gzip is gzip and br is Brotli. HTTP’s deflate is the odd one: it means a zlib wrapper around a DEFLATE stream, not raw DEFLATE. Only advertise formats your client can decode. For curl, curl --version lists what your build supports.
Quality Values and Preferences
Accept-Encoding: br;q=1, gzip;q=0.8
This says “Brotli preferred, gzip fine”. Plain br, gzip gives both the default quality of 1, because list order isn’t a ranking.
Real-World Examples
Let curl advertise what it supports and decode the response for you:
curl --compressed -D - -o /dev/null https://example.com/
--compressed decodes the body, but the printed headers still describe the encoded response. So the saved file’s size won’t match Content-Length, which counts compressed bytes.
Compression Effectiveness
How much you save depends on the content. There’s no fixed ratio for HTML, JSON or JavaScript. Measure the same resource both ways and check which coding the server actually chose before crediting compression with the difference.
Responses that arrive already encoded are a good diagnostic case. If the application sends Content-Encoding: gzip, look at the raw bytes saved without --compressed (the commands in the measuring section below save them to /tmp/gzip.body):
file /tmp/gzip.body
gzip -t /tmp/gzip.body
Run the gzip check only after the saved headers confirm the coding. A 200 status says nothing about whether the body is valid gzip, and a gzip failure on a body that was never encoded tells you nothing about negotiation.
Getting Accept-Encoding right
Inside an nginx http, server, or location block:
gzip on;
gzip_types text/plain application/json text/css application/javascript;
gzip_vary on;
The nginx gzip module always compresses text/html on top of whatever gzip_types lists. Both gzip and gzip_vary default to off, so you need to turn them on. This config gives you gzip only, not Brotli.
In browsers, Accept-Encoding is a forbidden request header. Leave it and Content-Length out of fetch() calls; the browser manages both.
For Caddy serving files from /srv/www, turn on its encoders directly:
example.com {
root * /srv/www
encode zstd gzip
file_server
}
Caddy’s encode directive negotiates these formats from the request. Putting zstd first makes it the server’s pick when the client doesn’t express a stronger preference. A client that only offers gzip gets gzip.
Measure the savings on your own responses
Swap in the URL you’re investigating. These requests save the raw bodies, with no automatic decompression from curl:
curl -sS -D /tmp/identity.headers -o /tmp/identity.body \
-H 'Accept-Encoding: identity' https://example.com/
curl -sS -D /tmp/gzip.headers -o /tmp/gzip.body \
-H 'Accept-Encoding: gzip' https://example.com/
cat /tmp/identity.headers /tmp/gzip.headers
wc -c /tmp/identity.body /tmp/gzip.body
Compare Content-Encoding, status and validators like ETag across both responses. Matching byte counts alone don’t prove the server ignored the header.
Compression Priority and Quality Values
Under RFC 9110 §12.5.3, a request with no Accept-Encoding field accepts any coding, while an empty field asks for no coding at all. identity means “no encoding”. It’s acceptable by default unless you exclude it with identity;q=0, or with *;q=0 when there’s no more specific entry for identity.
Accept-Encoding: identity asks for an uncompressed response. Because gzip and Brotli aren’t listed, they aren’t acceptable, and a server that sends gzip anyway is ignoring the request. Test this case when an intermediary seems to compress every response.
Related Headers
Frequently asked questions
What is Accept-Encoding?
Accept-Encoding tells the server which compression algorithms the client supports. Common values are gzip, deflate, and br (Brotli). Servers use this to compress responses.
What compression should I accept?
Accept only content codings your client can decode. Browser-managed values vary by browser and connection; inspect the actual request instead of copying a fixed list.
What does Accept-Encoding: identity mean?
identity means no content encoding. Accept-Encoding: identity requests an unencoded response and does not make gzip or Brotli acceptable.
How does Accept-Encoding affect caching?
Servers should include Vary: Accept-Encoding so caches store different versions for different encodings. This prevents serving gzip to clients that cannot decompress.
Sources
Related
HTTP Compression: gzip, Brotli and Zstandard Setup
How HTTP compression works: Accept-Encoding negotiation, gzip vs Brotli vs zstd, nginx, Caddy, Express and Cloudflare config, BREACH, and measuring with curl.
If-Match Header
Learn how the If-Match header makes requests conditional based on ETag matching. Prevent conflicts and lost updates in concurrent editing scenarios.
If-Modified-Since Header
Learn how the If-Modified-Since header requests resources only if modified since a specific date. Reduce bandwidth with efficient conditional caching.
If-None-Match Header
Learn how the If-None-Match header makes conditional requests using ETags. Avoid downloading unchanged resources and reduce bandwidth with cache validation.