What Is Text Compression (Brotli & gzip)? Complete Guide (2026)

Saar Twito8 min read
Saar Twito
Saar TwitoFounder & SEO Engineer

Hi, I'm Saar - a software engineer, SEO specialist, and lecturer who loves building tools and teaching tech.

View author profile →

What Is Text Compression?

Text compression refers to gzip or Brotli compression applied to text-based resources (HTML, CSS, JavaScript, JSON, SVG) before they're sent to the browser. Audits flag any text resource over 1.4 KB served without a Content-Encoding: gzip or Content-Encoding: br response header. Brotli typically shrinks text by 70–80%, gzip by 60–75% — same code, far less network time.

Key Facts (TL;DR)

  • Audit threshold: any text resource > 1.4 KB without a Content-Encoding header is flagged.
  • Brotli savings: typically 70–80% reduction on HTML/CSS/JS.
  • gzip savings: typically 60–75% reduction — slightly less than Brotli at equivalent CPU cost.
  • Brotli vs. gzip ratio: Brotli generally compresses text 15–25% smaller than gzip. Brotli level 4 ≈ gzip level 6 in compression ratio.
  • Browser support: all modern browsers support Brotli over HTTPS. gzip is supported everywhere as the universal fallback.
  • Performance impact: a 200 KB uncompressed JS file becomes ~50 KB Brotli-compressed — 4× less network time, with direct improvements to TTFB, FCP, and LCP.

Think of text compression like vacuum-sealing clothes for travel. Same shirts, same fit when unpacked — but a quarter of the volume in the suitcase. Brotli and gzip do the same thing for HTML, CSS, and JS: identical output in the browser, a fraction of the bytes on the wire.

Why Uncompressed Text Files Slow Down Every Page Load

Text resources (HTML, CSS, JS) sit at the front of the critical path — the browser cannot render or become interactive until they arrive and parse. Shipping them uncompressed amplifies every other performance problem:

  • Slower TTFB and FCP: The HTML document is the first byte the browser receives. Compressing it cuts the time-to-first-byte for the rest of the page.
  • Slower LCP: Render-blocking CSS and JS must arrive before the largest contentful paint can occur. Compressed text means less network time and earlier LCP.
  • Mobile data costs: Visitors on metered plans pay for every kilobyte. Saving 70% on text resources is a real cost saving, not just a speed metric.
  • CDN egress bills: Compressed responses cost less to serve. At scale, enabling Brotli on a high-traffic site routinely cuts text egress in half.
  • Search rankings: Slower TTFB and LCP hurt Core Web Vitals, which are confirmed ranking signals. Skipping compression is one of the cheapest performance wins to leave on the table.

How Audits Detect Missing Compression

The audit reads each response's Content-Encoding header. Any text response over 1.4 KB without gzip, br, or deflate in that header is flagged. Worked example for a typical missing-compression report:

Resource             Original   Encoded    Savings
-------------------- ---------- ---------- ----------
/index.html             56 KB      —         flagged
/styles/main.css        82 KB      —         flagged
/js/app.bundle.js      612 KB      —         flagged
/api/products.json     140 KB      —         flagged
/icons/logo.svg          8 KB      —         flagged
-------------------- ---------- ---------- ----------
Total                  898 KB

Estimated transfer with Brotli:    ~210 KB
Estimated savings:                 ~688 KB (77% smaller)

On this page, enabling Brotli alone removes nearly 700 KB from the transfer — roughly the difference between a passing and failing Total Byte Weight audit.

What Gets Compressed (and What Doesn't)

Compress these: HTML, CSS, JavaScript, JSON, SVG, plain text, XML, RSS, source maps — basically all text/* and most application/* text-based MIME types.

Do NOT compress these:JPEG, PNG, WebP, AVIF, video (MP4, WebM), woff2 fonts, MP3/AAC. They're already compressed internally — re-running gzip or Brotli over them costs CPU, doesn't reduce size, and can occasionally make the response slightly larger.

Brotli vs. gzip: Which Should You Use?

Both. Modern servers and CDNs negotiate compression based on the browser's Accept-Encoding request header — they serve Brotli to clients that support it and fall back to gzip for everyone else.

AspectgzipBrotli
Typical text savings60–75%70–80%
Ratio comparisonBaseline~15–25% smaller output than gzip at equivalent CPU
Browser supportUniversal (every HTTP client)All modern browsers, HTTPS only
Compression speedFast at low levelsSlower at level 11; level 4–6 is comparable to gzip 6
Decompression speedVery fastComparable to gzip
Best useUniversal fallback for older clientsDefault for modern HTTPS traffic

Practical rule: enable Brotli at level 4–6 for dynamic responses (HTML), pre-compress static assets (CSS/JS) with Brotli at level 11 once at build time, and keep gzip enabled as the fallback.

How to Check If Compression Is Working

You don't need a full audit to verify — a single curl command does it:

  • Greadme deep scan — surfaces every uncompressed text resource on the page, broken down by file, and pairs each finding with an AI-generated server-config fix or one-click GitHub PR.
  • Greadme crawler scan — checks compression coverage across every indexable URL on your site, so you can spot specific routes (often API endpoints or JSON responses) that slip through.
  • Chrome DevTools → Network tab — click any request and look at "Response Headers" for content-encoding: br or content-encoding: gzip. The "Size" column shows transferred vs. resource size.
  • Google Search Console — slow TTFB and LCP on the Core Web Vitals report often trace back to missing compression on the HTML document.

For a one-line CLI check:

# Verify Brotli is active for a JS file
curl -I -H "Accept-Encoding: br" https://yoursite.com/main.js \
  | grep -i content-encoding

# Expected output:
# content-encoding: br

# If you see no header at all, compression isn't enabled.
# If you see "content-encoding: gzip", Brotli isn't configured
# but the gzip fallback is — still good, but not optimal.

8 Ways to Enable and Optimize Text Compression

1. Turn On Brotli at Your CDN Edge

Most CDNs offer Brotli as a single toggle. Enabling it at the edge means responses are compressed once and cached, so origin CPU is unaffected. This is the highest-leverage change on most sites — often a five-minute job.

2. Enable Brotli + gzip in Nginx

If you serve from your own origin, configure both Brotli and gzip so every browser gets the best option it supports.

# /etc/nginx/conf.d/compression.conf

# gzip (universal fallback)
gzip on;
gzip_comp_level 6;
gzip_min_length 1024;
gzip_vary on;
gzip_types
  text/plain text/css text/xml
  application/javascript application/json
  application/xml application/rss+xml
  image/svg+xml;

# Brotli (modern browsers, HTTPS)
brotli on;
brotli_comp_level 5;
brotli_min_length 1024;
brotli_types
  text/plain text/css text/xml
  application/javascript application/json
  application/xml application/rss+xml
  image/svg+xml;

3. Enable mod_deflate and mod_brotli in Apache

On Apache, the equivalent modules are mod_deflate (gzip) and mod_brotli. Both ship with most modern distributions.

# httpd.conf or .htaccess
<IfModule mod_brotli.c>
  AddOutputFilterByType BROTLI_COMPRESS \
    text/html text/plain text/css text/xml \
    application/javascript application/json \
    application/xml image/svg+xml
</IfModule>

<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE \
    text/html text/plain text/css text/xml \
    application/javascript application/json \
    application/xml image/svg+xml
</IfModule>

4. Compress JSON API Responses

JSON is the format most often missed. API endpoints frequently skip compression because backend frameworks default to off. Add the JSON MIME types (application/json, application/vnd.api+json) to your compression config — payloads typically shrink 80%+.

5. Pre-Compress Static Assets at Build Time

For static CSS and JS, run Brotli at maximum quality once during the build and serve the precompressed file directly. The runtime CPU cost is zero, and the compression ratio is better than on-the-fly.

# Generate .br and .gz alongside each output file
brotli -q 11 dist/main.js          # creates main.js.br
gzip  -9 -k dist/main.js           # creates main.js.gz

# Nginx: serve pre-compressed file when client supports it
location ~* \.(js|css|svg|json)$ {
  brotli_static on;
  gzip_static   on;
}

6. Skip Already-Compressed Formats

Don't add JPEG, PNG, WebP, MP4, or woff2 to your compression MIME-type list. Brotli or gzip on already-compressed binary saves nothing and wastes CPU. Keep the list strictly to text-based MIME types.

7. Set a Sensible Minimum Size

Compressing a 200-byte response is pure overhead — the compressed output may even be slightly larger because of the format's framing bytes. Set gzip_min_length / brotli_min_lengthto around 1024 bytes (1 KB). The audit threshold is 1.4 KB anyway, so anything smaller wouldn't be flagged.

8. Confirm the Header Is Sent (and Cached)

After enabling compression, run the curl command from the previous section against five or six representative URLs (homepage, an API endpoint, a CSS file, a JS bundle, an SVG, and a 404). All should return content-encoding: br for Brotli-capable clients. Also verify your Vary: Accept-Encoding response header so caches store one copy per encoding.

Common Compression Problems and Fixes

Problem: HTML Compressed but JSON API Responses Aren't

What's happening: The web server compresses static assets, but a backend application server returns JSON without a Content-Encoding header.

Fix: Add application/json to your gzip_types / brotli_types list, or enable compression middleware in the app framework itself (most Node.js, Python, and Go frameworks ship one).

Problem: Compression Disabled by a Proxy or Load Balancer

What's happening: Your origin sends compressed responses, but a reverse proxy or load balancer in front of it strips Accept-Encoding from the request — so the origin sees no encoding offered and replies uncompressed.

Fix: Configure the proxy to forward Accept-Encoding upstream, or enable compression at the proxy itself.

Problem: Cache Stores Compressed Response and Serves It to Clients That Can't Decode

What's happening: A shared cache stores a Brotli-encoded response and later serves it to a client that didn't advertise Brotli support.

Fix: Set Vary: Accept-Encoding on every compressed response so caches store one variant per encoding. Most modern servers do this automatically; verify with a header check.

Problem: Double-Compression at CDN and Origin

What's happening: The origin compresses with gzip, the CDN re-compresses with Brotli, and the response ends up oddly large or breaks decoding.

Fix: Compress in exactly one place. The cleanest pattern is to pre-compress static assets at build time and let the CDN handle dynamic HTML compression — disable origin-side compression for anything the CDN re-encodes.

Compression Thresholds and Targets

StatusContent-Encoding HeaderTypical Text SavingsAudit Result
Optimalbr (Brotli)70–80%Pass
Goodgzip60–75%Pass
Acceptable for legacydeflate55–70%Pass
Failing(none)0%Flagged for any text resource > 1.4 KB

FAQ

What is the audit threshold for text compression?

Any text resource larger than 1.4 KB served without a Content-Encoding: gzip, br, or deflateresponse header is flagged. Files under 1.4 KB aren't flagged because the per-response framing overhead of compression isn't worth the savings on tiny payloads.

Should I use Brotli or gzip?

Both. Modern servers and CDNs negotiate per request: they serve Brotli to clients that advertise br in Accept-Encodingand fall back to gzip for everyone else. Brotli compresses text 15–25% smaller than gzip at comparable CPU cost, so it's the preferred default for HTTPS traffic.

Is text compression a Google ranking factor?

Not directly — but it strongly improves TTFB, FCP, and LCP, all of which feed Core Web Vitals. LCP is a confirmed ranking signal, and skipping compression is one of the easiest ways to fail it. In practice, enabling Brotli is one of the cheapest SEO performance wins available.

Will compression hurt my server's CPU?

At sane levels (Brotli 4–6, gzip 6) the CPU cost is small and almost always dwarfed by the network savings. For static assets, pre-compress once at build time (Brotli level 11) and the runtime cost drops to zero. CDNs handle this automatically when you toggle Brotli on — origin CPU isn't affected.

What about compressing images, video, or fonts?

Don't. JPEG, PNG, WebP, AVIF, MP4, WebM, and woff2 are already compressed internally. Re-running gzip or Brotli over them spends CPU for zero (or negative) savings. Keep your compression MIME-type list strictly to text formats: HTML, CSS, JS, JSON, SVG, XML, plain text.

Does text compression matter for AI search engines like ChatGPT and Perplexity?

Indirectly, yes. AI-driven systems (Google AI Overviews, generative answer engines) preferentially cite pages that already rank well in traditional search. Slow TTFB and LCP from missing compression hurt Core Web Vitals → hurt rankings → reduce your odds of being chosen as a citation. Compressed pages compete better in both surfaces.

How do I know if my site is already using compression?

Run curl -I -H "Accept-Encoding: br, gzip" https://yoursite.com/ and look for a content-encoding line in the response headers. br means Brotli is active, gzip means gzip-only, no header means compression isn't configured. For a full per-resource breakdown across every page on your site, run a Greadme deep scan.

Conclusion

Text compression is the rare optimization with no downside: identical output in the browser, 70–80% fewer bytes on the wire, faster TTFB, faster LCP, and lower CDN bills. Modern servers and CDNs ship it as a single toggle. If your audit flags "Uses Text Compression," this is the highest-leverage fix you can ship today.

Run a Greadme deep scan to see exactly which text resources are uncompressed on your site, then enable Brotli at the edge and gzip as a fallback. Verify with one curl call. Most sites get a measurable Core Web Vitals improvement from this change alone.