Base64 Encoding Explained: How It Works & When to Use It

September 26, 2026 · Web Development

You've seen it everywhere: the data:image/png;base64,iVBOR... in HTML, the gibberish middle of a JWT, email attachments that look like alphabet soup. Base64 is the internet's standard trick for squeezing arbitrary binary data through text-only channels. Here's how it works, when to use it — and the security misunderstanding to kill on sight.

What Base64 encoding is, in plain words

Many systems only safely carry plain text — email bodies, JSON strings, URLs, HTML attributes. But files, images, and encryption keys are binary: raw bytes that include control characters and values text channels mangle. Base64 solves this by re-encoding any bytes using only 64 safe ASCII characters: A–Z, a–z, 0–9, +, and / (with = as padding). The result is pure text that survives email, JSON, and copy-paste intact.

How it works: 3 bytes become 4 characters

The classic example: Man → TWFu.

  1. Take 3 bytes: M (77), a (97), n (110) — 24 bits total.
  2. Split the 24 bits into four 6-bit groups: 010011 010110 000101 101110.
  3. Each 6-bit value (0–63) maps to one alphabet character: 19→T, 22→W, 5→F, 46→u.

That's the whole algorithm: regroup bits, look up characters. Decoding reverses it. The 6-bit grouping is why the alphabet has exactly 64 characters (2⁶ = 64).

Try it: encode Man yourself in our free Base64 Encoder/Decoder — then flip to URL-safe mode and decode it back.

Padding and the ~33% size overhead

Input isn't always a multiple of 3 bytes. Leftover bytes get padded with =: Ma (2 bytes) → TWE=, M (1 byte) → TQ==. The padding tells the decoder how many bytes the last group really held.

The price: every 3 bytes become 4 characters, so Base64 output is always about 33% larger than the input. It's a feature, not a bug — you're buying text-safety with size — but it means Base64 is the wrong choice when size matters and the channel already handles binary (like a file upload).

Base64 vs Base64URL: when to use which

Standard Base64Base64URL
Characters 62–63+ and /- and _
Padding= keptUsually dropped
Use inEmail (MIME), data URLs, XMLURLs, filenames, JWTs

+ means "space" in query strings and / separates URL paths — so standard Base64 in a URL gets corrupted unless percent-encoded (defeating the purpose). Base64URL exists precisely for that case. Rule of thumb: if the output touches a URL, use Base64URL.

Where Base64 shows up

  • Data URLs — data:image/png;base64,... embeds small images directly in HTML/CSS.
  • JWTs — the header and payload are base64url-encoded (readable, not encrypted — see our JWT guide).
  • Email — MIME encodes attachments as Base64 so they survive text-only mail transport.
  • JSON APIs — JSON has no binary type, so APIs Base64-encode files and keys inside JSON payloads.
  • HTTP Basic Auth — Authorization: Basic dXNlcjpwYXNz is just user:pass in Base64. Obfuscation, not security — always over HTTPS.

Encoding is not encryption

The single most important sentence in this article: Base64 provides zero confidentiality. It's a format conversion, like writing a number in hexadecimal — anyone who recognizes it reverses it instantly. Every "I Base64-encoded the password before storing it" is a vulnerability report waiting to happen. If data must be secret, encrypt it (AES, TLS) or hash it (bcrypt, Argon2) — encoding is for transport, never for protection.

Common mistakes

  • btoa() and Unicode: JavaScript's btoa() throws on anything outside Latin-1 — emoji, Chinese, Arabic, even some European characters. Encode to UTF-8 bytes first (TextEncoder), then Base64 those bytes; reverse with TextDecoder on decode.
  • Double encoding: encoding an already-encoded string produces valid-looking output that decodes to garbage. If your output has suspicious length or decodes to more Base64, you've encoded twice.
  • Huge data URLs: inlining a 2MB image as Base64 bloats your HTML by ~2.7MB, blocks parsing, and can't be cached separately. Reserve data URLs for tiny assets (icons under a few KB).
  • Base64 vs percent-encoding: they're different tools — Base64 packs binary into text; percent-encoding (%20) escapes reserved characters within text that's already text. Don't Base64 a URL when you meant to percent-encode it (and vice versa).

Frequently asked questions

Why does Base64 end with =?
Padding. Base64 works on 3-byte groups; if your input isn't a multiple of 3 bytes, `=` characters pad the last group out to 4 characters. One trailing byte → `==`, two trailing bytes → `=`. The `=` carries no data — it just marks how much padding was added.
Is Base64 secure?
No. Base64 is an encoding, not encryption — anyone can decode it instantly. It provides zero confidentiality. Never "protect" passwords, tokens, or personal data with Base64; use real encryption or hashing instead.
Why is Base64 bigger than the original?
It represents every 3 bytes as 4 characters, so output is ~33% larger than input (plus padding). That overhead is the price of restricting output to 64 safe ASCII characters.
What's Base64URL for?
Standard Base64 uses `+`, `/`, and `=` — characters with special meaning in URLs. Base64URL swaps them for `-` and `_` and drops padding, so encoded values survive in query strings, filenames, and JWTs without percent-encoding.
Why does btoa() fail on emoji?
JavaScript's `btoa()` only accepts Latin-1 (single-byte) characters; emoji and most non-English text are multi-byte UTF-8 and throw "InvalidCharacterError". The fix is encoding the string to UTF-8 bytes first (e.g. via TextEncoder), then Base64-encoding the bytes.
Can I put images in HTML with Base64?
Yes, via data URLs (`<img src="data:image/png;base64,...">`), and it's handy for tiny icons — one fewer HTTP request. But the ~33% size overhead makes it a bad deal for large images; files above a few KB are usually better as separate requests (which also cache independently).
How do I decode Base64?
In JavaScript: `atob()` (ASCII/Latin-1 only — use TextDecoder for UTF-8). In Python: `base64.b64decode()`. On the command line: `echo "TWFu" | base64 -d`. Or paste it into our Base64 Encoder/Decoder tool — no code needed.

Related articles

Try the free tool