Base64 turns any bytes into text from a 64-character alphabet so binary data can travel through text-only channels. This explainer walks the encoding by hand, explains the 33% size tax and the padding equals signs, and settles the most dangerous misconception about it.
Base64 exists because the internet's oldest plumbing — email, and many text formats — was built for letters, not bytes. Arbitrary binary data (an image, a key, a compressed file) contains byte values that text systems mangle, truncate or reject outright. Base64 solves that transport problem by re-expressing bytes in an alphabet of 64 safe characters: A–Z, a–z, 0–9, plus + and /, with = as padding. It is a change of representation, nothing more — and that "nothing more" matters, because Base64 output is routinely mistaken for protected data.
This article encodes a word by hand so the mechanism is demystified, counts the cost precisely, introduces the URL-safe variant, and then deals firmly with the encryption confusion and the places Base64 genuinely belongs.
Key takeaways
- Base64 maps every 3 bytes to 4 characters; output is always about 33% larger than the input.
- Decoding needs no key and no secret — anyone holding Base64 text holds the original data, one trivial step away.
- The URL-safe variant swaps + and / for - and _ so encoded text survives inside links and filenames.
- Legitimate homes: email attachments, data URIs, embedding binary in JSON, carrying keys and tokens as text.
Encoding "Cat" by hand
Take the three bytes of Cat: C = 67, a = 97, t = 116. Written in binary and joined, they form a 24-bit stream: 010000 110110 000101 110100 when re-sliced into four 6-bit groups. Each 6-bit group is a number from 0 to 63, and the alphabet maps numbers to characters: 16 → Q, 54 → 2, 5 → F, 52 → 0. So Cat encodes to Q2F0. No key entered that process at any point — the alphabet is public and fixed, which is the entire reason the output cannot be a secret.
When the input length is not a multiple of three, the final group is short, and = signs pad the output to a multiple of four characters: one leftover byte produces two characters plus ==; two leftover bytes produce three characters plus =. Those equals signs are a length receipt, not decoration, and strict decoders want them present unless the variant in use explicitly omits padding, as many URL-safe contexts do.
The 33% tax, and where it shows up
Because 3 bytes become 4 characters, Base64 output is exactly ⌈n/3⌉ × 4 characters for n bytes — about 33% larger before line breaks. Email's MIME standard also wraps Base64 at 76 characters per line, adding a further ~3% in newlines. Consequences you can plan around: a 750 KB image inlines as roughly 1 MB of text in a data URI; a JSON API that Base64-embeds a 10 MB upload moves about 13.3 MB; and a database column of Base64 blobs wastes a third of its space versus storing the bytes natively. The tax is worth paying where the channel demands text — and a pure cost everywhere it does not.
Variants you will meet
| Variant | Differences | Where it lives |
|---|---|---|
| Standard | + and /, = padding, often line-wrapped in email | MIME email attachments, PEM keys, countless file formats |
| URL-safe (base64url) | - and _ replace + and /, padding usually omitted | JWT tokens, URL parameters, filenames, WebAuthn and OAuth payloads |
| Base64 in data URIs | Standard alphabet, no line breaks, declared mediatype first | Embedding small images and fonts directly in HTML/CSS |
A strict decoder fed the wrong variant can fail — or worse, mis-decode, which is why finding - and _ in a token is a reliable tell that you are looking at base64url. When a tool offers a URL-safe toggle, it is switching exactly those two characters and the padding habit.
Why "encoded" must never be read as "protected"
Encryption transforms data with a key so that only key-holders can reverse it. Encoding transforms data with a public rule so that anyone can reverse it. Base64 is unambiguously the second thing — decoding is a single command available in every operating system and browser. Yet Base64'd passwords, API keys and personal data keep appearing in breaches, configuration files and URLs under the assumption that scrambled-looking text is safe text.
Hold two rules. First, treat Base64 output as plain text for every security and privacy purpose: if the original needed protection, the encoded form needs exactly the same protection. Second, remember the reverse mistake is also possible — finding Base64 in a system is not automatically finding a vulnerability; it is a transport format doing its job in email, tokens and embedded media. Judge it by what it carries and where it sits, not by its alphabet.
Mistakes and pitfalls
Encoding a password before storing it and calling that security
Anyone who obtains the encoded value decodes it instantly; you have stored the password with extra steps. Passwords need a slow salted hash (Argon2, bcrypt); secrets in transit need encryption or a protected channel — Base64 is neither.
Assuming long Base64 strings in URLs are harmless to share
A pasted link carrying a Base64 token carries the token's contents — which may be a reset credential or personal data — to anyone the link reaches, and links get logged, forwarded and screenshotted. Inspect before you share.
Decoding twice because the first pass 'still looks encoded'
Nested encoding happens in the wild (a token inside a JSON inside a Base64 blob). Repeated blind decoding can also corrupt: keep decoding layer by layer, checking at each stage whether the output is plausible text or structured data, and stop there.
Common questions
Why 64 characters — why not Base256 or Base32?
The alphabet must survive the channels it crosses. 256 symbols cannot be typed or transmitted as plain text at all; Base32 exists (a smaller, case-insensitive alphabet) where case-insensitivity matters, at a larger 60% size tax. Sixty-four is the largest power-of-two alphabet that common text channels carry safely.
Is the Base64 in a JWT a problem?
A JWT's header and payload are base64url-encoded, not encrypted — anyone can read them, and that is by design: the signature provides integrity, not secrecy. The practical rule follows: never put secrets or sensitive personal data in a JWT payload.
My decoded output is gibberish. What went wrong?
Usually one of three things: the input was the URL-safe variant fed to a strict decoder, padding or characters were lost when the string was copied through a system that treats + as a space (a classic URL-decoding casualty), or the payload was never text — decoding an image's Base64 correctly returns binary, which looks like gibberish because it is.
To wrap up
Base64 is humble, essential plumbing: a way for bytes to travel as text, at a 33% toll, reversibly by anyone. Respect it for exactly that — use it where channels demand it, never lean on it for secrecy, and the long strings will stop looking like either magic or menace.
Try it yourself
The Base64 encoder handles text and files in your browser, with the URL-safe variant one toggle away — encode or decode something and check the size tax against the arithmetic in this article.