How to gzip and Base64 encode
- Type or paste text into the input, or drop a file. Live is on, so the output updates as you type.
- Keep Format on gzip. zlib, raw deflate and, where the browser supports it, Brotli are in the same list.
- Tick URL-safe (- _) if the string goes into a URL or a filename, or Wrap at 76 for email and PEM-style line lengths.
- Copy output, Download the Base64 as a
.txtfile, or Download compressed file to save the binary.gz.
The meta line shows input size, compressed size, Base64 size and ratio, and the status says how much shorter or longer the result is than plain Base64 of the same input.
When compressing first is worth it
Base64 always grows data by a third. On data with repetition, gzip wins that back and more.
| Input | Plain Base64 | Gzip + Base64 |
|---|---|---|
Hello, world! (13 bytes) | 20 characters | 44 characters |
| A 9,281-byte JSON array of 100 product records | 12,376 characters | 1,096 characters |
| A JPEG photo | about 4/3 of the file | slightly longer than plain Base64 |
The figures were produced with gzip -6. The browser’s compressor can differ by a few bytes, and the meta line shows the exact numbers for your input. As a rule of thumb, inputs under about 100 bytes and anything already compressed are better off as plain Base64.
Where gzip + Base64 strings are used
- Cloud-init and VM user data: cloud-init detects gzip-compressed user data, which helps stay under the size limits of cloud metadata services.
- AWS CloudWatch Logs subscriptions deliver log batches to Lambda as Base64 of gzip in
awslogs.data. - Helm 3 stores each release as Base64 of gzipped JSON inside a Kubernetes Secret.
- Environment variables and JSON fields that must hold a config file or a large text blob.
- Query strings and deep links with a state object. Use URL-safe output there.
Apart from the H4sI prefix, nothing in the Base64 tells the receiver the data is gzip. Say so in the field name or the API docs, or, over HTTP, send the binary body with Content-Encoding: gzip instead of Base64.
Gzip + Base64 in code
import base64, gzip
data = open("products.json", "rb").read()
packed = base64.b64encode(gzip.compress(data, mtime=0)).decode()
// Node.js
const zlib = require("zlib");
const packed = zlib.gzipSync(Buffer.from(text)).toString("base64");
In browsers, new CompressionStream("gzip") does the compression, which is what this page uses. More examples are on the Python and Node.js pages.
Common problems
- The receiver gets garbage: it decoded the Base64 but did not gunzip. Check for
H4sIand decompress with the gzip Base64 decoder. - “incorrect header check” on the other side: the receiver expects zlib, not gzip. Switch Format to zlib (deflate); the zlib page explains which library expects which.
- Brotli is grayed out: the browser’s built-in compression API does not offer Brotli, and the page says so below the options.
- Output differs from another tool: gzip headers carry a timestamp and an OS byte, and compressors choose different levels. Different bytes can decompress to the same content.
FAQ
Does gzip before Base64 make a string shorter?
For text, JSON, XML and logs larger than a few hundred bytes, usually by a lot. For short strings and already compressed data (JPEG, PNG, ZIP, MP4) it makes the result longer, because gzip adds 18 bytes of header and trailer.
Why does every gzip Base64 string start with H4sI?
Gzip data starts with the bytes 1F 8B 08, and those three bytes are H4sI in Base64. The next characters depend on flags and timestamp: H4sIAAAAAAAA means no file name and no modification time.
How do I gzip and Base64 encode in the terminal?
On Linux: gzip -nc file.json | base64 -w0. On macOS, where base64 has no -w, use gzip -nc file.json | base64 | tr -d '\n'. The -n leaves out the file name and time, so the same input gives the same output.