UUsefulCrate Your files never leave your browser

HomeGuides › Developer

Base64 is not encryption

Base64 turns up everywhere in software and is misunderstood almost as often as it is used. None of the misconceptions are hard to clear up.

2026-09-24 · 7 min read

Short answer: no. Base64 is an encoding, not a cipher. It turns arbitrary bytes into text that can survive a channel built for text — an email body, a JSON field, a data URL — and anyone can reverse it with no key at all. It also makes the data roughly a third larger, because it spends four characters to carry three bytes.

A string that looks like line noise, produced by a function called "encode", is easy to mistake for something protective. Base64 is not protective. It is a transport format, and misunderstanding that has consequences.

What Base64 actually does

Base64 represents arbitrary bytes using an alphabet of 64 printable characters: the upper- and lower-case letters, the ten digits, plus + and /, with = used as padding at the end.

The purpose is to move binary data through channels that only carry text. Email bodies, JSON values, XML documents, HTTP headers and URLs all have rules about which bytes are allowed. Base64 turns any sequence of bytes into a sequence that satisfies every one of those rules.

"hello"        → aGVsbG8=
0x00 0xFF 0x10 → AP8Q
café           → Y2Fmw6k=     (UTF-8 bytes: 63 61 66 C3 A9)

Misconception one: it is not encryption

Encoding is a reversible transformation with no key. Anyone who has the string can decode it, instantly, with a function available in every language. There is no secret involved at any point.

The practical test is simple: if decoding requires nothing but the encoded text, it is encoding. Encryption requires a key; without it, the output is indistinguishable from random noise.

The mistake shows up in production more often than you would hope. Authorisation headers containing Basic credentials are just Base64 — the standard even calls them credentials, and they are readable by anyone who sees the header. An API key stored in a config file as a Base64 string is an API key. Obfuscation is not a control, and this is the most common place it gets mistaken for one.

Misconception two: it does not make anything smaller

The opposite. Base64 uses 4 characters to carry 3 bytes, so the output is exactly 4/3 the size of the input — about 33% larger, before line breaks.

The intuition that it must compress something comes from the input usually being binary, which often looks cryptic. But the length grows, every time, deterministically. Embedding an image in JSON as Base64 makes the payload a third bigger, and the JSON parser still has to decode it back to bytes.

Why "base64 compression" sometimes seems to work

Because what was being measured was an HTTP response with gzip enabled. Base64 output uses only 64 distinct characters drawn from a printable range, which compresses well. So the wire size can genuinely fall — but the saving comes from gzip, not from Base64, and gzip would have handled the original binary at least as well.

Misconception three: the "encrypted-looking" padding means something

The trailing = or == is not a checksum, a key hint or a security marker. It exists because the input's length may not be divisible by three, and the encoding works in three-byte groups. One leftover byte produces two padding characters, two leftover bytes produce one, and no leftover bytes produce none.

It carries a small amount of information: the padding tells you the original length modulo three. That is all.

Misconception four: any two Base64 tools will agree

There are two variants, and mixing them up produces output that fails to decode with a confusing error.

StandardURL-safe
Character 62+-
Character 63/_
Padding=Often omitted
Used byEmail (MIME), data URIs, most APIsJWTs, URLs, filenames

The URL-safe variant exists because + and / have meanings in a URL — + is a space in form-encoded data, and / is a path separator. A standard Base64 string pasted into a query parameter or a path segment may therefore be mangled in transit, silently, before your server ever sees it.

This is why JWTs use the URL-safe alphabet. It is also why a token copied from a browser can appear to differ from the same token seen server-side, if something along the way treated a + as a space. The Base64 encoder here has an explicit URL-safe toggle so the choice is deliberate.

Misconception five: it is a reasonable way to store data

Storing an image as a Base64 string in a database column is a common shortcut with three costs: the column holds 33% more bytes than necessary, the database cannot index or inspect it meaningfully, and every read pays a decode step.

Data URIs in CSS and HTML are the version of this that is sometimes justified, because they eliminate a request for a genuinely tiny asset. Above a kilobyte or two the trade turns negative, and the ability to cache the image separately is lost.

Where Base64 is the right tool

In each case the motive is the same: the destination only accepts text. None of them is about secrecy.

The one-line summary

Base64 makes data safe to transfer. It makes it neither smaller nor secret.

If you need secrecy, you need encryption, with a key that never touches the channel. If you need integrity, you need a signature or a hash. Base64 gives you neither, and treating it as if it did is how credentials end up in logs and configuration files that people believe are safe to share.

For the encoding itself, doing it locally avoids the specific problem that the input is very often a secret — an API key being embedded in a config, a token going into a header, a password in a connection string. The encoder and decoder here handles UTF-8 correctly, which matters more than it sounds: many tools encode characters rather than their UTF-8 bytes, producing output that decodes to mojibake. Accented letters, emoji and CJK text round-trip correctly here.

← All guides