Everything About Base64 Encoding - From Principles to Practical Applications
Learn everything about Base64 encoding: what it is, why it's needed, and how to use it with practical examples. From inline images to JWT.
Toolypet Team
Development Team
Everything About Base64 Encoding
"How do I send this image via API?" "How do I put this binary data in JSON?"
The answer is Base64.
This guide covers everything from Base64 principles to practical applications.
What is Base64?
Base64 is an encoding method that converts binary data to text.
Why is it needed?
| Problem | Base64 Solution |
|---|---|
| Cannot send binary via email | Convert to text for transmission |
| Cannot include binary in JSON | Convert to string for inclusion |
| Special characters not allowed in URL | Use only URL-safe characters |
| Inline image embedding in HTML | Convert to Data URL |
Features
- 64 characters used: A-Z, a-z, 0-9, +, / (standard)
- Size increase: Approximately 33% larger than original
- Reversible: Perfect encoding <-> decoding restoration
- Not encryption: Anyone can decode
How Base64 Works
Encoding Process
Original string: "Man"
1. ASCII conversion
M = 77 = 01001101
a = 97 = 01100001
n = 110 = 01101110
2. Split into 6-bit chunks
010011 | 010110 | 000101 | 101110
19 | 22 | 5 | 46
3. Convert to Base64 characters (A=0, B=1, ... Z=25, a=26, ...)
19 = T
22 = W
5 = F
46 = u
Result: "TWFu"
Base64 Character Table
Index: Character
0-25: A-Z
26-51: a-z
52-61: 0-9
62: +
63: /
Padding: =
Padding (=)
If original length is not divisible by 3, add padding
"M" -> "TQ==" (2 padding)
"Ma" -> "TWE=" (1 padding)
"Man" -> "TWFu" (no padding)
Language-Specific Implementation
JavaScript (Browser)
// Encoding
const encoded = btoa('Hello, World!');
console.log(encoded); // "SGVsbG8sIFdvcmxkIQ=="
// Decoding
const decoded = atob('SGVsbG8sIFdvcmxkIQ==');
console.log(decoded); // "Hello, World!"
// Unicode handling (non-ASCII characters)
function encodeUnicode(str) {
return btoa(encodeURIComponent(str).replace(
/%([0-9A-F]{2})/g,
(_, p1) => String.fromCharCode(parseInt(p1, 16))
));
}
function decodeUnicode(str) {
return decodeURIComponent(
Array.from(atob(str), c =>
'%' + c.charCodeAt(0).toString(16).padStart(2, '0')
).join('')
);
}
// Unicode test
const text = 'Hello World';
const encodedText = encodeUnicode(text);
console.log(encodedText);
console.log(decodeUnicode(encodedText)); // "Hello World"
Node.js
// Using Buffer
const encoded = Buffer.from('Hello, World!').toString('base64');
console.log(encoded); // "SGVsbG8sIFdvcmxkIQ=="
const decoded = Buffer.from('SGVsbG8sIFdvcmxkIQ==', 'base64').toString('utf-8');
console.log(decoded); // "Hello, World!"
// File encoding
const fs = require('fs');
const imageBuffer = fs.readFileSync('image.png');
const base64Image = imageBuffer.toString('base64');
console.log(base64Image.substring(0, 50) + '...');
Python
import base64
# Encoding
encoded = base64.b64encode(b'Hello, World!').decode('utf-8')
print(encoded) # "SGVsbG8sIFdvcmxkIQ=="
# Decoding
decoded = base64.b64decode('SGVsbG8sIFdvcmxkIQ==').decode('utf-8')
print(decoded) # "Hello, World!"
# Unicode
text = 'Hello World'
encoded_text = base64.b64encode(text.encode('utf-8')).decode('utf-8')
print(encoded_text)
# File encoding
with open('image.png', 'rb') as f:
base64_image = base64.b64encode(f.read()).decode('utf-8')
Go
package main
import (
"encoding/base64"
"fmt"
)
func main() {
// Encoding
data := "Hello, World!"
encoded := base64.StdEncoding.EncodeToString([]byte(data))
fmt.Println(encoded) // "SGVsbG8sIFdvcmxkIQ=="
// Decoding
decoded, _ := base64.StdEncoding.DecodeString(encoded)
fmt.Println(string(decoded)) // "Hello, World!"
// URL-safe Base64
urlSafe := base64.URLEncoding.EncodeToString([]byte(data))
fmt.Println(urlSafe)
}
Practical Applications
1. Inline Image Embedding (Data URL)
<!-- Embed image directly in HTML -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" alt="1x1 red pixel">
// File -> Base64 Data URL
function fileToDataUrl(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
// Usage
const file = document.getElementById('fileInput').files[0];
const dataUrl = await fileToDataUrl(file);
document.getElementById('preview').src = dataUrl;
2. Sending Images via API
// Client
async function uploadImage(file) {
const base64 = await fileToBase64(file);
const response = await fetch('/api/upload', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
filename: file.name,
contentType: file.type,
data: base64,
}),
});
return response.json();
}
function fileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
// Remove data:image/png;base64, prefix
const base64 = reader.result.split(',')[1];
resolve(base64);
};
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
// Server (Node.js)
app.post('/api/upload', (req, res) => {
const { filename, contentType, data } = req.body;
// Base64 -> Buffer -> Save file
const buffer = Buffer.from(data, 'base64');
fs.writeFileSync(`uploads/${filename}`, buffer);
res.json({ success: true, filename });
});
3. JWT Tokens
// JWT = Header.Payload.Signature (each Base64URL encoded)
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';
// Decode Payload
const payload = token.split('.')[1];
const decoded = JSON.parse(atob(payload));
console.log(decoded);
// { sub: "1234567890", name: "John Doe", iat: 1516239022 }
4. Basic Authentication
// HTTP Basic Authentication
const username = 'user';
const password = 'password';
const credentials = btoa(`${username}:${password}`);
fetch('/api/protected', {
headers: {
'Authorization': `Basic ${credentials}`,
},
});
// Header: Authorization: Basic dXNlcjpwYXNzd29yZA==
5. Email Attachments (MIME)
Content-Type: application/pdf
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="document.pdf"
JVBERi0xLjQKMSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZwovUGFnZXMgMiAwIFIK
Pj4KZW5kb2JqCjIgMCBvYmoKPDwKL1R5cGUgL1BhZ2VzCi9LaWRzIFszIDAgUl0K
...
Base64 Variants
URL-safe Base64
| Standard | URL-safe |
|---|---|
+ | - |
/ | _ |
= | Can be omitted |
// URL-safe encoding
function toUrlSafeBase64(str) {
return btoa(str)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
// URL-safe decoding
function fromUrlSafeBase64(str) {
// Restore padding
const pad = str.length % 4;
const padded = pad ? str + '='.repeat(4 - pad) : str;
return atob(
padded
.replace(/-/g, '+')
.replace(/_/g, '/')
);
}
Base64 vs Base32 vs Base16
| Encoding | Characters | Size Increase | Use Case |
|---|---|---|---|
| Base64 | 64 | +33% | General purpose |
| Base32 | 32 | +60% | Case-insensitive needed |
| Base16 (Hex) | 16 | +100% | Hashes, color codes |
Cautions
1. Not Encryption
// Do NOT use for security
const password = btoa('mySecretPassword');
// Anyone can restore with atob()!
// Encrypt first, then Base64 if needed
const encrypted = await encryptAES(data, key);
const encoded = btoa(encrypted);
2. Size Increase
// Original: 1MB image
// Base64: ~1.33MB (33% increase)
// For large files, direct upload is more efficient
// Use FormData + multipart/form-data
3. Unicode Handling
// Browser btoa() only supports Latin-1
btoa('Special chars'); // Works
// Non-ASCII needs special handling
// Unicode handling required
function encodeUnicode(str) {
return btoa(unescape(encodeURIComponent(str)));
}
4. Line Breaks
// Some systems add line breaks every 76 characters
// MIME standard: 76 character line breaks
// Remove line breaks
const cleaned = base64String.replace(/[\r\n]/g, '');
Performance Optimization
Streaming Encoding
// Process large files in chunks
async function* encodeFileInChunks(file, chunkSize = 1024 * 1024) {
const reader = file.stream().getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
// Base64 encode each chunk
yield Buffer.from(value).toString('base64');
}
}
Web Worker Usage
// worker.js
self.onmessage = function(e) {
const { action, data } = e.data;
if (action === 'encode') {
const result = btoa(data);
self.postMessage({ result });
}
};
// main.js
const worker = new Worker('worker.js');
worker.postMessage({ action: 'encode', data: largeString });
worker.onmessage = (e) => console.log(e.data.result);
Debugging Tools
Base64 Encoder/Decoder
- Enter text or file
- Click encode/decode button
- Copy result
CLI
# Encoding
echo -n "Hello, World!" | base64
# SGVsbG8sIFdvcmxkIQ==
# Decoding
echo "SGVsbG8sIFdvcmxkIQ==" | base64 -d
# Hello, World!
# File encoding
base64 image.png > image.txt
# File decoding
base64 -d image.txt > restored.png
FAQ
Q1: Why does Base64 increase size by 33%?
A: Because 3 bytes (24 bits) are represented as 4 characters (4x6=24 bits).
- 3 bytes -> 4 characters
- Increase: (4-3)/3 = 33%
Q2: Why is padding (=) needed?
A: The decoder needs it to know the original length. The number of padding characters indicates the number of bytes in the last group.
Q3: When should I use Base64URL?
A: When using in URLs or filenames. Standard Base64's + and / have special meaning in URLs, so they're replaced with - and _.
Q4: What are the pros and cons of inline image embedding?
A:
- Pros: Fewer HTTP requests, simplified caching
- Cons: Larger HTML, no individual image caching
- Recommendation: Only use for small icons (under 2KB)
Q5: How do I check if a string is valid Base64?
A: Use regex for format validation, then try decoding:
function isBase64(str) {
const regex = /^[A-Za-z0-9+/]*={0,2}$/;
if (!regex.test(str)) return false;
try {
atob(str);
return true;
} catch {
return false;
}
}
Conclusion
Base64 key points:
- Purpose: Binary -> Text conversion
- Size: 33% larger than original
- Security: Not encryption (anyone can decode)
- Variants: URL-safe uses
-and_ - Applications: Data URL, JWT, Basic Auth, MIME
Related Tools
| Tool | Purpose |
|---|---|
| Base64 Encoder/Decoder | Base64 encoding/decoding |
| JWT Decoder | JWT token analysis |
| JSON Formatter | JSON formatting |
About the Author
Toolypet Team
Development Team
The Toolypet Team creates free, privacy-focused web tools for developers and designers. All tools run entirely in your browser with no data sent to servers.