Base64: What It Is, When to Use It, and When Not To
Base64 encoding is misunderstood as encryption. It's not. Here's what it actually does and where it's legitimately useful.
Base64 appears in API docs, image data URIs, email attachments, and JWTs. Developers use it regularly without always knowing exactly what it does or why. Let's clear it up.
What Base64 Is
Base64 is an encoding scheme that converts binary data into a string of 64 safe ASCII characters: A–Z, a–z, 0–9, +, and /.
The name comes from the character set size: 64 possible characters.
It was designed to transmit binary data through systems that only handle text specifically email systems, which historically choked on binary bytes.
What Base64 Is Not
Base64 is not encryption. It provides zero security. Anyone can decode a Base64 string instantly it's a completely reversible operation with no key or secret.
This is the most common misunderstanding. You will occasionally see developers Base64-encoding sensitive data under the impression it's "hiding" it. It's not. It's as hidden as a pig in sunglasses.
dXNlcm5hbWU6cGFzc3dvcmQ=
That's username:password in Base64. The spec for HTTP Basic Authentication literally does this openly both sides know it's Base64, and the value is decoded immediately upon receipt.
How It Works
Base64 takes 3 bytes of binary data at a time and converts them into 4 ASCII characters.
3 bytes = 24 bits → split into four 6-bit groups → each 6-bit group maps to one of 64 characters.
This means Base64 is always 4/3 the size of the original data about 33% larger. A 3 KB binary becomes roughly 4 KB in Base64.
The = characters at the end are padding they align the output when the input length isn't divisible by 3.
Practical Uses
1. Embedding images in HTML/CSS (data URIs)
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUh...">
Instead of a separate HTTP request for the image, you embed it directly in the HTML. Useful for tiny icons where the request overhead outweighs the size cost. Not useful for large images (bloats HTML significantly).
In CSS:
.icon {
background-image: url("data:image/svg+xml;base64,PHN2Zy...");
}
2. Sending binary data in JSON
JSON is text-only. If an API needs to send a PDF, image, or any binary file inside a JSON response, Base64 encodes it:
{
"filename": "report.pdf",
"content": "JVBERi0xLjQKJcfs..."
}
The client decodes the Base64 string to get the binary file.
3. JWT (JSON Web Tokens)
JWTs consist of three Base64URL-encoded segments separated by dots: header, payload, signature.
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiYWxpY2UifQ.abc123
Base64URL is a variant that replaces + with - and / with _ to make it safe for URLs and HTTP headers. The JWT decoder decodes these without needing a secret key for the header and payload.
4. Email attachments (MIME)
The SMTP email protocol transmits text. Attachments (PDFs, images, any binary) are Base64-encoded before transmission and decoded by the recipient's email client. This happens automatically you don't manage it manually unless building an email system.
5. API authentication headers
HTTP Basic Auth encodes username:password as Base64 in the Authorization header:
Authorization: Basic dXNlcjpwYXNzd29yZA==
Again, this is not security. HTTPS provides the security (the header is encrypted in transit). The Base64 is purely to make the header value safe for transport.
URL-Safe Base64
Standard Base64 uses + and /. These characters have special meanings in URLs. URL-safe Base64 (Base64URL) replaces:
+→-/→_
And typically omits the padding = characters.
If you're encoding data for a URL parameter or HTTP header, use Base64URL. If you're encoding binary for storage or JSON, standard Base64 is fine.
When Not to Use Base64
Don't use it for security. It's trivially reversible.
Don't use it for large images in HTML. A 50 KB image base64-encoded is ~67 KB in the HTML. Plus it blocks caching (the HTML can't be cached independently of the image) and blocks lazy loading.
Don't use it to "compress" data. Base64 always makes data 33% larger. It's for format compatibility, not compression.
Don't use it as a substitute for proper binary transmission. Modern APIs, CDNs, and storage systems handle binary directly. Prefer multipart form uploads for files over Base64-encoding them in JSON.
Quick Reference
| Situation | Use Base64? |
|---|---|
| Tiny icon embedded in HTML | Yes |
| Binary data inside JSON response | Yes |
| JWT components | Yes (auto-handled by JWT libraries) |
| API auth header | Yes (auto-handled by HTTP libraries) |
| "Hiding" a password | No use encryption |
| Compressing a file | No use gzip/zstd |
| Sending a large image to an API | No use multipart upload |
| URLs | Yes, but use Base64URL variant |
Encode and Decode in Your Browser
The Base64 encoder/decoder converts between text and Base64 instantly. No upload, no server, just conversion.
For encoding/decoding in code:
JavaScript:
btoa("hello world") // encode: "aGVsbG8gd29ybGQ="
atob("aGVsbG8gd29ybGQ=") // decode: "hello world"
For binary data (files, images), btoa/atob don't work directly on binary. Use TextEncoder or FileReader.readAsDataURL() depending on context.
Python:
import base64
base64.b64encode(b"hello world") # b'aGVsbG8gd29ybGQ='
base64.b64decode("aGVsbG8gd29ybGQ=") # b'hello world'
Use the Base64 encoder/decoder when you need quick conversion. For JWT decoding specifically, the JWT decoder handles the Base64URL encoding and formats the JSON payload cleanly.