Base64 turns every 3 bytes into 4 characters, so the encoded data is 33% larger. But each Base64 character carries only 6 bits of information in an 8-bit byte. Compression algorithms such as gzip (DEFLATE) and Brotli use Huffman coding, which spends fewer bits on frequent symbols, and they win back most of that waste.
What happens in practice
We measured it with Node.js zlib (gzip level 9 and Brotli defaults). The “already compressed” rows use random bytes, which behave like PNG, JPEG or MP3 data:
| Data | Raw | Base64 | gzip(raw) | gzip(Base64) | Brotli(Base64) |
|---|---|---|---|---|---|
| Compressed file, 1 KB | 1,024 B | 1,368 B | 1,047 B | 1,073 B | 1,054 B |
| Compressed file, 100 KB | 102,400 B | 136,536 B | 102,453 B | 102,875 B | 102,685 B |
| English-like text, 10 KB | 10,240 B | 13,656 B | 1,920 B | 2,663 B | 2,226 B |
Rule of thumb: for already-compressed formats, Base64 + gzip is within about 1–5% of the original size, because the Huffman stage removes the 6-of-8-bits redundancy. For compressible originals such as text, JSON or BMP, compressing the raw data is clearly better: in our test, gzip of the Base64 text was 39% larger than gzip of the text itself.
Why it is not exactly zero
DEFLATE finds repeated sequences byte by byte. Base64 splits input bytes across character boundaries, so a repetition in the original appears in the encoded text only when it is aligned to the same 3-byte offset. Compression therefore finds fewer matches in Base64 than in the original binary.
Takeaways
- Always enable gzip or Brotli on HTML, CSS, JS and JSON that contain Base64. Check yours with the gzip test.
- Compress first, then encode, when you control both ends (for example
gzip | base64in scripts). - Never inline large resources just because “gzip fixes it”: inlined data still has to be downloaded and parsed before rendering.
Comments (0)
Questions, ideas or a bug in “Base64 and gzip compression”? Leave a comment, rate the tool, or reply to others.
No comments yet. Be the first to share your feedback!