14 categories See all →
home / blog / Developer

How Base64 Encoding Actually Works

Base64 is encoding, not encryption — a mix-up that causes real security mistakes. Here's the 3-bytes-to-4-characters mechanism, why padding appears, and where Base64 is actually used.

Base64 is one of those things every developer uses regularly and almost nobody can explain precisely. You've seen it — strings full of letters, numbers, plus signs, slashes, and sometimes trailing equals signs, showing up in data URIs, auth headers, and config files. Let's actually get into how and why it works, and clear up the single most damaging misconception about it.

Base64 is not encryption

This needs to be said plainly because it causes real security mistakes: Base64 provides zero confidentiality. It's a reversible encoding scheme — anyone can decode a Base64 string back to its original form instantly, with no key, no password, nothing. If you Base64-encode a password and store it thinking it's "obfuscated" or "protected," you've protected nothing. It's the equivalent of writing a note in a slightly different alphabet and calling it a secret — anyone who's ever seen Base64 before (which is to say, every developer and most scanning tools) can read it in seconds.

People reach for Base64 thinking it adds security because the output looks unreadable at a glance. It doesn't. Its actual job is entirely different: making binary data safe to put somewhere that only expects text.

What Base64 is actually for

Lots of systems — email (the original use case, via MIME), JSON, XML, URLs, HTTP headers — are designed to carry text, specifically a limited set of safe characters. But plenty of data you want to transmit is binary: images, PDFs, encrypted blobs, arbitrary bytes that include control characters or values that would break a text-based format. Base64 converts arbitrary binary data into a string using only 64 characters that are safe everywhere: A–Z, a–z, 0–9, plus + and / (and an optional = for padding). That's the whole alphabet — 64 symbols, which is where the name comes from.

The 3-bytes-to-4-characters mechanism

Here's the actual mechanism. A byte is 8 bits, giving 256 possible values — too many to map onto a 64-character alphabet directly (64 values only need 6 bits to represent, since 2^6 = 64). Base64 solves this by regrouping: it takes 3 bytes (24 bits total) and re-slices them into 4 chunks of 6 bits each. Since 2^6 = 64, each 6-bit chunk maps directly onto one of the 64 alphabet characters.

Concretely: 3 bytes in → 24 bits → split into four 6-bit groups → each group looked up in the 64-character alphabet → 4 output characters. This is why Base64-encoded data is always about 33% larger than the original — you're using 4 characters to represent what was 3 bytes, a 4:3 expansion ratio.

Why the padding (=) shows up

The 3-bytes-to-4-characters grouping only works cleanly when your input length is a multiple of 3. Most real data isn't. So when the input doesn't divide evenly:

If there's 1 leftover byte (8 bits), it gets padded with zero bits to make up a 6-bit group, producing 2 real characters, and the encoder adds == to signal that 2 characters' worth of data is missing from this final group.

If there are 2 leftover bytes (16 bits), you get 3 real characters, and a single = is appended to signal 1 missing character's worth.

That's the entire reason you sometimes see one =, sometimes two, and sometimes none at the end of a Base64 string — it's purely about whether the input length was a multiple of 3, not anything about the content itself.

Where you'll actually run into Base64 as a developer

Data URIs for small images. Instead of referencing an image file, you can embed it directly in HTML or CSS: <img src="data:image/png;base64,iVBORw0KG...">. This saves an HTTP request, which matters for small icons, but bloats the document size by ~33% — a tradeoff worth making for tiny assets, not for large images.

Encoding binary data in JSON or URLs. JSON has no native binary type, and URLs can't safely carry arbitrary bytes. If you need to send a binary blob (an image, a file, encrypted data) through either, Base64-encoding it first makes it safe to include as a plain string.

Basic Auth headers. HTTP Basic Authentication sends credentials as Authorization: Basic <base64(username:password)>. This is a textbook example of why Base64 isn't security — the credentials are fully recoverable by anyone who intercepts the header, which is exactly why Basic Auth is only considered acceptable over HTTPS, where TLS (actual encryption) is doing the real protection work, not the Base64 encoding.

Try it yourself

Our Base64 Encode/Decode tool lets you convert text or files to Base64 and decode Base64 strings back instantly — useful for inspecting a JWT payload, decoding a Basic Auth header while debugging, or generating a data URI for a small image.