What Is Base64?
Base64 is a binary-to-text encoding scheme that represents binary data using only 64 printable ASCII characters: A-Z, a-z, 0-9, +, and / (plus = for padding). The name "Base64" comes from this 64-character alphabet.
It was designed for a specific problem: some systems (email protocols, XML documents, URLs) were designed to handle text, not raw binary. Base64 lets you embed binary data — images, files, encrypted bytes, cryptographic signatures — in text-only contexts.
Base64 is not encryption. It has no key and provides no security. Decoding is trivial and reversible by anyone. Its purpose is encoding for compatibility, not secrecy.
How Base64 Works
Base64 works by:
- Taking input bytes in groups of 3 (24 bits)
- Splitting each 24-bit group into four 6-bit chunks
- Looking up each 6-bit value in the Base64 alphabet (0–63 → A–Z, a–z, 0–9, +, /)
- If the input isn't a multiple of 3 bytes, adding
=padding characters
Example: encoding "Man"
Input: M a n
ASCII: 77 97 110
Bits: 01001101 01100001 01101110
Group of 24 bits: 010011 010110 000101 101110
Lookup: T W F u
Output: TWFu
Size increase: Base64 output is always 4/3 the size of the input (plus padding). A 3-byte input becomes 4 characters. A 1 MB file becomes ~1.37 MB Base64-encoded.
Padding
If the input length isn't a multiple of 3:
- 1 remaining byte → 2 Base64 characters +
== - 2 remaining bytes → 3 Base64 characters +
=
"M" → TWO= (1 byte input → 4 chars with == padding)
"Ma" → TWE= (2 bytes input → 4 chars with = padding)
"Man"→ TWFu (3 bytes input → 4 chars, no padding)
URL-Safe Base64
Standard Base64 uses + and /, which have special meanings in URLs. Base64url replaces:
+→-/→_- Often omits padding
=(since%3Din URLs is ugly)
Used in: JWTs, OAuth tokens, many web APIs.
Encoding and Decoding in Code
JavaScript (Browser)
// Browser built-ins: btoa (binary to ASCII) and atob (ASCII to binary)
// Encode string to Base64
const encoded = btoa('Hello, World!');
// => 'SGVsbG8sIFdvcmxkIQ=='
// Decode Base64 to string
const decoded = atob('SGVsbG8sIFdvcmxkIQ==');
// => 'Hello, World!'
// ⚠️ btoa/atob only work with Latin-1 characters.
// For Unicode strings, encode to UTF-8 bytes first:
function toBase64(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
(_, p1) => String.fromCharCode(parseInt(p1, 16))
));
}
function fromBase64(b64) {
return decodeURIComponent(atob(b64).split('').map(
c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
).join(''));
}
// Or use the modern TextEncoder approach:
function toBase64Modern(str) {
const bytes = new TextEncoder().encode(str);
let binary = '';
for (const b of bytes) binary += String.fromCharCode(b);
return btoa(binary);
}
JavaScript (Node.js)
// Node.js — Buffer
const text = 'Hello, World!';
// Encode
const encoded = Buffer.from(text).toString('base64');
// => 'SGVsbG8sIFdvcmxkIQ=='
// Base64url (no padding, URL-safe chars)
const encodedUrl = Buffer.from(text).toString('base64url');
// Decode
const decoded = Buffer.from('SGVsbG8sIFdvcmxkIQ==', 'base64').toString('utf8');
// => 'Hello, World!'
// Encode a file
const { readFileSync } = require('fs');
const fileBase64 = readFileSync('/path/to/image.png').toString('base64');
Python
import base64
# Encode bytes
encoded = base64.b64encode(b'Hello, World!')
print(encoded) # b'SGVsbG8sIFdvcmxkIQ=='
print(encoded.decode()) # 'SGVsbG8sIFdvcmxkIQ=='
# Decode
decoded = base64.b64decode('SGVsbG8sIFdvcmxkIQ==')
print(decoded) # b'Hello, World!'
# URL-safe Base64
url_encoded = base64.urlsafe_b64encode(b'binary data here')
url_decoded = base64.urlsafe_b64decode(url_encoded)
# Encode a file
with open('image.png', 'rb') as f:
img_b64 = base64.b64encode(f.read()).decode()
Go
import "encoding/base64"
// Encode
encoded := base64.StdEncoding.EncodeToString([]byte("Hello, World!"))
// => "SGVsbG8sIFdvcmxkIQ=="
// URL-safe (no padding)
encodedUrl := base64.RawURLEncoding.EncodeToString([]byte("Hello, World!"))
// Decode
decoded, err := base64.StdEncoding.DecodeString("SGVsbG8sIFdvcmxkIQ==")
Common Use Cases
1. Data URLs (Inline Images in HTML/CSS)
Embed images directly in HTML or CSS without separate HTTP requests:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..." />
.icon {
background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL...');
}
Good for small icons and critical images that shouldn't require separate requests. Avoid for large images — Base64 increases size by 33% and prevents caching.
2. JWT (JSON Web Tokens)
A JWT is three Base64url-encoded parts separated by dots:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
^header^ ^payload^ ^signature^
Decoding the header: atob('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9') → {"alg":"HS256","typ":"JWT"}
3. Email Attachments (MIME)
SMTP was designed for ASCII text. Email clients encode attachments as Base64 in MIME parts:
Content-Type: image/jpeg
Content-Transfer-Encoding: base64
/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsL...
4. Storing Binary in JSON
JSON doesn't support binary. When an API needs to return binary data (e.g., a thumbnail, an encrypted blob) inside a JSON response, Base64 encoding is the standard approach:
{
"id": "file-123",
"thumbnail": "data:image/webp;base64,UklGRiQAAABXRUJQVlA4...",
"encrypted_key": "c2VjcmV0a2V5..."
}
5. Basic Authentication Header
HTTP Basic Auth sends credentials as Base64(username:password):
Authorization: Basic dXNlcjpwYXNzd29yZA==
atob('dXNlcjpwYXNzd29yZA==') → user:password
This is Base64, not encryption — always use HTTPS with Basic Auth. The encoding only prevents casual observation, not interception.
6. Cryptographic Keys and Certificates
PEM files (the ones that start with -----BEGIN CERTIFICATE-----) contain Base64-encoded DER binary data:
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIUMTIzNDU2Nzg5MEFCQ0RFRjAxMjM0NTY3ODkwMTIz...
-----END CERTIFICATE-----
Common Mistakes
Encoding instead of encrypting: Base64 is trivially reversible. Never "protect" sensitive data with just Base64.
Not handling Unicode in browsers: btoa() throws on non-Latin-1 characters. Use TextEncoder or the percent-encoding approach shown above.
Forgetting padding when decoding: Some systems strip the = padding. When decoding, you may need to add it back: b64 + '='.repeat((4 - b64.length % 4) % 4).
Using wrong variant: Standard Base64 (+, /) vs Base64url (-, _). Using the wrong one causes decode failures.
→ Encode and decode Base64 strings instantly with the Base64 String Converter.