LW IT Solutions logo LW IT Solutions logo LW IT Solutions
« Blog Overview /Web Development/Tutorials / gzip, Brotli and zstd: HTTP Compression Measured
Read this article in other languages:

gzip, Brotli and zstd: HTTP Compression Measured

gzip, Brotli and zstd: HTTP Compression Measured

Management Summary

HTTP compression packs website content more efficiently for transfer, reducing the amount of data sent to a browser. gzip, Brotli and zstd are different methods for doing this. A sample of twenty domains illustrates actual use, but cannot rank the methods because the sites serve different content. The useful business balance is transfer size against computing effort and loading performance. Smaller transfers help, yet do not make a complete page proportionally faster because other parts of loading still take time.

Contents
  1. How the response encoding is selected
  2. gzip, Brotli, zstd and deflate
  3. The measured responses
  4. Ratio and saving are different numbers
  5. A measurement needs matching bodies
  6. Questions and answers
  7. Sources

HTTP compression reduces the bytes needed to transfer a response body. The result depends on the content, compression settings and the response actually returned. A successful HTTP status alone does not prove that the requested homepage arrived.

A check of twenty domains on 24 October 2026 produced seventeen regular HTML responses and three access-block responses. Of the seventeen regular responses, eleven used gzip, five used Brotli and one had no Content-Encoding. No response selected zstd. These are observations from one request configuration, not market shares or permanent website settings.

Compression sample: 24 October 2026: 20 domains checked; access blocks are not regular homepages
Compression sample: 24 October 2026: 20 domains checked; access blocks are not regular homepages.

How the response encoding is selected

Accept-Encoding advertises acceptable response encodings. The sample offered gzip, deflate, br, zstd with equal default weights. Server capabilities, configuration and resource type influence the selection; the order of this list is not a guaranteed preference order. An unencoded response is normally acceptable unless explicitly excluded.

Content-Encoding identifies the encoding actually applied. Absence of the field means no content coding is declared, not that the body must match a file on disk. HTML can be generated dynamically. Encodings can also be stacked; decoding then reverses the listed application order.

When the representation varies with this request field, Vary: Accept-Encoding helps compliant caches keep variants separate. The header is not proof that every intermediary is configured correctly. Cached or precompressed responses can be selected without recompressing the content for every request.

gzip, Brotli, zstd and deflate

  • gzip: widely supported, but not guaranteed in every client or tool build. The advertised capabilities still matter.
  • Brotli (br): often effective for text. Quality settings trade encoding effort against output size; no fixed speed or size advantage applies to every input.
  • Zstandard (zstd): designed for a useful speed-to-compression trade-off. Results depend on level, implementation, hardware and data. Zero selections in this sample do not imply missing browser support or universal server non-support.
  • deflate: the HTTP coding uses a zlib wrapper around DEFLATE. gzip also commonly uses DEFLATE, with a different wrapper. The formats are not interchangeable.

Actual browser offers depend on browser version and context. A manually constructed curl request is not a browser compatibility test.

The measured responses

The measurement ran from a Raspberry Pi between 04:45:33 and 04:45:37 UTC on 24 October 2026. curl 8.14.1 supported all four offered decoders. Each domain received one retrieval chain, with HTTPS redirects followed, no login or browser JavaScript, and the default curl user agent. The table describes the final response. Headers, decoded bodies and curl metadata were retained for verification.

Domain HTTP Content-Encoding Encoded bytes Decoded bytes Classification
wikipedia.org 200 gzip 28883 122421 regular HTML
github.com 200 gzip 118918 580257 regular HTML
bbc.com 200 gzip 92972 649846 regular HTML
nytimes.com 403 absent 771 771 access block
cloudflare.com 200 br 109639 1333885 regular HTML
mozilla.org 200 br 8032 47807 regular HTML
apple.com 200 gzip 47325 326751 regular HTML
microsoft.com 200 absent 201253 201253 access block
spiegel.de 200 gzip 272825 1958177 regular HTML
heise.de 200 gzip 135977 936097 regular HTML
python.org 200 absent 52766 52766 regular HTML
debian.org 200 gzip 4279 15864 regular HTML
kernel.org 200 gzip 3438 19152 regular HTML
gnu.org 200 gzip 9806 31463 regular HTML
w3.org 200 br 8996 49520 regular HTML
nginx.org 200 gzip 2206 6461 regular HTML
postgresql.org 200 gzip 5914 25040 regular HTML
zeit.de 403 absent 5439 5439 access block
tagesschau.de 200 br 128481 1613994 regular HTML
php.net 200 br 11789 60308 regular HTML

New York Times and ZEIT returned HTTP 403. Microsoft returned HTTP 200 but an explicit access-block page. Those three responses are excluded from the regular-homepage totals. The Microsoft body contained 201,253 bytes with no declared content coding; this does not establish the compression policy of the actual Microsoft homepage.

Python.org returned regular homepage HTML without Content-Encoding in this run. A no-JavaScript notice occurs inside that homepage; the notice alone is not a separate access-block page. Earlier or differently configured requests can receive another representation.

A tall stack of plates beside a frame and, past it, the same plates as a much shorter stack; a coral stack passes above the frame at full height

Ratio and saving are different numbers

The ratio is decoded body bytes divided by encoded body bytes. A ratio of 4 means the encoded body is one quarter of the decoded size: a 75% reduction. It does not mean a fourfold improvement in page-load speed.

Among the compressed regular responses, the ratios ranged from 2.93 at nginx.org to 12.56 at tagesschau.de. For tagesschau.de, 1,613,994 decoded bytes corresponded to 128,481 encoded bytes, about 92.0% fewer body bytes. These numbers exclude response headers, TLS and transport framing, other page resources and rendering work.

Different websites provide different inputs, so these ratios cannot rank the algorithms. A fair algorithm comparison compresses identical bytes at documented settings and measures CPU time as well as size. Repetition, not simply file length or use of a framework, determines how much redundancy is available.

A measurement needs matching bodies

Comparing two separate requests can mix different content, redirects, error pages or cache variants. An identity request also needs its actual Content-Encoding checked. Comparing the transferred and decoded sizes of the same response avoids mixing different content, but still requires a complete successful transfer, correct decoding and content inspection.

In this measurement, curl used --compressed: the saved body was decoded, while size_download recorded transferred body bytes. Saved response headers still describe the encoding on the response. The saved file must therefore not be decoded again merely because those headers contain gzip.

Questions and answers

Is extra compression useful for images and fonts?

Already compressed JPEG, PNG, WebP, AVIF and WOFF2 often gain little and can grow. SVG is text and commonly benefits. File extensions alone are insufficient; actual bytes and MIME type matter.

Should Brotli always run at its highest quality?

No. Brotli supports quality levels 0–11. Higher settings can spend substantially more encoding time. Static assets can be precompressed during a build; for dynamic responses, the compression effort must fit the available processor capacity and acceptable response time. gzip and zstd can also be precompressed. No universal best level follows from this sample.

Does HTTPS make compression harmless?

No. With BREACH-style attacks, changes in compressed response length can reveal information about secrets. This risk can arise when secrets and attacker-influenced content share a compressed response and repeated response lengths can be observed. Ordinary HTML escaping alone does not remove that condition. Depending on the application, mitigations include disabling compression on affected responses, separating secrets from reflected input or correctly masking tokens. TLS 1.3 removes TLS-level compression, but does not remove HTTP Content-Encoding or its side-channel risks.

How can one gzip response be checked manually?

The following curl command is intended for a new empty working directory and a small trusted HTTPS resource. It disables curlrc loading, does not automatically decode and does not follow redirects:

curl -q --fail --silent --show-error --max-time 30 --max-filesize 10000000 --proto "=https" -H "Accept-Encoding: gzip" -D headers.txt -o body.bin -w "%{http_code}\n" https://example.com/

Before decoding, the printed status must be 200 and the final headers must declare exactly Content-Encoding: gzip. The decoded content must subsequently be checked against the expected resource before interpreting the sizes. A redirect, block page, missing encoding or failed curl exit is not a gzip measurement. After those checks:

gzip -t body.bin &&
gzip -dc body.bin > decoded.html &&
wc -c body.bin decoded.html

The first command checks gzip integrity; subsequent commands run only on success. The two byte counts belong to the same response. Decompression can greatly expand data, so available disk space and trusted input matter. A missing Content-Encoding is an unencoded-response finding, not a reason to force gzip decoding. Other encodings require the matching decoder.

Lukas Wojcik

Lukas Wojcik

Systems architect and technology enthusiast specializing in scalable tracking solutions, GMP Stack (GA4 & GTM), and robust backend architectures. Advocate for clean code and privacy-first design.

Get in touch

A question or an idea for a web project? Tell me a little about it. This form uses reCAPTCHA to protect against spam.

Write a comment

Edge cases the article misses and questions about the code are welcome here.

The email address is not published. Required fields are marked with an asterisk.