HTTP Compression
HTTP compression reduces the size of data transferred between servers and clients. A client sends an Accept-Encoding header listing supported content codings. The server picks one, compresses the response body, and indicates the choice in a Content-Encoding header. This exchange is a form of proactive content negotiation.
Baseline
Brotli compression is widely available across all major browsers. Zstandard is newly available.
How content coding works
HTTP compression operates at the representation level. The server applies a content coding to the response body before transmission. The client reverses the coding after receiving the full response.
The Accept-Encoding request header lists acceptable codings with optional quality values:
Accept-Encoding: br, gzip;q=0.8, zstd;q=0.9
The server selects one coding and returns the compressed body with two key headers:
- Content-Encoding names the coding applied
- Content-Length reflects the compressed size, not the original
Vary header and caching
Servers returning different encodings based on
the request must include Vary: Accept-Encoding
in the response. Without this header, a
cache stores one encoded variant and
serves the cached variant to clients expecting a
encoding or no encoding at all.
Content codings
The content coding framework defines registered codings. The IANA Content Coding Registry tracks all registered codings. The most common ones used in HTTP:
gzip
The gzip coding uses the GZIP file format
, combining LZ77 and Huffman coding.
Supported by every HTTP client and server. The
gzip coding remains the most widely deployed
content coding on the web.
br (Brotli)
The br coding uses the Brotli algorithm
, developed by Google. Brotli achieves
higher compression ratios than gzip at comparable
decompression speeds. Brotli includes a built-in
static dictionary of common web content patterns,
an advantage for compressing HTML, CSS, and
JavaScript.
All major browsers support Brotli over HTTPS connections.
zstd (Zstandard)
The zstd coding uses the Zstandard algorithm
, developed at Facebook. Zstandard
offers a wide range of compression levels, from
fast modes exceeding gzip speed to high modes
rivaling Brotli compression ratios. Zstandard
decompression is fast regardless of the
compression level used.
deflate
The deflate coding wraps a DEFLATE compressed
stream inside the zlib format
. Historical inconsistencies between
implementations (some sent raw DEFLATE without
the zlib wrapper) made deflate unreliable.
Modern HTTP favors gzip or br instead.
compress
The compress coding uses adaptive Lempel-Ziv-
Welch (LZW). Rarely encountered in modern HTTP.
identity
The identity coding means no transformation
was applied. This value appears in
Accept-Encoding to signal
acceptance of uncompressed responses. A server
is always allowed to send an uncompressed
response, even when the client lists only
compression codings.
Lossy vs. lossless compression
HTTP content coding is exclusively lossless. Every content coding registered for use with Content-Encoding (gzip, br, zstd, deflate) reconstructs the original bytes exactly on decompression.
Lossy compression exists in media formats like JPEG, MP3, and H.264. These formats are applied at the content creation stage, before HTTP transmission. A JPEG image served over HTTP is already lossy at the format level. Applying HTTP content coding (gzip or br) to a JPEG adds lossless compression on top, often with negligible size reduction, since the JPEG data is already compressed.
Skip compression for pre-compressed formats
Applying content coding to pre-compressed media (JPEG, PNG, MP4, WOFF2) wastes CPU cycles for minimal size savings. Server configurations often exclude these MIME types from compression.
End-to-end compression
End-to-end Compression compresses data at the origin and decompresses at the final client. Intermediaries such as proxies, load balancers, and CDNs pass the compressed body through without modification.
The negotiation flow:
- Client sends Accept-Encoding listing supported codings
- Server selects a coding and compresses the response body
- Server returns
Content-Encoding and
Vary: Accept-Encoding - Client decompresses the body
This is the standard compression model in HTTP and the one most servers implement.
Hop-by-hop compression
Hop-by-hop compression uses Transfer-Encoding instead of Content-Encoding. The compression applies between individual hops (client to proxy, proxy to proxy, proxy to server) rather than across the entire path.
The client sends a TE header to indicate which transfer codings are acceptable. The receiving server or intermediary selects a coding and applies the compression for one hop. The next hop negotiates independently.
HTTP/2 restriction on TE
HTTP/2 restricts the TE header
to the value trailers only. Hop-by-hop
transfer coding compression is not available
in HTTP/2 or HTTP/3.
Limited server support
Hop-by-hop compression is rarely implemented. Most servers and proxies use end-to-end content coding instead.
Example
A client requests an HTML page and lists four
accepted codings in order of preference. The
server selects gzip and returns the compressed
response with the appropriate headers.
Request
GET /news.html HTTP/1.1
Host: www.example.re
Accept-Encoding: br, zstd, gzip, deflate
Response
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 5028
Vary: Accept-Encoding
<compressed body>
The Content-Length value (5028) represents the
compressed size. The original uncompressed HTML
is larger. The Vary: Accept-Encoding header
tells caches to store separate variants for
different encoding preferences.
A Brotli-compressed response from the same server
to a client supporting br:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Encoding: br
Content-Length: 4211
Vary: Accept-Encoding
<compressed body>
SEO and compression
Search engine crawlers like Googlebot support
gzip and Brotli. Compressed responses reduce
crawl bandwidth consumption, allowing more
pages to be fetched within a crawl budget.
Bingbot sends
Accept-Encoding: gzip, deflate.
Takeaway
HTTP compression reduces transfer sizes
through lossless content codings negotiated
between client and server via
Accept-Encoding and
Content-Encoding. Brotli
and Zstandard offer better ratios than gzip,
while gzip remains universally supported.
Servers include Vary: Accept-Encoding to
ensure caches serve the correct variant.
See also
- RFC 9110: HTTP Semantics, Section 8.4 (Content Codings)
- RFC 7932: Brotli Compressed Data Format
- RFC 8878: Zstandard Compression
- Accept-Encoding
- Content-Encoding
- Transfer-Encoding
- TE
- Vary
- Content negotiation
- HTTP/2
- HTTP headers