Skip to content

/flags/http/curl-compressed

curl --compressed: request gzip, br or zstd and decompress the response

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · curl 8.21.0 (x86_64-w64-mingw32) libcurl/8.21.0 Schannel zlib/1.3.2updated
tool
HTTP
command
curl
flag
--compressed
default
off (curl sends no Accept-Encoding header, and servers that follow RFC 9110 send the body uncompressed)

curl --compressed URL adds an Accept-Encoding header listing every compression algorithm the curl build supports and transparently decompresses the response, so the output is the same as without compression but fewer bytes cross the network. Without the option curl asks for nothing, so a well-behaved server answers uncompressed. Use it to see what a browser actually receives, to test that a server or CDN compresses responses, and to save bandwidth on large text downloads.

Without and with --compressed

A local server compresses only when the request asks for gzip. %{size_download} reports the bytes received on the wire:

bash
cat > server.js <<'EOF'
const http = require('http'), zlib = require('zlib');
const body = JSON.stringify({ items: Array.from({ length: 50 }, (_, i) => ({ id: i, name: 'item ' + i })) }) + '\n';
http.createServer((req, res) => {
  res.setHeader('Vary', 'Accept-Encoding');
  if (/\bgzip\b/.test(req.headers['accept-encoding'] || '')) {
    res.setHeader('Content-Encoding', 'gzip');
    return res.end(zlib.gzipSync(body));
  }
  res.end(body);
}).listen(5414, '127.0.0.1');
setTimeout(() => process.exit(0), 6000);
EOF
node server.js &
sleep 1
curl -s -o plain.json -w 'without: %{size_download} bytes received\n' http://127.0.0.1:5414/
curl -s --compressed -o comp.json -w 'with:    %{size_download} bytes received\n' http://127.0.0.1:5414/
cmp plain.json comp.json && echo "saved files are identical"
curl -s -H 'Accept-Encoding: gzip' http://127.0.0.1:5414/ | head -c 2 | od -An -tx1
wait

Output

without: 1342 bytes received
with:    278 bytes received
saved files are identical
 1f 8b

With --compressed the server sent 278 gzip bytes instead of 1,342, and curl wrote the same decompressed JSON. The last line shows the trap: setting Accept-Encoding: gzip by hand makes the server compress, but curl does not decompress, so the output starts with the gzip magic bytes 1f 8b.

What curl sends

The header depends on the libraries curl was built with. Check curl -V: libz enables deflate, gzip, brotli adds br, zstd adds zstd. A full build sends Accept-Encoding: deflate, gzip, br, zstd.

RequestServer sendscurl writes
No optionIdentity (uncompressed), per RFC 9110The body as received
--compressedOne of the listed encodings, or identityThe decompressed body
-H "Accept-Encoding: gzip"gzipCompressed bytes; nothing is decoded
--compressed with an unsupported server encodingFor example br on a build without brotlicurl fails with exit code 61 (CURLE_BAD_CONTENT_ENCODING)

Checking that a server compresses

Look at the response headers rather than the body: curl -s --compressed -o /dev/null -D - URL and check for Content-Encoding and Vary: Accept-Encoding. Vary tells caches to store one copy per encoding; without it a proxy may serve gzip to a client that cannot decode it. See show HTTP response headers for the header options.

Pitfalls

  • Content-Length is the compressed size. With --compressed the Content-Length header (and %{size_download}) count encoded bytes, not the size of the file you get.
  • -r ranges apply to the encoded body. Combining --compressed with a byte range asks for a slice of the compressed stream, which usually cannot be decoded on its own.
  • Transfer-Encoding is different. --tr-encoding asks for hop-by-hop compressed transfer encoding, which few servers support; --compressed is the content encoding every web server and CDN implements.
  • ETags may change. Servers often send a different (weak) ETag for compressed variants, which matters for conditional requests.

FAQ

Why does curl print binary garbage instead of JSON?

The server sent a compressed body (Content-Encoding: gzip) even though curl did not ask for it, or you added an Accept-Encoding header by hand. Use --compressed instead of the manual header so curl also decompresses the body.

Which encodings does --compressed request?

Only those the curl build supports. A build with zlib, brotli and zstd sends Accept-Encoding: deflate, gzip, br, zstd; curl -V lists them in the Features line (libz, brotli, zstd).

Does --compressed make the download smaller on disk?

No. The transfer over the network is smaller, but curl writes the decompressed body, so the saved file is identical to what an uncompressed request would give.

Sources