What Is Base64?
Base64 is a binary-to-text encoding scheme. It takes any stream of bytes — an image, a PDF, a JSON payload, an encryption key — and represents it using only 64 printable ASCII characters: A–Z, a–z, 0–9, +, and /.
Why bother? Because many systems only reliably transport text. Email bodies, HTTP headers, JSON strings, XML, and CSS files all have constraints on which bytes they can safely carry. Base64 gives you a way to represent arbitrary binary data using only safe characters — which is why image-to-Base64 conversion is such a common workflow for frontend developers.
Base64 Is Not Encryption
Base64 provides zero security. Anyone with a browser can decode a Base64 string in one click. If you can read it, so can anyone who intercepts it. Never encode passwords, API keys, session tokens, or private messages in Base64 and call it "protected."
The confusion is understandable: a Base64 string looks like scrambled garbage — SGVsbG8gV29ybGQ= hides "Hello World" in plain sight. But "looks unreadable" is not the same as "is confidential." Base64 is a transport format, not a security format. For actual protection you need encryption (AES, ChaCha20, etc.) or hashing (SHA-256, bcrypt) — a distinction worth keeping in mind whenever you're reviewing code that stores sensitive data.
Understanding Base64 Padding
Base64 works in groups of 3 input bytes → 4 output characters. Because 3 bytes (24 bits) map exactly to 4 Base64 characters (6 bits each), the ratio is always 4 / 3. But what if your input length isn't divisible by 3?
That's what the = signs are for. They pad the output so it stays a multiple of 4 characters:
The pattern is fixed: 1 remaining byte = ==, 2 remaining bytes = =, 0 remaining = no padding. If you see a Base64 string that ends in =, you know the original data length was not a multiple of 3. If it ends without padding (or with - / _), you're looking at Base64url — covered next.
Base64url and JSON Web Tokens
Standard Base64 uses + and /, which have special meaning in URLs and file paths. + becomes a space in query strings; / is a path separator. So a URL-safe variant called Base64url (RFC 4648 §5) swaps them:
+→-(hyphen)/→_(underscore)- Trailing
=padding is usually stripped
If you've ever pasted a JWT into a debugger, you've seen Base64url in action. A typical token looks like eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.abc123 — three Base64url segments separated by dots: header, payload, and signature. Decode the first two with a JWT debugger and you get plain JSON. This is why you should never put secrets in a JWT payload: it isn't encrypted, only encoded.
The 33% Size Penalty
Base64 output is always about 33% larger than the input. The math is straightforward: 3 input bytes (24 bits) become 4 ASCII characters (32 bits). That's an increase of 8 bits per 3 bytes, or roughly 33%:
This matters when you're deciding whether to embed assets as data URIs. For a small SVG icon under 5 KB, the overhead is negligible and you save an HTTP request. For a 200 KB hero image, you're adding 66 KB to your CSS payload — a real cost that affects page speed and Core Web Vitals. The rule of thumb: inline under 10 KB, link the rest.
When to Use Base64 (and When Not To)
Good uses:
- Small icons and UI assets embedded directly in CSS to eliminate HTTP requests
- Transmitting binary blobs through JSON APIs that only accept text
- Email attachments (MIME encoding wraps binary files as Base64)
- JWT payloads and OAuth tokens (Base64url)
- Data URIs for dynamically generated images from canvas
Bad uses:
- Storing passwords or API keys in configuration files (it's not encryption)
- Embedding large images in HTML/CSS (they block parsing and inflate payload size)
- Compressing data (Base64 always makes it bigger, never smaller)
- Hiding sensitive information in a "secret" file (anyone can decode it)
Worked Example: "Hello"
Walking through the encoding step by step:
That final = tells any decoder that the original input was 5 bytes — two bytes short of a full 6-byte group — and to reconstruct it accordingly. This level of precision is what makes Base64 deterministic across every language and platform.