Base64 Encoding Explained — Why JWT, Data URIs and Email All Use It
Base64 isn't encryption — it's a way to safely move binary data through text-only channels. Here's what's actually happening and when to use it.
Base64 is one of those techniques you see all over the place — in JWT tokens, data URIs, email attachments, OAuth flows — without ever being told what it actually does or why. The mystery dissolves once you see the core idea: Base64 represents binary data using 64 printable characters. That's all.
Encode or decode now: the Base64 Encoder / Decoder converts text or files in either direction. URL-safe variant supported.
The problem Base64 solves
Computers store everything as binary (bytes — values 0-255). But many systems can only safely handle text — specifically, the printable ASCII range. Examples:
- Email was designed for 7-bit ASCII text. Binary attachments need a text representation.
- URLs only allow certain characters. Arbitrary binary data needs escaping.
- JSON and XML are text formats. Binary data inside them needs encoding.
- HTTP headers are mostly ASCII. Tokens that include random bytes need text-safe encoding.
Base64 solves all these by translating bytes into a 64-character alphabet that's safe in all these contexts.
How Base64 works
The 64-character alphabet:
- A-Z (26 characters)
- a-z (26)
- 0-9 (10)
- + and / (2)
6 bits gives 2^6 = 64 possible values, exactly matching the alphabet. Base64 takes 3 bytes (24 bits) and represents them as 4 characters (4 × 6 = 24 bits).
When the input isn't a multiple of 3 bytes, = padding fills the remainder. That's why Base64 strings often end with one or two equals signs.
Example: the string "Cat" (3 bytes: 67, 97, 116) encodes as "Q2F0" (4 characters).
Why Base64 is 33% bigger
Every 3 bytes of input becomes 4 bytes of Base64 output. That's a fixed 33% size increase. For a 1 MB binary file, Base64 produces ~1.33 MB of text. This overhead is the unavoidable cost of representing binary in text form.
When file size matters, send the binary directly (HTTP file uploads, S3, etc.) instead of Base64-encoding it inline.
Where Base64 shows up
1. Data URIs in CSS and HTML
background-image: url("data:image/png;base64,iVBORw0KGgo...");Embeds an image directly inside a CSS or HTML file. Useful for tiny icons (under 1 KB) where saving one HTTP request beats the 33% size penalty. Not useful for larger images.
2. JWT tokens
A JWT is three Base64URL-encoded segments joined by dots: header.payload.signature. Each segment is JSON encoded as Base64. The JWT Decoder reverses this in your browser.
3. Email attachments (MIME)
When you attach a PDF to an email, your email client Base64-encodes the file so it can travel through SMTP's text-only pipeline. This is why email attachments are larger than the original file — though most modern clients show the original size.
4. HTTP Basic auth
The classic Authorization: Basic dXNlcjpwYXNz header is just user:passBase64-encoded. This is encoding, not security — anyone can decode it. Always pair with HTTPS.
5. API tokens with binary
OAuth refresh tokens, CSRF tokens, and similar often include random bytes that need to be URL-safe and header-safe. Base64URL (variant — see next section) handles this.
URL-safe Base64 (Base64URL)
Standard Base64 uses + and /, which have special meaning in URLs. Base64URL replaces them with - and _, and often drops the =padding too.
Used in: JWTs, OAuth flows, anything embedded in a URL. The Base64 tool has a URL-safe toggle.
Base64 is NOT encryption
This is the single most important thing to know. Base64-encoded data is trivially reversible — anyone with a 5-line script can decode it. Never use Base64 to hide passwords, secrets, or sensitive data.
- Base64: encoding. Makes binary safe in text contexts.
- Encryption (AES, etc.): scrambles data so only the key holder can read it.
- Hashing (SHA-256): one-way function for verification, not retrieval.
The Hash Generator covers hashing. Encryption needs dedicated tools (libsodium, age, gpg) — not Base64.
Common pitfalls
- Forgetting padding. Some implementations strip the trailing
=. If you're decoding, add them back: pad to a multiple of 4 with=. - Confusing standard vs URL-safe. If you can't decode, try the other variant.
- Whitespace in Base64. Some encoders insert newlines every 76 characters (the MIME standard). Strip whitespace before decoding.
- UTF-8 handling.
btoa()in JavaScript can't handle Unicode directly. UseTextEncoderfirst to convert to bytes, then Base64-encode the bytes. - Treating it as data validation. Valid-looking Base64 doesn't mean the underlying data is valid. Always validate what you decoded.
JavaScript quick reference
// Text → Base64 (UTF-8 safe)
const text = "Hello, world! ñ ✨"
const utf8Bytes = new TextEncoder().encode(text)
const base64 = btoa(String.fromCharCode(...utf8Bytes))
// Base64 → Text
const decoded = atob(base64)
const bytes = new Uint8Array([...decoded].map(c => c.charCodeAt(0)))
const original = new TextDecoder().decode(bytes)
// URL-safe variant
const urlSafe = base64
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/, "")When to use Base64
Use it for:
- Embedding small binary data in text-based formats.
- Generating URL-safe random tokens.
- Working with JWTs and OAuth.
- Quick experimentation when you need to paste binary in chat or email.
Don't use it for:
- Hiding sensitive data — it's not encryption.
- Large files (use binary transfer, not Base64-inline).
- Anything performance-critical at scale (33% overhead adds up).
Convert anytime: Base64 Encoder / Decoder — text or file input, URL-safe variant toggle, UTF-8 safe. Pair with the URL Encoder when you need different escaping.