Toolmingo
Guides7 min read

What Is a Data URI (and When Should You Use One)?

A data URI embeds a file directly into HTML or CSS as base64 text. Learn the format, browser limits, performance trade-offs, and practical code examples in JavaScript, Python, Go, and PHP.

What Is a Data URI?

A data URI (also called a data URL) lets you embed a file — an image, font, SVG, or any binary asset — directly into a web page as a base64-encoded text string, instead of referencing an external file by URL. You have probably seen one: they start with data: and look something like this:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...

That entire string can go anywhere a URL normally goes — an <img> src, a CSS background-image, a <link> href for a font, or an anchor href for a downloadable file. No HTTP request is made; the browser decodes the string in place.


The Data URI Format

Every data URI follows this structure:

data:[<mediatype>][;base64],<data>
Part Example Meaning
data: data: Scheme — tells the browser this is inline data
<mediatype> image/png MIME type of the content (defaults to text/plain;charset=US-ASCII if omitted)
;base64 ;base64 Encoding flag — omit for plain text, include for binary
,<data> ,iVBOR… The actual content (base64-encoded if ;base64 is present, percent-encoded otherwise)

Plain-text example (no base64 needed)

<a href="data:text/plain,Hello%20world">Download text file</a>

Binary image example (base64 required)

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" alt="1px red dot" width="1" height="1">

SVG example (can stay as percent-encoded text)

<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100'%3E%3Ccircle cx='50' cy='50' r='50' fill='red'/%3E%3C/svg%3E" alt="red circle">

SVG is often cleaner without base64 because the XML is human-readable once decoded.


How to Create a Data URI

JavaScript (browser)

// From a File or Blob (e.g., user-uploaded image)
function fileToDataUri(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = reject;
    reader.readAsDataURL(file); // produces "data:image/png;base64,..."
  });
}

// Usage
const input = document.querySelector('input[type="file"]');
input.addEventListener('change', async (e) => {
  const uri = await fileToDataUri(e.target.files[0]);
  document.querySelector('img').src = uri;
});
// From a URL (Node.js / fetch)
const res = await fetch('https://example.com/logo.png');
const buf = Buffer.from(await res.arrayBuffer());
const dataUri = `data:image/png;base64,${buf.toString('base64')}`;

Python

import base64
import mimetypes
from pathlib import Path

def file_to_data_uri(path: str) -> str:
    p = Path(path)
    mime, _ = mimetypes.guess_type(p)
    mime = mime or "application/octet-stream"
    encoded = base64.b64encode(p.read_bytes()).decode()
    return f"data:{mime};base64,{encoded}"

uri = file_to_data_uri("logo.png")
# → "data:image/png;base64,iVBORw0KGgo..."

Go

package main

import (
    "encoding/base64"
    "fmt"
    "mime"
    "os"
    "path/filepath"
)

func fileToDataURI(path string) (string, error) {
    data, err := os.ReadFile(path)
    if err != nil {
        return "", err
    }
    ext := filepath.Ext(path)
    mimeType := mime.TypeByExtension(ext)
    if mimeType == "" {
        mimeType = "application/octet-stream"
    }
    encoded := base64.StdEncoding.EncodeToString(data)
    return fmt.Sprintf("data:%s;base64,%s", mimeType, encoded), nil
}

PHP

function fileToDataUri(string $path): string {
    $data = file_get_contents($path);
    if ($data === false) {
        throw new RuntimeException("Cannot read: $path");
    }
    $mime = mime_content_type($path) ?: 'application/octet-stream';
    $encoded = base64_encode($data);
    return "data:$mime;base64,$encoded";
}

$uri = fileToDataUri('logo.png');
// → "data:image/png;base64,iVBOR..."

When to Use Data URIs

Good use cases

Use case Why data URIs work well
Small icons and logos in HTML email Email clients block external images; inline base64 always loads
Critical above-the-fold images in static HTML Zero HTTP round-trip, guaranteed availability
SVG icons in CSS Eliminates a separate asset request for a tiny file
Downloadable blobs generated in the browser <a href="data:…" download="file.csv"> triggers download without a server
Favicons embedded in <link> Single-file HTML pages that must be fully self-contained

Bad use cases

Use case Problem
Large images (> ~5 KB) Base64 inflates size by ~33 %; plus the browser can't cache the URI separately
Images reused on multiple pages A normal URL is cached once; each page with a data URI re-downloads the encoded string
Performance-critical pages Data URIs block HTML parsing; a normal <img> is loaded asynchronously
Logos with many breakpoints Responsive images (srcset) don't work with data URIs

The rule of thumb: data URIs make sense when the file is small and either unique to the page or must be self-contained (email, offline HTML).


Data URI Size Limits

Browsers do not enforce a universal limit, but practical ceilings exist:

Context Effective limit
All modern browsers (img, CSS) 2 MB–32 MB (varies by browser)
Internet Explorer 8 32 KB (long obsolete but worth knowing)
URL bar / navigation ~2 KB on most browsers
HTML email clients Varies; some reject data URIs entirely

For typical use, anything under a few hundred kilobytes works reliably. Beyond that, prefer a normal URL.


Data URI vs URL vs Blob URL

Feature Data URI File URL Blob URL
Created Statically embedded External file on disk or server URL.createObjectURL(blob) in JS
HTTP request None Yes (server) or No (local) None
Browser cache Not cacheable as a URL Yes Not cacheable across sessions
Size overhead +33 % (base64) None None
Lifetime Permanent in HTML While server is up Until URL.revokeObjectURL()
Best for Self-contained pages, email Most web assets Temporary in-browser previews

For in-browser image previews (e.g., before upload), a Blob URL (URL.createObjectURL) is faster to create and uses no extra memory for encoding — prefer it over FileReader.readAsDataURL when you only need a temporary src.


Quick Reference

# Full syntax
data:[mediatype][;charset=<charset>][;base64],<data>

# Common MIME types
data:image/png;base64,…
data:image/jpeg;base64,…
data:image/svg+xml,…            ← SVG can stay percent-encoded
data:image/gif;base64,…
data:image/webp;base64,…
data:text/plain;charset=utf-8,Hello
data:text/html,<h1>Hello</h1>
data:application/json,{"key":"value"}
data:font/woff2;base64,…
data:application/pdf;base64,…

# Inline CSS background
background-image: url("data:image/png;base64,…");

# Downloadable link
<a href="data:text/csv;charset=utf-8,name%2Cage%0AAlice%2C30" download="data.csv">Download CSV</a>

Common Pitfalls

1. Forgetting ;base64 for binary files Binary data without the ;base64 flag is interpreted as percent-encoded text. The result will be garbled or a parser error.

2. Using data URIs for large images A 100 KB PNG becomes a 133 KB base64 string — and can't be cached separately. Every page load re-parses it. Use a real URL for anything larger than a small icon.

3. Embedding data URIs in HTML email Some email clients (notably Gmail) strip <img> data URIs citing security policy. SVG data URIs are often blocked entirely. Test with your target clients.

4. Assuming they're safe for user-supplied content Never construct a data URI from untrusted content without sanitization — data:text/html,<script>…</script> executes JavaScript in older browsers. Modern browsers restrict this for security, but the safest approach is to avoid text/html data URIs with user content entirely.

5. Confusing data URIs with Blob URLs blob:https://example.com/… looks similar but is a temporary in-memory reference, not inline data. They behave differently in caching, serialization, and across page loads.

6. SVG data URIs with unescaped characters SVG strings containing <, >, ", or # must be percent-encoded (or base64-encoded) before embedding. Unescaped characters break the URL parser.


FAQ

What is the difference between a data URI and a data URL?

The terms are interchangeable. Officially they are URIs (Uniform Resource Identifiers); developers commonly call them data URLs because they are used in places that normally take a URL.

Does base64 encoding make data URIs secure?

No. Base64 is encoding, not encryption. Anyone can decode the string to recover the original file instantly. Do not embed secrets in data URIs.

Can I use a data URI as an href in an anchor tag?

Yes — and it's one of the most useful patterns. Set the download attribute to trigger a save dialog: <a href="data:text/csv,…" download="export.csv">Download</a>. The file is generated entirely in the browser without a server request.

Are data URIs blocked by Content Security Policy?

They can be. img-src 'self' data: must be present in your CSP to allow data URIs in <img> tags. Stricter policies that omit data: will silently block them. Check your CSP header if data URIs stop loading in production.

What MIME type should I use for a binary file I don't recognize?

application/octet-stream — the generic binary fallback. Browsers will treat it as a download rather than attempting to render it.

Can I use a data URI for a CSS @font-face?

Yes. Embedding fonts as data URIs eliminates the font request and avoids flash-of-unstyled-text (FOUT). The trade-off is page size: a typical variable font can be 100–300 KB, adding significant base64 overhead. Only worthwhile for tiny subsetted fonts used on every page.

Related tools

Keep reading

All Toolmingotools are free & run in your browser

No sign-up, no upload, no watermark. Your files never leave your device.

Browse all tools