Content Encoding: Gzip vs Brotli

Run a Speed Test

A web page is mostly text — HTML, stylesheets, scripts — and text compresses beautifully. Rather than send every byte of it across the network, servers squeeze it down first and let your browser unpack it on arrival. The savings are dramatic: a file can shrink by eighty or ninety percent before it leaves the server. This is HTTP content encoding, and the quiet negotiation that picks gzip or Brotli for each response is one of the biggest speed wins on the web.

Compression Built Into the Protocol

Content encoding is compression applied to a response body before it is sent. The point is simple: a smaller payload spends less time on the wire, so the page arrives faster — particularly on slow or distant connections where every saved kilobyte counts. Because text is highly repetitive (think how often <div class= appears in a page), it compresses far more than already-dense data, which is why this technique targets text resources specifically.

The elegant part is that it is built into HTTP as a negotiation, handled entirely through two headers. Neither side assumes anything: the browser states what it can decode, and the server chooses from that list. The user sees nothing — just a page that loads quicker.

The Two-Header Handshake

The browser opens by listing the compression schemes it understands in the Accept-Encoding request header:

Accept-Encoding: gzip, br, zstd

The server picks one it also supports, compresses the body with it, and reports the choice in the Content-Encoding response header — alongside the Content-Type that still describes the underlying format:

Content-Type: text/html; charset=utf-8
Content-Encoding: br

The browser sees Content-Encoding: br, decompresses the Brotli-packed body, and then treats the result as the UTF-8 HTML the content type promised. If the browser had sent no Accept-Encoding, or the server supported none of the listed schemes, the body would simply arrive uncompressed — the negotiation always has a safe fallback.

Gzip, Brotli, and zstd

Three schemes cover almost all of today's traffic, and they trade off differently between how small they make a file and how much CPU they spend doing it.

SchemeTokenCharacter
gzipgzipThe long-standing default — fast, universally supported, decades of compatibility. Excellent for compressing on the fly.
BrotlibrNewer and built for the web; ships with a dictionary of common web text, so it usually beats gzip on HTML, CSS, and JS. High settings are slower, so it shines for static assets compressed once.
ZstandardzstdA modern scheme prized for an exceptional speed-to-ratio balance, increasingly supported by browsers and servers.

The headline comparison most people want is gzip versus Brotli. For the same web file, Brotli typically produces a smaller result than gzip — often noticeably so on HTML and JavaScript — partly thanks to that built-in web dictionary, which gives it a head start on the boilerplate that appears on nearly every site. The catch is time: Brotli at its maximum level works harder than gzip, so squeezing the last few percent costs more CPU.

Compress Once, Serve Many — or Compress on the Fly

That speed trade-off resolves cleanly once you split content into two kinds. Static assets — your CSS bundle, your JavaScript, fonts — change rarely and are served to everyone. Compress them once at the highest Brotli level, cache the result, and every visitor gets the smallest possible file at no repeated cost. The slow compression happens a single time, off to the side.

Dynamic responses — a personalised page, a fresh API result — are generated per request and cannot be pre-compressed. Here you compress on the fly, and the right call is a faster, lower setting (gzip, or Brotli at a modest level) so the compression time does not eat the network savings. The general rule: maximum compression for things you build once, fast compression for things you build every time. This pairs naturally with caching — a compressed-and-cached asset is about as cheap as the web gets.

What Not to Compress

A common and costly mistake is compressing everything indiscriminately. Images (JPEG, PNG, WebP), video (MP4), and audio are already compressed by their own formats, which have wrung out the redundancy that gzip and Brotli look for. Running content encoding over them burns CPU for essentially zero gain — and can even add a few bytes of overhead, making the file marginally larger. Content encoding is for the text-based resources: HTML, CSS, JavaScript, JSON, SVG, XML, and font files. Media is left alone, relying on the compression baked into its format.

Two footnotes worth knowing. Content encoding is distinct from transfer encoding (such as chunked), which is about how a body is framed on the connection rather than how it is compressed. And HTTP/2 and HTTP/3 add header compression of their own — separate from this body compression — so that the headers themselves, not just the payload, travel efficiently. The principle runs all the way through: on the modern web, very little is sent at full size if it does not have to be.

Frequently Asked Questions

What is HTTP content encoding?

Compression applied to a response body before it is sent, so less data crosses the network. The browser advertises supported schemes in Accept-Encoding, the server compresses and names its choice in Content-Encoding, and the browser decompresses on arrival. It can shrink text files by 70–90%.

What is the difference between gzip and Brotli?

Both compress text, but Brotli usually produces smaller files for web content, helped by a built-in dictionary of common web text. Gzip is older, universal, and very fast. Brotli at high settings compresses more but takes longer, so it suits static assets compressed once and served many times.

Does compression help with images and video?

No — and you should not apply it. JPEG, PNG, MP4, and WebP are already compressed, so gzip or Brotli over them wastes CPU and can slightly enlarge them. Content encoding is for text: HTML, CSS, JavaScript, JSON, SVG, and fonts.

What is Accept-Encoding?

A request header in which the browser lists the compression schemes it can decode — gzip, br for Brotli, zstd. The server picks one it supports, compresses with it, and reports the choice in Content-Encoding. If none match, the response is sent uncompressed.

Does compression slow down the server?

It costs some CPU, but for text the network savings almost always outweigh it. Static files are compressed once at the highest setting and cached; dynamic responses are compressed at a lower, faster setting on the fly to balance CPU against bandwidth.

Related Guides

More From This Section