Short answer: a data URI is the image's raw bytes, base64-encoded, pasted straight into your HTML or CSS as data:image/png;base64,iVBORw0KGgo.... You can make one with an online converter or in the browser with FileReader.readAsDataURL. It saves an HTTP request but inflates the image by about 33% — so it is a win for tiny icons and a loss for photos.
What a data URI actually is
The format is data:[mime type];base64,[encoded bytes]. The mime type tells the browser what the bytes are — image/png, image/jpeg, image/webp, or image/svg+xml — and everything after the comma is the base64 payload. The browser decodes it exactly as if it had downloaded a file, except there is no download: the bytes are already in the document.
Make one in the browser
No server needed. FileReader.readAsDataURL reads a file and hands you the complete data URI, prefix included:
function imageToDataUri(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(reader.error);
reader.readAsDataURL(file);
});
}
// Wire it to a file input
const input = document.querySelector("#upload");
input.addEventListener("change", async (e) => {
const uri = await imageToDataUri(e.target.files[0]);
document.querySelector("#preview").src = uri; // "data:image/png;base64,..."
});When it helps
- Tiny icons and logos: saving one HTTP request outweighs the 33% size penalty when the file is a few kilobytes.
- Email signatures: many email clients block external images until the reader allows them — an embedded data URI renders immediately.
- Single-file HTML: demos, reports, and saved pages that must work with no external assets.
- Blur-up placeholders: embed a tiny low-res preview that shows instantly while the full image loads.
The traps
- The 33% bloat is real: base64 turns every 3 bytes into 4 characters. A 300 KB photo becomes 400 KB of text inside your HTML.
- No separate caching: the image is re-downloaded every time the HTML or CSS file changes, even if the image did not.
- Large data URIs delay rendering: the browser must parse all that text before it can lay out the page.
- Hard to edit: the image is buried in code, invisible to asset pipelines and image optimizers.
Prefer plain SVG for icons
If the icon is a vector, skip base64 entirely and inline the SVG as plain text. It is smaller than the base64 version, you can style it with CSS (fill, stroke, currentColor), and there is nothing to decode. Base64 only wins when the source is already a raster image you cannot replace.
Try it
Drop an image into the Image to Base64 converter and copy the data URI — everything runs in your browser, nothing is uploaded.