Base64 Is Not Encryption: When to Use It
Published 2026-10-31
Every few months someone ships a system that "encrypts" credentials with Base64. It does not. Anyone can decode it in one line:
Buffer.from('cGFzc3dvcmQ=', 'base64').toString(); // 'password'
Base64 is a binary-to-text encoding. Its job is to move bytes through channels that only accept text, without losing information. Secrecy is not part of the contract.
What it actually does
It takes 3 bytes (24 bits) and rewrites them as 4 characters from a 64-character alphabet (A–Z a–z 0–9 + /). Padding with = brings the length back to a multiple of 4.
The consequences follow directly:
| Property | Value | Why |
|---|---|---|
| Size overhead | +33% | 3 bytes become 4 characters |
| Reversible | Always | It is an encoding, not a transform |
| Key required | None | There is nothing to hold a key for |
| Safe in JSON | Yes | Output is pure ASCII |
| Safe in URLs | Not by default | + and / collide with URL syntax |
That 33% is why you should never Base64 an image "to make it smaller". You are making it 33% larger.
Base64 vs hashing vs encryption
The three get confused constantly. They solve different problems:
| Base64 | Hash (SHA-256) | Encryption (AES) | |
|---|---|---|---|
| Purpose | Move bytes through text channels | Verify integrity, store passwords | Keep data secret |
| Reversible | Yes, by anyone | No | Yes, with the key |
| Shrinks data | No (+33%) | Yes, fixed 32 bytes | Roughly no |
| Needs a key | No | No | Yes |
A useful test: if you can prove it is not encryption by decoding it without a key, it is not encryption.
See Password Hashing for the hashing side of this story.
Where Base64 is genuinely the right answer
Base64 is not a mistake — it is misapplied. These are the cases where it is correct:
- Embedding binary in JSON. JSON has no byte type. A Base64 string is the standard way to ship an image or a PDF inside an API response.
- Data URLs in HTML/CSS.
data:image/png;base64,...avoids an extra request for tiny assets. Practical below roughly 2 KB; above that, the 33% overhead and the loss of caching outweigh the saved request. - Email attachments. MIME encodes attachments as Base64 because SMTP is a 7-bit text protocol.
- JWT segments. The header and payload are Base64URL so they can be copied into headers and URLs without escaping.
- Basic authentication.
Authorization: Basic base64(user:pass)— famously not encryption, and only safe over TLS.
Common failure modes
Assuming it hides anything
Base64 makes text unreadable to a human skimming a log. It stops nothing else. Attackers have base64 -d.
Using standard Base64 inside a URL
+, / and = in a query string break parsing. That is exactly why Base64URL exists: + becomes -, / becomes _, and padding is dropped. If you are putting Base64 in a URL or a cookie, use the URL-safe variant. Anything else produces intermittent, hard-to-reproduce 400s.
Line wrapping
MIME Base64 wraps at 76 characters. Most modern implementations do not. If you paste a wrapped blob into a decoder that expects a single line, you get garbage or an error. Strip newlines before decoding.
Encoding already-encoded data
Base64 of Base64 is a real pattern in the wild: 33% overhead squared, plus a decoding ambiguity. If your string starts with cGFzc3dvcmQ you may be looking at one layer too many.
Decoding safely
Three practical notes:
- Decode to bytes, not to text. If the payload is a PNG,
toString('utf8')produces mojibake. Write bytes to a file and check the magic number (89 50 4E 47for PNG). - Validate the alphabet. A strict decoder rejects characters outside the 64-character set. A lenient one silently drops them — which is how corrupted data passes through unnoticed.
- Watch out for URL-safe input. A payload containing
-or_will fail a standard decoder. Convert-→+and_→/first, then re-add padding.
Base64 Encoder/Decoder handles text and files in both directions locally, including the URL-safe alphabet switch — useful when debugging a token you cannot paste into a third-party site.
The one-line summary
Base64 is a text-friendly container for bytes. Use it to transport, never to protect. If a design document says "the password is encrypted with Base64", that document has a security bug, not a naming problem.