What Is Base64 Encoding? A Developer's Complete Guide
Base64 turns binary data into printable ASCII text. Learn how the algorithm works, why it adds 33% overhead, and when to use it in JWTs, data URIs, and API payloads.
Base64 is a binary-to-text encoding scheme that represents arbitrary binary data using 64 printable ASCII characters. It was not invented to protect data — it has nothing to do with encryption. It was invented to solve a specific, mundane problem: getting binary bytes through text-only channels without corruption.
Email is the canonical example. SMTP, the protocol that carries email, was designed in the 1980s to transfer 7-bit ASCII text. Attaching a binary file — a PNG image, a PDF, an executable — to an email required a way to represent those 8-bit binary bytes as 7-bit safe text. Base64 was the answer, standardized in the MIME specification (RFC 2045) and later formalized on its own in RFC 4648.
How Base64 Works
The algorithm is straightforward. Take any stream of bytes. Group them into chunks of three bytes (24 bits). Split each 24-bit chunk into four groups of six bits. Map each 6-bit value (0–63) to a character in the Base64 alphabet. The result is a string of ASCII characters that can be transmitted over any text channel.
The Base64 alphabet consists of 64 characters: uppercase A–Z (26), lowercase a–z (26), digits 0–9 (10), and the symbols + and / (2). Together these map the values 0–63 to printable characters. A 65th character, =, is used for padding when the input length is not a multiple of three bytes.
Input bytes: 77 61 6E (ASCII "Man")
Binary: 01001101 01100001 01101110
Split 6-bit: 010011 010110 000101 101110
Base64 index: 19 22 5 46
Base64 chars: T W F u
Result: "TWFu"Padding with = Characters
Base64 always produces output in groups of four characters. When the input length is not divisible by three, the final group of output characters must be padded to reach four characters. One trailing input byte produces two Base64 characters followed by ==. Two trailing bytes produce three Base64 characters followed by =. Three bytes produce four characters with no padding.
- 1 remaining byte → 2 Base64 chars + "=="
- 2 remaining bytes → 3 Base64 chars + "="
- 3 remaining bytes → 4 Base64 chars (no padding)
Why Base64 Adds 33% Overhead
Every three input bytes become four output characters. Since each output character is one byte in ASCII, three bytes become four bytes — a 33.3% size increase. A 1 MB binary file Base64-encoded becomes approximately 1.37 MB. This is not compression; it is deliberate expansion to achieve text-only compatibility.
The overhead is acceptable for small payloads — a 200-byte authentication credential or a 2 KB icon. For large files, the overhead matters. Encoding a 10 MB image as Base64 in a JSON API response adds 3.3 MB to every transfer. Use multipart/form-data or direct binary uploads for anything substantial.
Standard Base64 vs URL-Safe Base64
The standard Base64 alphabet includes + and /. These characters have special meanings in URLs: + means space in query strings, and / is the path delimiter. When Base64-encoded data must appear in a URL — such as a JWT token in a query parameter — the URL-safe variant replaces + with - and / with _. This variant is also called Base64url (RFC 4648 §5).
JWT tokens use Base64url encoding for their header and payload segments. The three-part structure header.payload.signature uses Base64url (with padding removed) for the first two segments. When you decode a JWT manually, you must use a Base64url decoder, not standard Base64 — otherwise the - and _ characters cause decode errors.
Common Use Cases
Data URIs in HTML and CSS
A data URI embeds file content directly inside a URL. The format is data:[mediatype];base64,[encoded-data]. This lets you embed small images, fonts, or SVGs directly in HTML or CSS without a separate HTTP request. Webpack's url-loader and similar tools automatically inline assets below a configurable size threshold using data URIs.
<img src="data:image/png;base64,iVBORw0KGgoAAAANS..." alt="icon" />HTTP Basic Authentication
HTTP Basic Auth requires the Authorization header to contain credentials encoded as Base64(username:password). The header looks like Authorization: Basic dXNlcjpwYXNz. Despite appearing obfuscated, this is not secure over plain HTTP — anyone who captures the header can decode it instantly. Basic Auth over HTTPS is acceptable; over HTTP it transmits credentials in the clear.
JSON and GraphQL Payloads with Binary Content
REST APIs and GraphQL mutations that accept binary data (file uploads, images, PDFs) but use JSON bodies must encode the binary content as Base64. JSON has no binary type — only strings, numbers, booleans, null, arrays, and objects. AWS Lambda invocation payloads, SendGrid email attachment fields, and Twilio MMS media all accept binary content as Base64-encoded JSON string fields.
Secrets in CI/CD Pipelines
Service account JSON files, TLS certificates, SSH private keys, and signing keystores are commonly stored as Base64 in CI/CD secrets. GitHub Actions, GitLab CI, and CircleCI store secrets as strings. A raw private key or JSON file with newlines and special characters does not survive safely as a single-line environment variable. Base64-encoding produces a clean single-line string that can be decoded in a pipeline step.
What Base64 Is Not
Base64 is also not compression. It makes data larger, not smaller. If you need to reduce data size before transmission, compress first with gzip or Brotli, then Base64-encode if the channel is text-only. Many APIs that accept Base64 payloads also accept gzip-compressed Base64, giving you compression benefits alongside text-channel compatibility.
UTF-8 and Non-ASCII Characters
JavaScript's native btoa() function only accepts strings where every character has a code point below 256. Passing a string with emoji, Chinese characters, or accented letters throws an error. The correct approach is to convert the string to UTF-8 bytes first using TextEncoder, then Base64-encode the byte array. This ensures characters like € (U+20AC) and 中 (U+4E2D) encode correctly.
function toBase64(str) {
const bytes = new TextEncoder().encode(str);
const binary = Array.from(bytes, b => String.fromCharCode(b)).join('');
return btoa(binary);
}→Base64 Encoder — Free Online ToolEncode any text or data to Base64 instantly in your browser.→Base64 Decoder — Free Online ToolDecode Base64 strings back to plain text instantly.