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:

  1. 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 47 for PNG).
  2. 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.
  3. 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.