Base64: what it is for, and when it quietly costs you
It exists to move binary data through channels that only accept text. It is not compression, it is not security, and it makes everything about a third bigger.
Base64 turns arbitrary binary data into a string of 64 safe characters: A–Z, a–z, 0–9, plus + and /, with = as padding. It exists for one reason — some channels only carry text, and you need to send bytes through them anyway.
Why it exists
Email is the original case. SMTP was designed for 7-bit ASCII, and a great many mail systems historically mangled anything else: stripping the eighth bit, reinterpreting byte sequences as control characters, converting line endings. Sending a JPEG through that unchanged produced a corrupted JPEG.
Base64 solves it by using only characters that survive everything. Every attachment you have ever sent was Base64-encoded in transit.
The same reasoning applies wherever binary meets a text-only container: embedding an image in a CSS file, putting a certificate in a PEM file, carrying a payload in a JSON field, or putting claims in a JWT.
How it works, and why 33%
Base64 takes three bytes — 24 bits — and re-splits them into four 6-bit groups, each mapped to one of the 64 characters. Three bytes in, four characters out.
4 ÷ 3 = 1.333, so Base64 data is always about 33% larger than the original. That is not overhead that a better implementation could avoid; it is arithmetic. Six bits of information per 8-bit character means a quarter of every character is wasted.
The = padding at the end appears when the input length is not a multiple of three: one = for two leftover bytes, two for one.
What it is not
Not encryption. There is no key. Anyone can decode it. This is the single most consequential misunderstanding about Base64, and it recurs constantly — HTTP Basic authentication sends credentials as Base64, and people see the gibberish and assume it is protected. It is not; TLS is what protects it. A password Base64-encoded in a config file is a password in plain sight, and any Base64 decoder reads it instantly.
Not compression. It is expansion. If your goal is smaller, Base64 moves you in the wrong direction by a third.
Not a checksum. It carries no integrity information. Corrupt one character and you get different bytes out, silently, with no indication anything went wrong.
Base64url, and why your JWT will not decode
Standard Base64 uses + and /, both of which have meaning in a URL — + means a space in query strings, / is a path separator. So a URL-safe variant swaps them for - and _, and usually drops the = padding entirely.
This is why pasting a JWT segment into a strict standard Base64 decoder sometimes fails. JWTs use Base64url. A decoder that handles both — or converting the characters back by hand before decoding — resolves it.
Data URIs: the useful case with a real cost
You can embed a file directly in HTML or CSS:
<img src="data:image/png;base64,iVBORw0KGgoAAAANS...">
The browser decodes it inline. No separate request.
That is the entire benefit, and it used to matter a great deal: under HTTP/1.1 browsers allowed roughly six connections per host, so every request was contended. Inlining small images removed real latency.
Under HTTP/2 and HTTP/3 requests are multiplexed over one connection and cost very little. Meanwhile the costs of inlining did not change:
- 33% larger than the file it replaces.
- Uncacheable independently. An inlined image is re-downloaded with the CSS every time the CSS changes, and cannot be cached on its own.
- Render-blocking if it is in CSS. A 40 KB image inlined in a stylesheet is 40 KB the browser must download before it paints anything.
- Unreadable in source. A 3,000-character string where a filename used to be.
The reasonable rule now: inline only very small, unchanging assets — an icon under a couple of kilobytes, a 1×1 tracking pixel, a tiny SVG. Anything larger should be a file with a cache header. And for SVG specifically, inlining the markup directly beats Base64-encoding it, since SVG is already text and encoding it adds a third for nothing.
Where it genuinely belongs
- Email attachments — the original purpose, still correct.
- Binary in JSON. JSON has no binary type, so a small file in an API payload is Base64. For anything large, a URL to the file is better than the file.
- Certificates and keys. A PEM file is Base64-encoded DER with header and footer lines — which is what makes certificates copy-pasteable at all. Our certificate decoder unwraps them.
- Anything going into a URL or a filename — using Base64url, and remembering it is still not secret.
Two practical notes
Beware line breaks. The MIME variant of Base64 inserts a newline every 76 characters. Some decoders tolerate them, some do not. If a decode fails on data that came out of an email or a PEM file, stripping the whitespace is usually the fix.
Compress before encoding, never after. Base64 output is high-entropy text that gzip can do very little with. Gzipping a Base64 string typically recovers only part of the 33% you just added. If you need both, compress the binary first and encode the result.
Our encoder and decoder both run entirely in the browser — which matters more than usual here, because the things people Base64-decode are so often tokens, keys and certificates that have no business being pasted into someone else's server.
Tools mentioned in this guide
Base64 Encoder
Encode text or a file to Base64 in your browser, with URL-safe output, MIME line wrapping and ready-to-paste data URIs.
Base64 Decoder
Decode Base64 back to text or a file in your browser — accepts URL-safe input, missing padding and data URI prefixes.
URL Encoder
Percent-encode text for safe use in URLs and query strings, with separate modes for a single component or a whole URL.
JWT Decoder
Decode a JWT in your browser to read its header, payload and claims — with expiry dates worked out and dangerous headers flagged.
More guides
- Why your link looks wrong when you share it Without Open Graph tags, every platform guesses what your page is about — and they guess badly, cache the guess, and give you no obvious way to correct it.
- How to shrink a video enough to actually send it Every service has a different ceiling — 25 MB, 16 MB, 100 MB — and hitting it is not guesswork. Work backwards from the limit and the settings choose themselves.
- Why your page is slow, in the order worth checking Performance advice is usually a list of forty things. In practice four causes account for almost every slow page, and they have a natural order of investigation.