TL;DR: Base64 encodes image bytes as text so you can embed them directly in HTML, CSS, or JavaScript. Great for tiny icons (under 4 KB) and self-contained HTML files. Bad for large images because Base64 adds ~33% to file size and kills caching. Use it wisely.
Picture this: instead of referencing an image with a file path like /images/logo.png, you embed the entire image as a long string of text directly inside your HTML or CSS. The browser decodes it on the spot — no separate HTTP request needed. That is what a data URI does, and it is powered by Base64 encoding.
Sounds weird? It kind of is. But it is also incredibly useful in the right situations. Let me explain when it makes sense, when it absolutely does not, and how to actually do it.
Base64 encoding is basically the image version of describing a painting to someone over the phone. It works, but the description is always longer than just showing them the picture.
What is Base64, Anyway?
Base64 is a way to represent binary data (like image bytes — all those 1s and 0s) using only 64 safe, printable characters: A-Z, a-z, 0-9, +, and /. It was originally invented for sending binary files through text-only protocols like email.
The trade-off is size: every 3 bytes of original data become 4 Base64 characters. That means Base64 makes things about 33% bigger. A 10 KB image becomes roughly 13.3 KB as Base64.
The Data URI Format
A data URI wraps the Base64 string with some metadata so the browser knows what to do with it:
data:[media-type];base64,[encoded-data]
// Real examples:
data:image/png;base64,iVBORw0KGgoAAAANS...
data:image/jpeg;base64,/9j/4AAQSkZJRg...
data:image/svg+xml;base64,PHN2ZyB4bWxu...
Using Data URIs in HTML
<!-- Inline image -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUg..."
alt="Small icon"
width="24" height="24">
<!-- Inline favicon (zero network requests!) -->
<link rel="icon"
href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...">
Using Data URIs in CSS
.icon-check {
background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0i...');
background-size: contain;
width: 20px;
height: 20px;
}
/* For SVGs, you can skip Base64 and use URL-encoded text instead */
.icon-arrow {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14' stroke='%23333' fill='none'/%3E%3C/svg%3E");
}
Pro tip for SVGs: skip Base64 entirely and use URL-encoded text instead. It is more readable and actually smaller because you avoid the 33% Base64 overhead.
Converting Images in JavaScript
Here is how to convert a file input to Base64 in the browser:
function fileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
// Usage with a file input
const input = document.querySelector('input[type="file"]');
input.addEventListener('change', async (e) => {
const dataUri = await fileToBase64(e.target.files[0]);
console.log(dataUri);
// "data:image/png;base64,iVBORw0KGgo..."
});
You can also convert from a Canvas element or fetch a URL:
// Canvas to Base64
const canvas = document.querySelector('canvas');
const dataUri = canvas.toDataURL('image/png');
// Fetch a URL and convert
async function urlToBase64(url) {
const response = await fetch(url);
const blob = await response.blob();
return new Promise((resolve) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.readAsDataURL(blob);
});
}
Converting on the Command Line
# macOS / Linux
base64 -i image.png | tr -d '\n'
# With the full data URI prefix
echo -n "data:image/png;base64,$(base64 -i image.png | tr -d '\n')"
When Data URIs Are a Great Idea
- Tiny icons under 4 KB. The 33% size overhead is more than offset by eliminating an HTTP request.
- Email HTML templates. Many email clients block external images by default. Inline images show up without the user clicking "load images."
- Self-contained HTML files. Need to send someone a single HTML file with all images embedded? Data URIs make it possible (reports, invoices, etc.).
- CSS background icons. Small UI icons in CSS avoid the complexity of old-school sprite sheets.
- Favicons. One fewer network request on every page load. Nice.
When Data URIs Are a Terrible Idea
Do NOT Base64-encode large images. A 100 KB image becomes 133 KB, it cannot be cached separately, and it bloats your HTML file. For images over 4-5 KB, use regular files.
- Large images (over 10 KB). The 33% overhead becomes significant, and you lose all caching benefits.
- Images used on multiple pages. A regular file gets cached once and reused across all pages. A data URI is re-downloaded every time its parent HTML/CSS loads.
- Frequently changing images. Updating a data URI means changing the HTML/CSS file, which invalidates its cache for everything.
Performance: The Real Trade-offs
| Factor | External File | Data URI |
|---|---|---|
| HTTP requests | 1 per image | 0 (embedded) |
| File size | Original | ~33% larger |
| Caching | Cached independently | Cached with parent file |
| Gzip benefit | Minimal | Good (text compresses well) |
With HTTP/2 and HTTP/3, the cost of extra requests is much lower than it used to be. The sweet spot for data URIs has shrunk. When in doubt, keep images as separate files and let the browser cache do its thing.
A Note on Security
Data URIs in <img> tags and CSS backgrounds are perfectly safe. However, if your Content Security Policy (CSP) is strict, you might need to allow data: in your img-src directive:
Content-Security-Policy: img-src 'self' data:;
Data URIs are a clever trick that shines in specific scenarios: tiny icons, self-contained documents, and email templates. For everything else, regular image files with proper caching are the better choice. Know when to use each and your sites will be both fast and maintainable.
Try It Yourself
Drop any image into our converter and get the Base64 data URI instantly. Copy as HTML, CSS, or raw Base64.
Open Image to Base64 Converter →