What Is a Base64-Encoded Image?
Image files are binary — they contain raw bytes that can include any value from0x00 to 0xFF. Many text-only environments (JSON payloads, HTML/CSS inline resources, config files, email MIME parts, environment variables) can't safely hold binary data. Base64 solves this by re-encoding the image bytes into 64 printable ASCII characters that survive any text pipeline.
A Base64-encoded image is roughly 33% larger than the original file (4 output chars per 3 input bytes). That's the trade-off: bigger, but portable in text.
Data URL vs Raw Base64 vs File
| Format | Shape | Where you find it |
|---|---|---|
| Data URL | data:image/png;base64,iVBORw0KG... | CSS background-image, inline <img src> |
| Raw Base64 | iVBORw0KGgoAAAANSUhE... | JSON payloads, database columns, API responses |
| Binary file | image.png (89 50 4E 47 …) | Disk, HTTP body, upload/download |
Detecting Image Format from Base64 (Magic Bytes)
The first few decoded bytes reveal the image format regardless of the data URL prefix:
- PNG — starts with
89 50 4E 47 0D 0A 1A 0A(Base64:iVBORw0K...) - JPEG — starts with
FF D8 FF(Base64:/9j/...) - GIF — starts with
47 49 46 38 (37|39) 61(Base64:R0lGODlh...) - WebP — starts with
52 49 46 46 __ __ __ __ 57 45 42 50(Base64:UklGRi...) - SVG — text-based, decodes to
<?xmlor<svg - BMP — starts with
42 4D(Base64:Qk0...) - AVIF/HEIC — has
66 74 79 70at bytes 4-7 (Base64 varies)
Decoding a Base64 Image in JavaScript (Browser)
function decodeBase64Image(input, fallbackMime = 'image/png') {
let mime = fallbackMime;
let b64 = input.trim();
// Detect data URL and extract MIME
const dataUrlMatch = b64.match(/^data:([^;]+);base64,(.+)$/);
if (dataUrlMatch) {
mime = dataUrlMatch[1];
b64 = dataUrlMatch[2];
}
// Handle URL-safe variants
b64 = b64.replace(/-/g, '+').replace(/_/g, '/');
// Add padding
b64 += '='.repeat((4 - b64.length % 4) % 4);
// Decode
const bytes = Uint8Array.from(atob(b64), c => c.charCodeAt(0));
const blob = new Blob([bytes], { type: mime });
return {
blob,
url: URL.createObjectURL(blob),
size: bytes.length,
mime,
};
}
// Display
const { url, size, mime } = decodeBase64Image(myBase64);
document.getElementById('preview').src = url;
console.log(`${mime}, ${size} bytes`);
// Free memory when done
// URL.revokeObjectURL(url);Decoding a Base64 Image in Python
import base64
import re
def decode_base64_image(input_str, out_path='decoded.png'):
input_str = input_str.strip()
# Extract from data URL if present
m = re.match(r'^data:([^;]+);base64,(.+)$', input_str)
if m:
mime, b64 = m.groups()
# Map common MIMEs to extensions
ext_map = {'image/png': 'png', 'image/jpeg': 'jpg',
'image/gif': 'gif', 'image/webp': 'webp',
'image/svg+xml': 'svg', 'image/bmp': 'bmp'}
ext = ext_map.get(mime, 'bin')
if not out_path.endswith(ext):
out_path = out_path.rsplit('.', 1)[0] + '.' + ext
else:
b64 = input_str
# Normalize URL-safe → standard, add padding
b64 = b64.replace('-', '+').replace('_', '/')
b64 += '=' * (-len(b64) % 4)
# Decode and write
with open(out_path, 'wb') as f:
f.write(base64.b64decode(b64))
return out_path
path = decode_base64_image(my_data_url)
print(f'Saved to {path}')Decoding to a File from Node.js
const fs = require('fs');
function decodeBase64Image(input, outPath = 'decoded.png') {
let b64 = input.trim();
const m = b64.match(/^data:([^;]+);base64,(.+)$/);
if (m) {
const mime = m[1];
b64 = m[2];
// Optionally adjust outPath extension based on MIME
}
fs.writeFileSync(outPath, Buffer.from(b64, 'base64'));
return outPath;
}Common Problems and Fixes
- Preview is blank— the MIME type is wrong. If the input is a data URL, use its prefix. If it's raw Base64, sniff the first bytes to determine the format.
- "Invalid character" in atob()— you left the data URL prefix in the input, or there's a stray newline. Strip everything before the first comma if it starts with "data:".
- Image is corrupt / partial — the Base64 was truncated during copy-paste. Check that the total length matches what you copied.
- SVG shows as text, not image— SVG data URLs sometimes aren't Base64-encoded at all (they use
data:image/svg+xml,%3C...instead). Check the prefix: if it doesn't contain ";base64," the payload is URL-encoded, not Base64-encoded. - Different file size than expected— the decoded size should be roughly (Base64 length × 3/4). If it's way off, you have padding or normalization issues.
Key Facts
- Data URL format:
- data:image/<type>;base64,<encoded-bytes>
- Size overhead:
- ~33% larger than the raw image file
- Supported formats:
- PNG, JPEG, GIF, WebP, SVG, BMP, ICO, AVIF, HEIC
- Browser API:
- atob() + Uint8Array + Blob + URL.createObjectURL
- Server round-trip:
- None — decoding runs entirely client-side
- Max size (browser):
- ~2 MB is comfortable; multi-MB works but slower
Related Base64 Tools
- Base64 Encode Image — the reverse direction (image to Base64)
- Base64 Decode Online — for text, not just images
- Decode Base64 String — cross-language guide
- Base64 Decode JavaScript — atob() + Blob patterns
- Base64 Decode Python — b64decode + file write
- Base64 Encode File — any file, not just images