Base64 Image Encoding — Data URIs for HTML & CSS
A Base64 data URI embeds image data directly in HTML or CSS — no separate file, no extra HTTP request. The format is data:image/png;base64,.... It's ideal for small assets, but has important performance tradeoffs to understand.
The Data URI Format
data:[mediatype][;base64],[data] Examples: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA... data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv... data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEK... data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgA...
Using Data URIs in HTML
<!-- In an img tag --> <img src="data:image/png;base64,iVBORw0KGgo..." alt="Logo" width="32" height="32"> <!-- In an SVG --> <image href="data:image/png;base64,iVBORw0KGgo..." width="100" height="100"/> <!-- In a link (favicon) --> <link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4...">
Using Data URIs in CSS
/* Background image */
.logo {
background-image: url('data:image/png;base64,iVBORw0KGgo...');
width: 32px;
height: 32px;
background-size: contain;
}
/* Cursor */
.custom-cursor {
cursor: url('data:image/png;base64,...') 8 8, auto;
}
/* CSS content property */
.icon::before {
content: url('data:image/svg+xml;base64,...');
}
Generating Data URIs
In the Browser (JavaScript)
// From a File object (e.g., file input or drag-drop)
function imageToDataURI(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = e => resolve(e.target.result); // Full data URI
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
// From a canvas
const canvas = document.getElementById('myCanvas');
const dataURI = canvas.toDataURL('image/png'); // PNG
const jpegURI = canvas.toDataURL('image/jpeg', 0.9); // JPEG at 90% quality
// From an img element
function imgToDataURI(imgElement) {
const canvas = document.createElement('canvas');
canvas.width = imgElement.naturalWidth;
canvas.height = imgElement.naturalHeight;
canvas.getContext('2d').drawImage(imgElement, 0, 0);
return canvas.toDataURL();
}
In Python
import base64, mimetypes
def image_to_data_uri(path: str) -> str:
mime = mimetypes.guess_type(path)[0] or 'image/png'
with open(path, 'rb') as f:
encoded = base64.b64encode(f.read()).decode('ascii')
return f"data:{mime};base64,{encoded}"
print(image_to_data_uri('logo.png')[:60])
# data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA...
In Node.js
const fs = require('fs');
const path = require('path');
function imageToDataURI(filePath) {
const ext = path.extname(filePath).slice(1).toLowerCase();
const mimeMap = { png: 'image/png', jpg: 'image/jpeg', jpeg: 'image/jpeg',
gif: 'image/gif', svg: 'image/svg+xml', webp: 'image/webp' };
const mime = mimeMap[ext] || 'image/png';
const base64 = fs.readFileSync(filePath).toString('base64');
return `data:${mime};base64,${base64}`;
}
When to Use Base64 Images
Good use cases:
- Small icons and favicons (< 2KB)
- Inline SVG logos that need to be embeddable
- Images in emails (many email clients block external images)
- Single-file HTML pages or offline apps
- Critical above-the-fold images to eliminate render-blocking requests
Avoid for:
- Large images (> 5KB) — the ~33% size overhead hurts significantly
- Images used on multiple pages — they can't be browser-cached separately
- Images that change frequently — embedded data URIs require re-deploying HTML/CSS
SVG as Base64 vs Inline SVG
For SVG images specifically, inline SVG is usually better than Base64:
<!-- Base64 SVG (larger, can't be styled with CSS) -->
<img src="data:image/svg+xml;base64,PHN2Zy...">
<!-- Inline SVG (smaller, styleable, accessible) -->
<svg viewBox="0 0 24 24"><path d="M12 2..."></svg>
<!-- URL-encoded SVG in CSS (no Base64 overhead for simple SVGs) -->
background-image: url("data:image/svg+xml,%3Csvg...");
Convert your image to Base64 now
Drag and drop your image into base64.dev's Image mode to get the full data URI instantly.
Open base64.dev →