How to check if gzip is enabled

Ask for gzip and read the header: curl -s -H 'accept-encoding: gzip' -D - -o /dev/null https://example.com/. A content-encoding: gzip line means the server compressed the body. Then request the same URL with accept-encoding: identity and compare %{size_download}, because the header alone never tells you how many bytes it saved.

Checker offline. Follow the manual steps below, they give the same answer.

Why check this

Compression is a server configuration, so it survives no deployment by itself. A release that moves a route behind a new reverse proxy, or a rewrite that starts serving HTML from an application server instead of the CDN, turns gzip off for that route while every other route stays compressed. Run this on staging sign-off for each content type the release touched. The failure it prevents is a page that ships at four times its usual weight and shows up two weeks later as a mobile timeout report with no code change to blame.

Prerequisites

Steps

  1. Step 1.

    Ask for gzip only, and print the response headers without the body.

    curl -s -H 'accept-encoding: gzip' -D - -o /dev/null https://www.cloudflare.com/ | grep -i -E '^HTTP|content-encoding|vary'
    
    HTTP/2 103
    HTTP/2 200
    vary: accept-encoding
    content-encoding: gzip

    The 103 line is an early hints response. Read the headers under the 200.

  2. Step 2.

    Measure the uncompressed body. identity is the token for "send it raw".

    curl -s -o /dev/null -H 'accept-encoding: identity' -w '%{size_download}\n' https://www.cloudflare.com/
    
    1317143
  3. Step 3.

    Measure the same body with gzip. %{size_download} counts bytes off the wire, so this is the compressed size.

    curl -s -o /dev/null -H 'accept-encoding: gzip' -w '%{size_download}\n' https://www.cloudflare.com/
    
    294577

    1317143 against 294577 is a ratio of 4.5 to 1 for this HTML document. Expect the number to move by a few hundred bytes between runs, because the origin recompresses each response.

  4. Step 4.

    Run the negative control. A route with no compression answers the same request like this.

    curl -s -H 'accept-encoding: gzip' -D - -o /dev/null https://httpbin.org/html | grep -i -E '^HTTP|content-encoding|content-length'
    
    HTTP/2 200
    content-length: 3741

    No content-encoding at all. That is the shape of a failure, and knowing it stops you reading an empty grep as a broken command.

How to read the result

| What you see | What it means | What to do | | --- | --- | --- | | content-encoding: gzip and the byte count drops | gzip is on for this route | Nothing. Record the ratio so the next release has a baseline. | | No content-encoding, byte counts equal | The route is uncompressed | Check the route, not the whole service. Compression is usually per location block. | | content-encoding: br | The server preferred brotli | gzip may still be configured. Ask for gzip alone, as in step 1. | | Header present, byte counts equal | A proxy sets the header without compressing | Report it. Clients that decode the body will fail on the raw bytes. | | content-encoding: gzip on a JPEG or a ZIP | Wasted CPU on both ends | Exclude the type at the server. The body gets no smaller and often grows. |

Common mistakes

Sign: curl reports a large byte count even though the header says gzip.Cause: The measurement used --compressed, which makes curl decode the body. %{size_download} then reports the wire bytes while the file you saved holds the decoded bytes, and mixing the two numbers gives a ratio of 1 to 1. Send an explicit accept-encoding header instead.
Sign: The home page is compressed and an API route is not, on the same host.Cause: gzip is configured per location and per MIME type. A default configuration that lists text/html and text/css will not touch application/json, so every JSON response leaves uncompressed while the page that loads it looks fine.
Sign: A test that passed last week now shows no compression, with no deploy in between.Cause: The earlier response came from a CDN edge that compressed on its own. A cache purge sends the next request to an origin that never had gzip on, and the defect was there the whole time.

Thresholds

4.5 to 1 on the Cloudflare home page HTML, 1317143 bytes raw against 294577 bytes gzipped Source: Measured with curl 8.21.0 on 2026-09-11, see the Verified block
nginx ships with gzip off, and gzip_min_length defaults to 20 bytes once it is on Source: https://nginx.org/en/docs/http/ngx_http_gzip_module.html

What to check next

FAQ

How much does gzip compress a page?

On the Cloudflare home page measured here, 1317143 bytes fell to 294577, a ratio of 4.5 to 1. HTML and JSON with repeated markup compress hardest. Minified JavaScript lands nearer 3 to 1. Measure your own document rather than quoting a ratio.

How to test gzip compression with curl?

Steps 1 to 3 are the test. Send accept-encoding: gzip, read content-encoding, then repeat with accept-encoding: identity and compare %{size_download}. Two numbers and one header line settle it.

How to check gzip compression in Chrome?

Open DevTools, Network tab, click the request, then the Headers panel for content-encoding. The Size column shows transferred bytes over decoded bytes. A DevTools capture of the MDN CORS page on this machine read 30865 bytes transferred against 258732 decoded.

How to check if an API supports gzip?

Send the same header to the API route. Compression on the HTML does not imply it on JSON. https://httpbin.org/json returned content-length: 429 with no content-encoding when asked for gzip, which is what an uncompressed API looks like.

Verified

Verified by Maks Vernycurl 8.21.0

Each output block is what the command above it printed on that date, on the host named in the step. Figures read from a live site move between runs. Compare the shape of the answer rather than the digits, and see the methodology for how a page is re-verified.

basic4 minpublished updated Maks Verny