Home · Blog · Base64

Base64 is not encryption: what it is and isn't

3 Oct 2026 · Data · 6 min read

Show a non-technical person the string SGVsbG8sIHdvcmxk and they will reasonably assume it's encrypted. It looks secret: an unreadable jumble of letters, numbers and symbols. Paste it into a decoder, though, and it instantly becomes "Hello, world" — no key, no password, no effort. Base64 is one of the most misunderstood encodings in computing, precisely because it looks like security while providing none.

This article explains what Base64 actually does, walks through the arithmetic, shows where you'll meet it in the wild, and clears up the three myths that refuse to die: that it's encryption, that it compresses, and that it's a hash.

What it actually is: binary dressed as text

Computers love binary — images, PDFs, zip files are all just bytes. But many of the channels we push data through only accept text: email bodies, URLs, JSON fields, source code. Binary bytes include values that these channels mangle, strip, or interpret as control characters. Base64 solves exactly this one problem: it re-expresses arbitrary bytes using only 64 safe text characters — A–Z, a–z, 0–9, + and /, with = as padding.

That's the entire job description. Base64 is a transport encoding: it carries binary through a text-only channel without damage. It hides nothing and shrinks nothing.

How the arithmetic works

The trick is regrouping bits. Take 3 bytes — 24 bits — and split them into 4 groups of 6 bits. Each 6-bit group is a number from 0 to 63, which maps to one character of the 64-character alphabet. Three bytes in, four characters out, every time.

Let's encode "Hi" by hand. The letters are bytes 72 and 105:

  • 72 in binary: 01001000; 105 in binary: 01101001
  • We need 3 bytes but have 2, so pad with a zero byte: 01001000 01101001 00000000
  • Regroup into 6-bit chunks: 010010 000110 100100 000000 → decimal 18, 6, 36, 0
  • Alphabet positions 18, 6, 36, 0 → S, G, k, A
  • But we padded a whole byte, so the last character becomes padding: SGk=

Decode SGk= and you reverse the steps to get "Hi" back — deterministically, with no key involved at any point. Anyone holding the output can do this in a single line of code, which is exactly why it must never be treated as secret.

Where you'll meet it in the wild

  • Data URLs. A tiny image embedded directly in a web page looks like data:image/png;base64,iVBORw0KGgo… — the image bytes, Base64-encoded, riding inside an HTML or CSS file.
  • Email attachments. Email was designed for text; attachments travel as Base64 inside MIME messages. That 2 MB photo becomes about 2.7 MB of text on the wire.
  • JSON Web Tokens (JWTs). The three dot-separated sections of a JWT are Base64url-encoded JSON. The payload is encoded, not encrypted — anyone can read it.
  • Embedding fonts and keys. Configuration files and code often carry binary blobs (fonts, certificates) as Base64 strings because text is easier to copy, paste and version-control than raw bytes.

Myth 1: "It's encryption"

This is the dangerous one. Encryption requires a key: without it, the data should be unrecoverable. Base64 has no key — the algorithm is public, fixed, and reversible by design. "Encrypting" a password with Base64 is like hiding a house key under the doormat and calling it a vault. If you see credentials or tokens stored as plain Base64 in a database or config file, treat them as exposed, because they are.

Myth 2: "It compresses"

Base64 makes data bigger, not smaller — by a fixed ratio. Every 3 bytes become 4 characters, so the output is always about 33% larger than the input (plus padding). A 3 MB file becomes 4 MB of text. If your goal is smaller files, you want actual compression (like gzip) — possibly before encoding, if the channel demands text.

Myth 3: "It's a hash"

Hashes are one-way: you can't reconstruct the input from the digest. Base64 is fully reversible — decoding always restores the exact original bytes. It also isn't unique the way hashes aim to be; it's a representation, not a fingerprint. Same input, same output, every time, and trivially undone.

The URL-safe variant

Standard Base64 uses + and /, which have special meanings in URLs, and padding =, which some systems dislike. The URL-safe variant swaps +→- and /→_ and usually drops the padding. JWTs use this variant. It's a small detail that causes real bugs when one side encodes standard and the other expects URL-safe.

Worked example: the classic "Man"

The original Base64 specification uses "Man" as its walkthrough, and it's worth repeating because the numbers are so clean. The three ASCII letters are bytes 77, 97, 110:

  • Binary: 01001101 01100001 01101110 (24 bits, no padding needed)
  • Regrouped into 6-bit chunks: 010011 010110 000101 101110 → decimal 19, 22, 5, 46
  • Alphabet lookup: 19→T, 22→W, 5→F, 46→u
  • Result: TWFu — no padding, since the input was exactly 3 bytes

Now change the input to "Ma" (2 bytes). The bit regrouping leaves one chunk made entirely of padding, giving TWE=. Shorten to "M" (1 byte) and two chunks are padding: TQ==. The padding tells the decoder exactly how many real bytes to recover — one = means the last group held 2 bytes, two means it held 1. Elegant, deterministic, and — to repeat the theme — entirely public.

The credential-leak pattern

The most common real-world misuse goes like this: a developer needs to put an API key in a config file, feels uneasy leaving it in plain text, and Base64-encodes it "for safety". The config gets committed to a shared repository. Months later the key is abused, and everyone is surprised — but the key was never protected. It was formatted.

The rule is blunt: if a secret appears anywhere outside a proper secrets manager — in code, in configs, in logs, in Base64 — treat it as compromised and rotate it. Encoding changes the representation, not the exposure. Real protection means encryption with a key stored separately, access controls on who can read the value, and rotation when exposure is suspected. Base64 does none of these; it just makes the leak slightly harder to spot with the naked eye, which arguably makes things worse.

Standard Base64 also has a presentation habit worth knowing: MIME email wraps encoded output at 76 characters per line, because some ancient mail systems truncated longer lines. Those line breaks are cosmetic — decoders ignore whitespace — but they explain why Base64 in emails looks like a neat paragraph while Base64 in a JWT is one endless string. Same encoding, different wrapping conventions for different channels.

The honest caveat

Base64 is a faithful courier: what goes in comes out, byte for byte. Just remember what the courier doesn't do. It doesn't keep secrets — for that you need real encryption with a key. It doesn't save space — budget an extra third. And it doesn't verify anything — a single changed character decodes to different bytes with no warning. Use it to carry binary through text-only channels, which is the one job it was designed for, and it will never surprise you.

Try the Base64 Encoder