How Base64 Encoding Works
Base64 converts binary data into 64 printable ASCII characters:
- A-Z (26 characters)
- a-z (26 characters)
- 0-9 (10 characters)
- + and / (2 characters)
- = for padding
Common Use Cases
Data URLs
``html
`HTTP Basic Authentication
`
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
`JSON Data Storage
When you need to store binary data in JSON, Base64 encoding allows safe text representation.URL-Safe Base64
Standard Base64 uses + and / which have special meaning in URLs. URL-safe Base64 replaces these with - and _.
What Base64 Actually Does
Base64 maps arbitrary binary data onto 64 printable ASCII characters, so it can pass
through systems that only handle text. It takes three bytes at a time — 24 bits — and
re-cuts them into four 6-bit groups, each becoming one character from
A–Z, a–z, 0–9, +, /.
Three bytes in, four characters out. That is where the 33% size increase comes from,
and it is unavoidable: 4 ÷ 3 = 1.333.
| Input bytes | Output characters | Padding |
|---|---|---|
| 3 | 4 | none |
| 2 | 4 | = |
| 1 | 4 | == |
The = padding exists so a decoder knows how many bytes the final group really held. Some
decoders accept unpadded input and some reject it, which is a common source of "invalid
base64" errors on values that look fine.Encoding Is Not Encryption
This is worth stating plainly because it is the most consequential misunderstanding about
the format. Base64 is a reversible, keyless transformation that anyone can undo in one
line. A password, an API key or a token that is "base64 encoded" is stored in plaintext
with an extra step.
HTTP Basic authentication sends base64(user:password) on every request. That is not a
security measure — it is a transport measure — which is why Basic auth over plain HTTP
transmits a readable password, repeatedly.
When It Earns Its Cost
The 33% overhead is worth paying when a system genuinely cannot carry binary:
Email attachments. MIME is a text protocol; this is what Base64 was designed for.Data URIs. Inlining a small icon asdata:image/png;base64,…removes an HTTP request.- JSON payloads. JSON has no binary type, so bytes travel as a Base64 string.
- JWTs and certificates. Base64url in tokens, PEM armour around DER certificates.
- Copy-pasteable blobs. Anything a human has to move through a terminal or a form.
It is the wrong choice for anything large. A 5MB image becomes 6.7MB of text that cannot be
cached separately, cannot be served with its own compression, and blocks the document it is
embedded in. Inline below roughly 4KB; link above it.Standard Base64 and Base64url
Two of the 64 characters are hostile to URLs: + means a space in form encoding and /
is a path separator. Base64url swaps them and usually drops the padding:
| Standard | Base64url | |
|---|---|---|
| Index 62 | + | - |
| Index 63 | / | _ |
| Padding | = required | Usually omitted |
Feeding standard Base64 to a Base64url decoder — or the reverse — fails on any input
containing those two characters, which is roughly one string in eight. If a token decodes
in your test and fails in production, this is the first thing to check.Which Tool to Use
[Encode text](/dev/base64-encoder/base64-text-encoder) for the standard alphabet.- [Decode](/dev/base64-encoder/base64-to-text-decoder) to read a value back.
- [Base64url](/dev/base64-encoder/base64-url-encoder) for anything going into a URL, a
cookie, or a JWT.Unicode Needs Care in the Browser
btoa() throws on any character above U+00FF, because it operates on a byte string rather
than on text. Encode to UTF-8 first:
`javascript
const encode = (s) => btoa(String.fromCharCode(...new TextEncoder().encode(s)));
const decode = (b) => new TextDecoder().decode(
Uint8Array.from(atob(b), (c) => c.charCodeAt(0)),
);
`
Skipping that step is why btoa('café') fails while btoa('cafe')` succeeds.