What base64 actually does
Base64 takes any binary input and emits a string made of just 64 ASCII characters (A–Z, a–z, 0–9, + and /). Every 3 bytes of binary input become 4 characters of output, which means the encoded string is always ~33% longer than the original.
It is not encryption. Anyone who sees the encoded string can instantly decode it. It is also not compression — it makes things bigger, not smaller. Its job is to make binary data safe to transport through channels that only accept plain text: JSON, URLs, email headers, XML attributes.
When base64 is the right answer
- Embedding a tiny image in CSS or HTML via a data: URI. Single-pixel trackers, a small icon, a logo under 4 KB. Avoids a separate HTTP request.
- Encoding binary bytes inside a JSON payload. APIs that carry file contents use base64 because JSON strings are text.
- JWT header and payload. The JWT spec uses URL-safe base64 (with - and _ instead of + and /) so tokens can sit in URLs and cookies.
- Email attachments. SMTP is technically a 7-bit ASCII protocol; base64 is how binary attachments survive transit.
- PEM-encoded certificates and keys. The -----BEGIN CERTIFICATE----- block wraps base64.
When to reach for something else
There is a mistake people make about once a year: base64-encoding large payloads "for safety". It makes them 33% bigger, and if you have somewhere they can go as raw binary, that is almost always better. Specifically:
- Images on a webpage. Use <img src="..."> — base64 data URIs cost more bytes and cannot be cached separately.
- File uploads. multipart/form-data is a binary protocol; it does not need base64.
- Large certificates in environment variables. Use a file path instead, or use base64 only for the PEM wrapper.
- Passwords. Encoding is not encryption. If a password is in your config, encoding it in base64 offers zero protection.
URL-safe vs standard base64
Standard base64 uses +, /, and = (padding). These characters have special meanings in URLs — / is a path separator, + encodes a space in query strings. URL-safe base64 swaps + for -, / for _, and drops the padding.
Use URL-safe when:
- Encoding a token for use in a URL query parameter.
- Encoding a JWT (RFC 7519 requires URL-safe).
- Producing a filename from arbitrary bytes.
Use standard when:
- Writing a PEM certificate (standard is the spec).
- Producing a data: URI (both work; standard is more widely recognised).
- Emailing a binary attachment (standard per RFC 2045).
The encoding that is not actually base64
If you see a 64-character alphabet with a dash and underscore but your decoder complains, you probably have "base64url" or "Go's base64.URLEncoding". These are URL-safe base64 with or without padding. Every real base64 library supports both; the symptom of mismatch is a decode that produces garbled bytes or complains about padding.
The related but distinct encoding "base58" (used in Bitcoin addresses) drops 0, O, I, and l to avoid visual confusion — much shorter alphabet, slower to compute, but human-readable. Base32 (used in QR codes and 2FA secrets) is even shorter and case-insensitive.