design
Base64 Encoding Explained: When and Why Developers Use It (and the Traps)
What Base64 does (3 bytes to 4 ASCII chars, +33% size), the real use cases (data URIs, JWT, Basic auth), and the traps: it is not encryption and not compression.
Published 2026-06-11 · 8 min read
Affiliate disclosure
Some links below are affiliate links. I may earn a commission from qualifying purchases at no extra cost to you. I only recommend tools I have used or tested.

TL;DR
- Base64 is an encoding, not encryption and not compression. It rewrites arbitrary bytes using only 64 printable ASCII characters so binary data can ride through text-only channels.
- The mechanics: every 3 bytes become 4 characters (6 bits each), padded with
=, which is why the output is about +33% larger than the input (RFC 4648, MDN).- Real uses: data URIs (inline images in CSS/HTML), email MIME attachments, binary inside JSON/XML, HTTP Basic auth headers, and JWT segments (which use Base64URL).
- The traps: Base64 is trivially reversible (never a security layer), the +33% tax makes it wrong for large files over the wire, and
btoa()chokes on non-ASCII because it speaks Latin-1, not UTF-8.- You can encode/decode either flavor in the AnyTools Base64 tool — runs in your browser, nothing leaves your device.
You keep seeing it — so what is it?
You see a long run of letters, digits, and a couple of = signs at the end (in a JWT, a config file, a data: URL, a copied auth header) and something in your head goes "Base64." But what does it actually buy you, and why is it everywhere?
Short answer: Base64 rewrites arbitrary binary data using only 64 safe, printable ASCII characters, so the bytes can travel through text-only channels without getting corrupted. It is not a secret code. It is not a zip. It is a transport costume. This guide is the dev-to-dev version: the exact mechanics, where it earns its keep, and the places people reach for it wrong.
What does Base64 actually do?
Base64 is defined by RFC 4648. The alphabet is 64 characters: A–Z, a–z, 0–9, plus + and /. A 65th character, =, is used only for padding.
The transform is purely mechanical. Per RFC 4648 §4, the encoder takes input in 24-bit groups (3 bytes × 8 bits) and emits 4 output characters, each carrying 6 bits. That 3-into-4 ratio is the whole story, and it has one unavoidable consequence that MDN spells out: the encoded form is roughly a third larger than the source — about +33%, the 4/3 ratio. If your input length is not a clean multiple of 3, the last group is padded so the output is a multiple of 4. That is why some strings end in one or two =.
A worked example, which you can reproduce in the Base64 tool:
"Hi" → 2 bytes → "SGk=" (one byte short of a group → one "=")
"Hello, World!" → 13 bytes → "SGVsbG8sIFdvcmxkIQ=="
Two things follow from the mechanics, and they matter more than the math:
- It is fully reversible with no key. Decoding is the same table run backwards. No secret is involved, which is the source of the single biggest misconception below.
- It costs size, not security. You spend ~33% to gain text-safety: great for a 200-byte token, terrible for a 10 MB file.
There is also a sibling worth knowing: Base64URL (RFC 4648 §5). Same encoding, but it swaps + for - and / for _ and usually drops the = padding, so the result is safe inside URLs, filenames, and JWT segments.
Where does Base64 actually earn its keep?
Every legitimate use of Base64 is the same shape: binary data needs to live inside something that only accepts text. Here is where that happens in practice.
- Data URIs. Inline a small icon directly in CSS or HTML:
background: url("data:image/svg+xml;base64,PHN2Zy…"). The image bytes become part of the text stylesheet, saving an HTTP request — worth it only for assets under ~1–2 KB, because the +33% tax rides along in every page that loads the stylesheet. - Email attachments (MIME). This is why Base64 exists. Email transport was built for 7-bit text, so binary files are Base64-wrapped to survive intact.
- Binary inside JSON / XML. JSON has no native binary type. To put a small blob (a thumbnail, a signature, a certificate) into a JSON field, you Base64 it into a string the parser will carry.
- HTTP Basic auth. The
Authorization: Basic …header is literallyusername:passwordBase64-encoded. Note encoded: Basic auth offers zero confidentiality on its own and relies entirely on HTTPS. The Base64 is framing, not protection. - JWT segments. A JSON Web Token is
header.payload.signature, each part Base64URL-encoded JSON. You can paste the middle segment into a decoder and read every claim, which is why you must never put secrets in a JWT payload.
For the URL-bound cases, Base64 often sits next to a different encoding. If you are hand-assembling a URL that carries an already-Base64 value, the +, /, and = still need to be made URL-safe: either use Base64URL up front, or run the URL through percent-encoding so those characters survive the query string. And when you need a unique text identifier rather than encoded bytes, a UUID generator is the right tool — UUIDs are identifiers, not a way to encode payloads.
When should you NOT use Base64?
This is the decisive section. Base64 is overused in exactly three ways, and each one is a real bug waiting to happen.
1. It is encoding, not encryption, so never use it for security. This is the cardinal sin. Base64 has no key; it is reversible by anyone in one step. A password, an API key, or a token "stored as Base64" is stored in plaintext; the encoding only changes which characters appear, as MDN notes. If you need confidentiality, encrypt. If you need to store credentials, hash them with bcrypt, scrypt, or argon2.
2. It is the wrong tool for large files over the wire. Because of the hard +33% size cost, Base64-inlining a big image or shipping a multi-megabyte file as a JSON string wastes bandwidth and forces the whole thing to be decoded in memory at once. For anything beyond small assets, send the binary properly (a real upload via multipart/form-data, or a binary HTTP body) and reference it by URL. Inline data URIs are for favicon-sized assets, not the hero image.
3. It is not compression. Base64 makes data bigger, never smaller. To shrink a payload, you want gzip/brotli. People sometimes Base64 a blob "to make it portable" and accidentally inflate it.
Here is the quick decision table.
| Situation | Base64 it? | Why |
|---|---|---|
| Icon inlined in CSS/HTML, under ~1–2 KB | ✅ Yes | Saves an HTTP request; +33% is negligible at that size |
| Asset larger than a few KB | 🚫 No | +33% inlined into every page beats the saved request; use a normal file request |
| Binary blob in a JSON/XML field | ✅ Yes | JSON has no binary type; text is the only option |
| Value going into a URL or JWT | ✅ Yes — Base64URL | + / = are unsafe in URLs; URL-safe alphabet fixes it |
| Storing a password or API key | 🚫 No | Reversible — that is plaintext. Hash or encrypt instead |
| Sending a 5 MB image to a server | 🚫 No | +33% tax; use a real binary upload and a URL |
| Trying to shrink a payload | 🚫 No | Base64 grows data; use gzip/brotli |
And a one-line reference for the encodings that get confused with each other:
| Encoding | Alphabet / form | Built for |
|---|---|---|
| Base64 | A–Z a–z 0–9 + /, = padding | Binary → ASCII text (email, JSON, data URIs) |
| Base64URL | +→-, /→_, no padding | Binary → text that is safe in URLs / filenames / JWT |
| URL (percent) encoding | %XX for unsafe chars | Making text safe inside a URL — different problem |
| Hex | 0–9 a–f, 2 chars/byte | Human-readable bytes; +100% size, simpler than Base64 |
How do you encode and decode it the right way?
You can do this in your browser without npm.
- Open the AnyTools Base64 tool. It runs entirely client-side — your input never leaves your device.
- Encode: paste text or bytes, get the Base64 string. Toggle URL-safe if the value is headed for a URL, filename, or JWT — you will get
-/_and no=padding. - Decode: paste a Base64 (or Base64URL) string to recover the original. The tool auto-detects the flavor, so you do not have to know which one you were handed.
- Non-ASCII just works. The tool UTF-8-encodes first, so emoji, accented Latin, Vietnamese, and Arabic round-trip cleanly — none of the
btoa()InvalidCharacterErroryou would hit on世界or🌏.
If you are doing this in code instead, the browser's native btoa()/atob() speak Latin-1, not UTF-8, so wrap TextEncoder/TextDecoder around them for anything outside basic ASCII, per MDN.
The honest verdict
Base64 is one of the most useful boring tools in the stack, and almost every problem with it comes from forgetting what it is. It is a transport encoding: arbitrary bytes into 64 safe ASCII characters at a fixed +33% size cost, so binary can ride through text-only channels like email, JSON, URLs, and headers. Reach for it for data URIs, MIME, blobs in JSON, Basic auth, and JWT (URL-safe variant). Do not reach for it as security (keyless and reversible), for large files over the wire (the size tax bites), or as compression (it grows data, never shrinks it).
Keep one sentence in your head, transport encoding, not a vault and not a zip, and you will use it correctly every time. Reach for the Base64 tool when you need to read a JWT claim, inline a sub-2 KB icon, or sanity-check an encoded value; reach for a real binary upload (multipart/form-data) the moment the asset is more than a few KB. It runs in your browser, both flavors — the text you paste is never sent to a server.
Disclosure: this article may contain affiliate links; anytools may earn a commission at no cost to you.
Sources
- IETF: RFC 4648 — The Base16, Base32, and Base64 Data Encodings
- IETF: RFC 4648 §5 — Base64 URL- and filename-safe alphabet
- MDN: Base64 (Glossary) — encoding, 6 bits per digit, ~33% size increase
- MDN: Window.btoa() — Base64 encoding in the browser
- MDN: Window.atob() — Base64 decoding in the browser
- IETF: RFC 7519 — JSON Web Token (JWT), Base64URL-encoded segments