Core answer: Base64 encodes binary data as 64 safe ASCII characters (A–Z, a–z, 0–9, +, /) at a 33% size cost: every 3 bytes become 4 characters, padded with =. "Hi" → "SGk=". It's encoding, NOT encryption — anyone can decode it instantly. Uses: data URIs, email attachments (MIME), JWT payloads, basic auth headers. URL-safe Base64 swaps +/ for −_ and drops padding.
How the encoding works
3 bytes = 24 bits = 4 groups of 6 bits; each 6-bit group indexes the 64-char alphabet. "Man" (77, 97, 110) → 010011 010110 000101 101110 → T W F u → "TWFu". Leftover bytes pad with =: 2 bytes → 3 chars + one =; 1 byte → 2 chars + ==.
| Input | Base64 |
|---|---|
| "M" | TQ== |
| "Ma" | TWE= |
| "Man" | TWFu |
| "Hello, 世界" | SGVsbG8sIOS4lueVjA== |
Where you meet it daily
- Data URIs: data:image/png;base64,iVBOR... embeds small images in CSS/HTML (saves a request, costs 33% bytes + no caching).
- JWT: header.payload.signature are each base64url — paste any JWT into a decoder to read claims (the signature only proves integrity, payload is NOT secret!).
- HTTP Basic auth: Authorization: Basic dXNlcjpwYXNz = "user:pass" — plaintext-equivalent; only safe over HTTPS.
- Email (MIME): attachments ride as base64 because SMTP was built for 7-bit text.
- Certificates: PEM files are base64 between BEGIN/END lines.
Worked examples
Example 1 — Debugging a JWT. eyJhbGciOi... decodes to {"alg":"HS256","typ":"JWT"}; the middle segment reveals user/role/exp — if sensitive data sits in a JWT payload, that's a leak by design.
Example 2 — Quick CLI. Encode: echo -n "hello" | base64 → aGVsbG8=; decode: echo "aGVsbG8=" | base64 -d. macOS/Linux both ship it.
Example 3 — Size math. A 300 KB PDF inline in JSON becomes 400 KB of base64 plus JSON escaping — for APIs, prefer binary endpoints or pre-signed upload URLs instead.
Common mistakes and myths
- "It's encrypted" — base64 is a public encoding with no key; never use it to "protect" secrets.
- URL breakage — + and / break query strings and paths; use base64url (− and _, no padding) in URLs and JWTs.
- Double-encoding — storing base64 of base64 happens in layered systems; if decoded output looks like base64, check your pipeline.
- Line-wrap variants — MIME wraps at 76 chars; some parsers choke on wrapped vs unwrapped; strip whitespace before decoding.
- Binary-in-JSON without thinking — 33% bloat plus CPU on both ends; fine for avatars, wrong for videos.