Cheatsheet

Base64 Reference

# Base64 Reference

Base64 turns arbitrary binary data into a string of 64 printable ASCII characters, so it can safely travel through text-only channels — email bodies, JSON fields, URLs, data: URIs. It is an encoding, not encryption: anyone can decode it, instantly, with no key.

Quick reference

The alphabet

Index range Characters
0–25 `A`–`Z`
26–51 `a`–`z`
52–61 `0`–`9`
62 `+` (standard) or `-` (URL-safe)
63 `/` (standard) or `_` (URL-safe)
padding `=`

How the math works

Base64 groups input into 3-byte (24-bit) chunks and re-slices each chunk into four 6-bit values (0–63), each mapped to one alphabet character. 6 bits per output character is why the encoded size is always ~4/3 the size of the input (a rough rule: ceil(n / 3) * 4 bytes).

Padding rules

Input bytes (mod 3) Output ends with
0 remainder No padding
1 remainder `==` (two pad chars)
2 remainder `=` (one pad char)
"M"   (1 byte)  -> "TQ=="
"Ma"  (2 bytes) -> "TWE="
"Man" (3 bytes) -> "TWFu"

Standard vs URL-safe (RFC 4648 §5)

Standard URL-safe
Char 62 `+` `-`
Char 63 `/` `_`
Padding `=` required Usually omitted

URL-safe Base64 exists because + and / are meaningful in URLs and query strings (+ means space in form-encoded data; / is a path separator) — swapping them avoids percent-encoding the Base64 output a second time. JWTs use unpadded URL-safe Base64 for exactly this reason (see the related tools below to decode one).

Common patterns

Encode/decode in the browser or Node

// Node.js
Buffer.from('Hello, World!').toString('base64');       // "SGVsbG8sIFdvcmxkIQ=="
Buffer.from('SGVsbG8sIFdvcmxkIQ==', 'base64').toString(); // "Hello, World!"

// Browser (ASCII-safe strings only — see pitfall below)
btoa('Hello');   // "SGVsbG8="
atob('SGVsbG8=');// "Hello"

URL-safe encode without padding (Node)

Buffer.from('Hello, World!').toString('base64url');
// "SGVsbG8sIFdvcmxkIQ" -- note: no padding, +/ replaced

Encode a UTF-8 string safely in the browser

function b64EncodeUnicode(str) {
  return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
    (_, p1) => String.fromCharCode(parseInt(p1, 16))));
}
b64EncodeUnicode('café'); // "Y2Fmw6k="

Data URI for inline images

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...">

Pitfalls

  • btoa()/atob() only understand characters 0–255, and silently corrupt some Unicode instead of erroring: btoa('😀') or btoa('中文') throw InvalidCharacterError because those code points are above 255 — but a character like é (U+00E9) is within that range, so btoa('café') doesn't throw at all, it just encodes the wrong bytes ("Y2Fm6Q==", silently different from the correct UTF-8-aware result). Don't treat "it didn't throw" as "it worked" — always encode to UTF-8 bytes first (see the pattern above) or use TextEncoder + a byte-to-Base64 loop.
  • Base64 is not encryption: it provides zero confidentiality. Never use it to "hide" a password, API key, or PII — treat any Base64 string in a URL, header, or log as fully readable plaintext.
  • Missing or extra padding breaks strict decoders: some libraries require exact = padding and reject unpadded input; others (Node's Buffer, most URL-safe decoders) are lenient. When round-tripping between systems, don't assume the receiver tolerates missing padding.
  • Line-wrapping in older tools: the Unix base64 CLI and some legacy MIME encoders insert a newline every 76 characters (RFC 2045). Passing that output straight into JSON.parse or a URL will silently corrupt it — strip whitespace first, or pass -w0 to base64 on Linux to disable wrapping.
  • Base64 inflates size by ~33%: for large payloads (embedding a big image as a data: URI, for example) this is a real bandwidth and parse-time cost, not just a formatting detail — weigh it against just linking to a binary asset.

Related ZipKit tools

  • Base64 Encode / Decode — encode/decode text and files, including the URL-safe variant.
  • URL Encode / Decode — the companion transform for the characters Base64's +// collide with in URLs.
  • Hash Generator — hashes are commonly displayed as Base64 (or hex) — generate and compare both here.
  • JWT Decoder — decode a JWT's Base64url header and payload segments instantly.

Related cheatsheets