Back to blog

Base64 Encoding Explained: When to Use It and When Not To

A practical guide to Base64 — what it does, what it doesn't do, and the four scenarios where it's actually the right tool.

Published September 18, 2026· by TextOpal Team· 4 min read
base64encodingdeveloper-tools

Base64 is one of those encodings that every developer encounters but few actually understand. It shows up in JWT payloads, data URIs, email attachments, OAuth tokens, and a dozen other places — and it carries a persistent myth along with it: that Base64 is somehow a form of encryption. It isn't. Understanding what Base64 actually does (and what it doesn't) will save you from security mistakes and help you pick the right tool when the temptation to reach for it appears.

What Base64 actually is

Base64 is a binary-to-text encoding scheme. It takes any sequence of bytes — whether that's a PNG image, a UTF-8 string, a serialized protobuf, or a tarball — and converts it into a string composed only of 64 printable ASCII characters: A-Z, a-z, 0-9, +, and /. The = character is used for padding at the end.

The reason this is useful is that many systems were designed for text, not binary. SMTP email, JSON strings, XML attributes, URL query parameters — all of them choke on raw bytes. Base64 lets you smuggle binary data through these text-only channels without corruption.

Every three bytes of input become four characters of Base64 output. That's a 33% size overhead — the price you pay for text-safe transport.

The Base64URL variant

The standard + and / characters are problematic in URLs and filenames. Base64URL replaces them with - and _ respectively, and typically drops the trailing = padding. JWTs use Base64URL for both their header and payload segments — if you've ever decoded a JWT manually and wondered why the standard atob choked on the - character, that's why.

The fix is simple: convert Base64URL back to standard Base64 before decoding:

function base64UrlDecode(segment) {
  let s = segment.replace(/-/g, '+').replace(/_/g, '/');
  while (s.length % 4) s += '=';
  return atob(s);
}

When to use Base64

1. Embedding small images and fonts as data URIs. Inline favicons, tiny SVG icons, and small font subsets can be Base64-encoded directly into CSS or HTML. This eliminates an HTTP request, which is faster for very small assets. The cutoff is roughly 4KB — below that, inlining is usually a win; above it, the size overhead and parsing cost outweigh the request savings.

2. Building Basic Auth headers. HTTP Basic Authentication sends user:password as a Base64-encoded string in the Authorization header. This isn't encryption — it's transport obfuscation. Always pair it with HTTPS.

3. Packaging binary payloads in JSON. If you need to send a small image or binary blob inside a JSON request body, Base64 is the standard way to do it. Larger binaries should use multipart form data instead.

4. JWT segments. The header and payload of a JWT are Base64URL-encoded JSON. The signature is also Base64URL-encoded bytes. This makes the entire token URL-safe and embeddable in cookies, headers, or query strings.

When NOT to use Base64

For encryption. Base64 is reversible by anyone. Encoding a secret in Base64 provides zero security. Use TLS for transport, AES for at-rest encryption, and proper key management for secrets.

For compressing data. Base64 makes data 33% larger, not smaller. If you need to compress text, use gzip, brotli, or deflate — not Base64.

For storing passwords. Even hashed passwords shouldn't be Base64-encoded; use a slow password hash like bcrypt, scrypt, or Argon2 instead, and store the raw output in your database.

For obscuring API keys in client-side code. Base64-obfuscated keys are trivially recoverable. Any secret shipped to the browser is public — there's no encoding scheme that changes that.

Decoding safely

When decoding Base64 from untrusted sources, watch for:

A defensive decoder strips whitespace, handles Base64URL, and re-pads as needed:

function safeDecode(input) {
  const cleaned = input.trim().replace(/\s/g, '');
  const standard = cleaned.replace(/-/g, '+').replace(/_/g, '/');
  const padded = standard + '='.repeat((4 - standard.length % 4) % 4);
  const binary = atob(padded);
  const bytes = new Uint8Array(binary.length);
  for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
  return new TextDecoder().decode(bytes);
}

MIME type detection from Base64

If you receive a Base64 string and don't know what kind of file it represents, you can inspect the first few bytes (the "magic bytes") of the decoded data. PNG starts with \x89PNG, JPEG with \xFF\xD8\xFF, PDF with %PDF, GIF with GIF8. TextOpal's Base64 tool does this automatically — drop in a Base64 string and it'll tell you the MIME type and offer to download the decoded file.

The bottom line

Base64 is a transport encoding, not a security primitive. Use it when you need to move binary data through a text-only channel, and never confuse it with encryption. The 33% size overhead is the cost of admission — pay it gladly when the alternative is corrupted bytes, but reach for proper binary protocols (like multipart form data or WebSocket frames) when the payload is large.

If you work with Base64 regularly, a local decoder saves you from pasting tokens into random websites. TextOpal's Base64 tool runs entirely in your browser — no token ever leaves your machine.

Try the tool

Base64 Encoder and Decoder

Related articles

TextOpal home