Base64 Encoding Explained: How It Works and When to Use It

Binary data in text-only channels — how Base64 solves the compatibility problem, and the performance cost you pay for it.

Developer ToolsApril 11, 20267 min read

The Problem Base64 Solves

Many communication channels — email (SMTP), URLs, JSON, XML, HTML attributes — only safely transmit ASCII text. Binary data (images, compressed files, encryption keys) contains bytes outside the 0–127 ASCII range that get mangled or rejected by these channels.

Base64 solves this by converting any binary data into a string of printable ASCII characters. It takes 3 bytes of input (24 bits), splits them into 4 groups of 6 bits, and maps each 6-bit value to a character in a 64-character alphabet (A–Z, a–z, 0–9, +, /).

The result: any binary data can travel through any text-based channel uncorrupted. The cost: a 33% size increase (3 bytes become 4 characters).

How Base64 Encoding Works

Let's encode the word Man:

Input bytes:  M        a        n
ASCII:        77       97       110
Binary:       01001101 01100001 01101110

Split into 6-bit groups:
              010011  010110  000101  101110
Index:        19      22      5       46
Base64:       T       W       F       u

Result: "TWFu"

Three bytes of input become four characters of output. If the input length isn't a multiple of 3, padding with = fills the gap: one remaining byte gets == padding, two remaining bytes get = padding.

The 33% Size Penalty

This isn't negotiable — it's math. Every 3 bytes of input produce 4 characters of output. On a 1 MB file, the Base64 representation is roughly 1.37 MB. This matters when you're embedding large images as data URIs in HTML or sending binary payloads through JSON APIs.

If you're wondering "should I Base64 encode this?" — the answer is "only if the transport requires it." Sending Base64-encoded data over a channel that already supports binary (like a properly configured HTTP request body) just wastes bandwidth and CPU cycles on both ends.

Real-World Use Cases

Data URIs in HTML and CSS

Embed small images directly in HTML or CSS without separate HTTP requests:

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

/* CSS */
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDov...");

This eliminates an HTTP request for small icons and SVGs, reducing latency. But for images larger than ~10 KB, the bandwidth cost of Base64 inflation usually outweighs the saved round-trip. Always measure.

HTTP Basic Authentication

The Authorization: Basic header encodes credentials as Base64:

# Format: base64("username:password")
echo -n "admin:secret123" | base64
# Output: YWRtaW46c2VjcmV0MTIz

# HTTP header
Authorization: Basic YWRtaW46c2VjcmV0MTIz

Important: Base64 is encoding, not encryption. Anyone who intercepts the request can decode it trivially. Always use Basic Auth over HTTPS only.

Email Attachments (MIME)

Email was designed for 7-bit ASCII text. Binary attachments are Base64-encoded in MIME parts:

Content-Type: image/jpeg; name="photo.jpg"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="photo.jpg"

/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsL
DBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/...

JSON Web Tokens (JWT)

JWTs consist of three Base64URL-encoded segments separated by dots:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.  # Header (Base64URL)
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.  # Payload
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c  # Signature

Note: JWT uses Base64URL, not standard Base64. The difference: + becomes -, / becomes _, and padding = is stripped. This makes JWTs safe to include in URLs without escaping.

Storing Images in Databases

Sometimes you need to store small images (avatars, thumbnails, QR codes) directly in a database column rather than as separate files. Base64 encoding makes binary data database-friendly in columns that expect text (VARCHAR, TEXT). This trades storage efficiency for deployment simplicity — no need for a separate file storage system.

Base64 Variants

VariantAlphabetPaddingUsed By
StandardA–Z a–z 0–9 + /=MIME, PEM certificates
URL-safeA–Z a–z 0–9 - _optionalJWT, URL parameters
Hex (Base16)0–9 A–FnoneSHA hashes, UUIDs
Base32A–Z 2–7=TOTP secrets, Google auth
Base85/Ascii8533–117 (!-u)optionalPostScript, PDF, IPv6

Common Mistakes

Encoding in Code

# Python
import base64
encoded = base64.b64encode(b"Hello, World!").decode()
decoded = base64.b64decode("SGVsbG8sIFdvcmxkIQ==").decode()

# URL-safe variant
safe = base64.urlsafe_b64encode(b"hello?world/yes").decode()

# JavaScript
const encoded = btoa("Hello, World!");   // "SGVsbG8sIFdvcmxkIQ=="
const decoded = atob("SGVsbG8sIFdvcmxkIQ==");  // "Hello, World!"

// For Unicode (btoa only handles Latin1)
const encoded = btoa(unescape(encodeURIComponent("你好世界")));

Key Takeaways