What is Base64
Base64 is a scheme that encodes arbitrary binary data into pure ASCII strings. It uses 64 printable characters (A-Z, a-z, 0-9, +, /) to represent data, plus = as padding. Because the output contains only ASCII, Base64-encoded data can safely pass through text-only channels—this is its core value.
Why Base64 Exists
Many legacy protocols (SMTP email, HTTP headers, JSON text) only handle printable ASCII. If you embed PNG binary data in a JSON field directly, the unprintable bytes break parsing. Base64 "translates" those bytes into safe text, solving the transport problem.
Encoding Principles
Core Algorithm
Base64 processes input in 3-byte (24-bit) groups:
- Take 3 bytes of binary data (24 bits)
- Split into 4 groups of 6 bits each
- Map each 6-bit value (0-63) to a Base64 alphabet character
- If the last group has fewer than 3 bytes, pad with
=to 4 characters
Alphabet Table
Index Char Index Char Index Char
0-25 A-Z 26-51 a-z 52-61 0-9
62 + 63 / Pad =
Encoding Example
Encoding the string Man:
| Step | Value |
|---|---|
| ASCII | M=77, a=97, n=110 |
| Binary | 01001101 01100001 01101110 |
| 6-bit groups | 010011 010110 000101 101110 |
| Decimal | 19, 22, 5, 46 |
| Base64 | TWFu |
Overhead
3 input bytes become 4 output characters, a constant 4/3 ≈ 33.3% overhead. For inputs under 3 bytes, overhead is higher: 1 byte encodes to 4 characters (with 2 =), a 300% increase.
Variant: URL-Safe Base64
The + and / in standard Base64 have special meanings in URLs, causing ambiguity. RFC 4648 §5 defines a URL-safe variant:
+→-/→_- Trailing
=padding usually omitted
JWT, Data URLs, and similar contexts default to URL-safe Base64.
Practical Use Cases
1. Data URLs (Inline Resources)
Embed small images directly in HTML/CSS to avoid extra HTTP requests:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUg..." alt="logo">
When to use: resources under 4KB. Larger images bloat the HTML and block parsing.
2. Email Attachments (MIME)
SMTP originally supported only 7-bit ASCII text. MIME uses Base64 to encode binary attachments (images, PDFs) as text. A line break (CRLF) is inserted every 76 characters—specific to MIME.
3. API Tokens & Credentials
Many APIs encode credentials with Base64:
- HTTP Basic Auth:
Authorization: Basic dXNlcjpwYXNz(Base64 ofuser:pass) - API Keys: some platforms' keys are Base64-encoded random bytes
4. JWT (JSON Web Token)
A JWT has three parts; the Header and Payload are Base64 URL-safe encoded:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
5. Source Maps & WASM
Frontend build artifacts (source maps) and WebAssembly modules use Base64 encoding in certain embedding scenarios.
Common Pitfalls
Pitfall 1: Base64 Is Not Encryption
Base64 is encoding, not encryption. Anyone can decode it; it provides zero confidentiality. Storing passwords Base64-encoded is equivalent to plaintext.
Pitfall 2: Ignoring Overhead
33% overhead matters for large files. A 10MB image becomes ~13.3MB in Base64. Passing large Base64 payloads in API responses slows both transfer and parsing.
Pitfall 3: Charset Confusion
The string "Hello" is first UTF-8 encoded to bytes, then Base64 encoded. Different charsets (UTF-8 vs GBK) produce different Base64 output. Always normalize to UTF-8 before encoding non-ASCII text like Chinese.
Pitfall 4: Padding = Issues
Some systems mishandle = in URLs. URL-safe Base64 typically omits =, but decoding requires padding to a multiple of 4. Some libraries handle this automatically; others need manual padding.
Pitfall 5: Newline Handling
MIME Base64 inserts a newline every 76 characters. Decoding MIME-formatted data with a standard decoder requires removing newlines first.
Language Reference
| Language | Encode | Decode |
|---|---|---|
| JS (Browser) | btoa(str) |
atob(b64) |
| Node.js | Buffer.from(str).toString('base64') |
Buffer.from(b64, 'base64') |
| Python | base64.b64encode(data) |
base64.b64decode(b64) |
| Go | base64.StdEncoding.EncodeToString(data) |
base64.StdEncoding.DecodeString(b64) |
| Java | Base64.getEncoder().encodeToString(bytes) |
Base64.getDecoder().decode(b64) |
Browser Caveat
btoa() / atob() only handle Latin1 characters. For Chinese text:
const encoded = btoa(unescape(encodeURIComponent('中文')));
const decoded = decodeURIComponent(escape(atob(encoded)));
Or use TextEncoder with a manual Base64 implementation.
Performance & Best Practices
- Inline resources under 4KB may use Base64; larger files use binary transfer
- Avoid Base64 for data over 1MB—use Blob URLs or multipart upload
- Use native APIs over pure-JS implementations for high-frequency scenarios
- Storing Base64 in databases increases index size; prefer binary columns
- Cache decoded results to avoid repeated computation