What is Base64?
Base64 is a binary-to-text encoding scheme that converts binary data into an ASCII string. The name comes from the fact that the encoding uses 64 different characters to represent data.
The 64 Characters
Base64 uses:
- A-Z (26 characters)
- a-z (26 characters)
- 0-9 (10 characters)
-
- and / (2 characters)
- = (padding)
Total of 64 characters that are safe to use in most systems.
Why Base64?
Problems Base64 Solves
1. Binary data in text-based systems Many systems are built to handle text, not binary data:
- Email (SMTP)
- JSON and XML
- URL query parameters
- HTML and CSS
2. Safe transmission Base64 uses only characters that are not interpreted specially by various systems:
- No whitespace problems
- No issues with different charsets
- Works in URLs (with Base64URL variant)
3. Data embedding Allows embedding files directly in code or markup:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUg..." />
How Does Base64 Work?
Encoding Process
- Take 3 bytes (24 bits) of data
- Split into 4 groups of 6 bits each
- Convert each group to a Base64 character
- Add padding if necessary
Example: โHiโ
Text: H i
ASCII: 72 105
Binary: 01001000 01101001
Grouped: 010010 000110 1001
Padded: 010010 000110 100100 (padding)
Base64: S G k =
Result: SGk=
Why Does It Get Larger?
Base64 increases size by ~33%:
- 3 bytes โ 4 Base64 characters
- 24 bits โ 32 bits (with padding)
- 100 KB file โ 133 KB Base64
This is the tradeoff for compatibility!
Base64 vs Base64URL
Standard Base64
+ / =
Problematic in URLs because these characters have special meaning.
Base64URL
- _ (no padding)
URL-safe variant used in:
- JWT tokens
- URL parameters
- Filenames
// Standard Base64
"hello+world/test=";
// Base64URL
"hello-world_test";
Common Use Cases
1. Data URLs in HTML/CSS
Embed images directly:
<img src="data:image/png;base64,iVBORw0KG..." alt="Logo" />
Advantages:
- Fewer HTTP requests
- Faster loading for small images
- No external file to handle
Disadvantages:
- Larger HTML size
- Cannot be cached separately
- Not suitable for large images
2. API Authentication
Basic Authentication:
const credentials = btoa("username:password");
// "dXNlcm5hbWU6cGFzc3dvcmQ="
fetch("/api/data", {
headers: {
Authorization: `Basic ${credentials}`,
},
});
JWT Tokens:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Each part is Base64URL-encoded JSON.
3. File Upload Preview
Show image before upload:
function previewImage(file) {
const reader = new FileReader();
reader.onload = (e) => {
const base64 = e.target.result;
document.getElementById("preview").src = base64;
};
reader.readAsDataURL(file);
}
4. Email Attachments
MIME uses Base64 to send attachments:
Content-Type: image/png
Content-Transfer-Encoding: base64
iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI
12P4//8/w38GIAXDIBKE0DHxgljN
BAAO9TXL0Y4OHwAAAABJRU5ErkJggg==
5. Store Binary Data in JSON
{
"filename": "document.pdf",
"content": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBl...",
"encoding": "base64"
}
6. WebSocket Binary Data
const base64Data = btoa(String.fromCharCode(...new Uint8Array(buffer)));
websocket.send(
JSON.stringify({
type: "binary",
data: base64Data,
})
);
JavaScript Implementation
Browser (Native)
Encoding:
// String to Base64
const encoded = btoa("Hello World");
console.log(encoded); // "SGVsbG8gV29ybGQ="
// Decode
const decoded = atob(encoded);
console.log(decoded); // "Hello World"
Unicode Problem:
// This will NOT work!
btoa("Hello ๐"); // Error!
// Solution:
function encodeUnicode(str) {
return btoa(
encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) =>
String.fromCharCode("0x" + p1)
)
);
}
function decodeUnicode(str) {
return decodeURIComponent(
atob(str)
.split("")
.map((c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2))
.join("")
);
}
Node.js
// Encoding
const encoded = Buffer.from("Hello World").toString("base64");
console.log(encoded); // "SGVsbG8gV29ybGQ="
// Decoding
const decoded = Buffer.from(encoded, "base64").toString("utf-8");
console.log(decoded); // "Hello World"
// Base64URL
const base64url = encoded
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=/g, "");
Modern Web API
// TextEncoder/TextDecoder (Unicode-safe)
function base64Encode(str) {
const bytes = new TextEncoder().encode(str);
const binString = String.fromCodePoint(...bytes);
return btoa(binString);
}
function base64Decode(base64) {
const binString = atob(base64);
const bytes = Uint8Array.from(binString, (m) => m.codePointAt(0));
return new TextDecoder().decode(bytes);
}
Performance Tips
1. Large Files
For large files, use streaming:
async function encodeFileInChunks(file) {
const chunkSize = 1024 * 1024; // 1MB chunks
const reader = file.stream().getReader();
let result = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
result += btoa(String.fromCharCode(...value));
}
return result;
}
2. Worker Threads
Move encoding to a Web Worker for large datasets:
// worker.js
self.onmessage = (e) => {
const encoded = btoa(e.data);
self.postMessage(encoded);
};
// main.js
const worker = new Worker("worker.js");
worker.postMessage(largeString);
worker.onmessage = (e) => console.log(e.data);
3. Caching
Cache encoded results when possible:
const cache = new Map();
function cachedEncode(data) {
const key = data.slice(0, 100); // Sample for key
if (cache.has(key)) {
return cache.get(key);
}
const encoded = btoa(data);
cache.set(key, encoded);
return encoded;
}
Security Considerations
1. Base64 is NOT Encryption!
// DANGEROUS - visible to everyone!
const password = btoa("mySecretPassword123");
// "bXlTZWNyZXRQYXNzd29yZDEyMw=="
// Easy to decode:
atob("bXlTZWNyZXRQYXNzd29yZDEyMw==");
// "mySecretPassword123"
Base64 is encoding, not encryption. Never use it to โhideโ sensitive data!
2. Always Validate Input
function safeBase64Decode(str) {
// Validate Base64 format
const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
if (!base64Regex.test(str)) {
throw new Error("Invalid Base64 string");
}
try {
return atob(str);
} catch (e) {
throw new Error("Failed to decode Base64");
}
}
3. Size Limitations
const MAX_SIZE = 10 * 1024 * 1024; // 10MB
function encodeWithLimit(data) {
const encoded = btoa(data);
if (encoded.length > MAX_SIZE) {
throw new Error("Encoded data too large");
}
return encoded;
}
Common Pitfalls
1. Unicode Handling
// Wrong - doesn't work with emoji/unicode
btoa("Hello ๐"); // Error!
// Right - handle unicode correctly
btoa(unescape(encodeURIComponent("Hello ๐")));
2. Newlines in Output
Some Base64 implementations add newlines:
const encoded = "SGVsbG8g\nV29ybGQ=";
const cleaned = encoded.replace(/\n/g, "");
3. Padding
// Standard Base64 - padding required
"SGVsbG8="; // OK
// Base64URL - no padding
"SGVsbG8"; // OK
// Mixed - problematic!
"SGVsbG8-"; // Wrong!
Best Practices
1. Use the Right Variant
- Standard Base64: Email, MIME, general encoding
- Base64URL: JWTs, URL parameters, filenames
- Base64 no-padding: Some databases, compact format
2. Document Encoding
interface FileData {
filename: string;
content: string; // Base64-encoded binary data
encoding: "base64";
mimeType: string;
}
3. Handle Errors Gracefully
function tryDecode(base64String) {
try {
return {
success: true,
data: atob(base64String),
};
} catch (error) {
return {
success: false,
error: "Invalid Base64 string",
};
}
}
4. Consider Alternatives for Large Files
For files > 5MB, consider:
- Direct file upload (multipart/form-data)
- Chunked upload
- Signed URLs (S3, CloudFlare R2)
- Binary WebSocket
Tools
Use our online tools for Base64:
- Base64 Encoder/Decoder - Basic encoding/decoding
- Base64URL Converter - URL-safe variant
- Image to Base64 - Convert images to data URLs
Conclusion
Base64 is an invaluable tool for modern web developers:
Use Base64 for:
- โ Small images in HTML/CSS
- โ API authentication headers
- โ JWT tokens
- โ Email attachments
- โ Binary data in JSON
Avoid Base64 for:
- โ Encryption or security
- โ Large files (>5MB)
- โ Data that needs to be searched/indexed
- โ When direct HTTP uploads are possible
Remember: Base64 is encoding for compatibility, not security or compression!