Content-Encoding gzip vs br in nginx: what stock nginx sends (tested)

Content-Encoding says how the body was compressed; the client lists what it accepts in Accept-Encoding. We checked what the official nginx Docker image does with each.

1. What stock nginx sent (gzip on)

Accept-EncodingContent-EncodingBytes
(identity)none187,779
gzipgzip23,515
br onlynone187,779
gzip, deflate, br, zstd (what Chrome sends)gzip23,515

The official image has no Brotli: brotli on; fails with unknown directive "brotli". A browser offering br simply gets gzip, which is fine. Every response carried Vary: Accept-Encoding because of gzip_vary on, so caches keep compressed and plain copies apart (what Vary does, measured).

2. The gzip config we ran

gzip on;
gzip_types application/javascript;   # text/html is always included; add text/css application/json image/svg+xml ...
gzip_vary on;

gzip_comp_level 9 gave 23,688 bytes vs 23,515 at the default level 1 on this file: higher levels cost CPU and are not guaranteed to be smaller. Levels 4–6 are the usual compromise; measure on your own files.

3. Getting br

Brotli usually beats gzip on text and every current browser supports it, but nginx needs the separate ngx_brotli module (a distro package or an image built with it), then brotli on; brotli_types …;. Many CDNs (Cloudflare and others) apply Brotli at the edge without touching nginx. Pre-compress static files (.br/.gz next to the original) to pay the CPU cost once.

4. Checking a site

curl -s -o /dev/null -D- -H 'Accept-Encoding: gzip, br' https://your-site/app.js | grep -i -E 'content-encoding|vary'

No Content-Encoding line means the response was not compressed: check gzip_types for its Content-Type first.

Frequently asked questions

What does Content-Encoding: gzip mean?

The body was compressed with gzip and the browser unpacks it. In our test nginx shrank a 187,779-byte script to 23,515 bytes.

Does nginx support Brotli (br)?

Not the official Docker image: 'brotli on' failed with unknown directive, and a br-only request got the uncompressed file. You need the ngx_brotli module.

gzip or br?

br is usually smaller for text; gzip is universally supported. Offer both and the server picks; stock nginx picked gzip for Chrome's 'gzip, deflate, br, zstd'.

Is a higher gzip_comp_level better?

Not necessarily: level 9 produced a slightly larger file than the default level 1 in our test, at more CPU cost.

Written with AI assistance. Measured on 2026-10-01 with curl 8.14.1 against the official nginx:alpine image (nginx 1.31.6, throwaway container) serving a generated 187,779-byte JavaScript file. The file is repetitive, so its compression ratios are higher than typical code; compare settings, not absolute ratios. Brotli sizes were not measured (no brotli module or tool was available); the brotli module lines, the CDN remark and Chrome's usual Accept-Encoding value are from documentation, not this test. PlainHeaders is our extension; curl is free.