Data URLs embed content directly in a URL using Base64 encoding. They're useful for small images, SVGs, and inline content without external requests.
Data URLs eliminate HTTP requests by embedding content directly in your HTML or CSS. This can improve performance for small assets by reducing round trips, but the trade-off is increased document size and lack of caching. Understanding when to use data URLs helps you make the right performance decisions.
Key Takeaways
- 1Data URLs embed content directly in the URL
- 2Base64 encoding increases size by ~33%
- 3Best for small files (< 10KB)
- 4Not cached separately by browsers
- 5Useful for CSS backgrounds and small icons
"Some applications that use URLs also have a need to embed small media type data directly inline. This document defines a new URL scheme that would work like an immediate address."
Data URL Structure
Data URLs have a specific format that specifies the content type and encoding. The data itself can be plain text, URL-encoded, or Base64-encoded, depending on what you're embedding.
# Data URL format
data:[<mediatype>][;base64],<data>
# Components:
data: - Scheme
[mediatype] - MIME type (optional, defaults to text/plain;charset=US-ASCII)
;base64 - Indicates Base64 encoding (optional)
,<data> - The actual data
# Examples:
data:,Hello%20World
# Plain text "Hello World"
data:text/plain;base64,SGVsbG8gV29ybGQ=
# Base64 encoded "Hello World"
data:text/html,<h1>Hello</h1>
# HTML content
data:image/png;base64,iVBORw0KGgo...
# PNG imageThe MIME type tells browsers how to interpret the data. For text content, you can skip Base64 encoding and use URL encoding instead, which is more readable. For binary content like images, Base64 is required.
Let's look at the most common content types you'll use with data URLs.
Common MIME Types
The table below lists MIME types you'll frequently encounter when working with data URLs. Images and SVGs are the most common use cases, but data URLs can embed any content type.
| Type | MIME Type | Example Use |
|---|---|---|
| Plain text | text/plain | Simple text content |
| HTML | text/html | Embedded HTML |
| CSS | text/css | Inline stylesheets |
| JavaScript | text/javascript | Inline scripts |
| JSON | application/json | Configuration data |
| PNG | image/png | Images |
| JPEG | image/jpeg | Photos |
| SVG | image/svg+xml | Vector graphics |
| GIF | image/gif | Animations |
| WebP | image/webp | Modern images |
| application/pdf | Documents |
For images, WebP and SVG offer the best compression. SVG has an advantage over bitmap formats: you can URL-encode it instead of Base64-encoding, resulting in smaller data URLs that are also human-readable.
Now let's look at how to create data URLs programmatically in JavaScript.
Creating Data URLs
JavaScript provides several ways to generate data URLs: from text using btoa(), from files using FileReader, and from canvas elements using toDataURL(). These functions cover the most common scenarios.
// Create data URL from text
function textToDataUrl(text, mimeType = 'text/plain') {
const base64 = btoa(text);
return `data:${mimeType};base64,${base64}`;
}
// Create data URL from file
async function fileToDataUrl(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
// Example usage
const input = document.querySelector('input[type="file"]');
input.addEventListener('change', async (e) => {
const file = e.target.files[0];
const dataUrl = await fileToDataUrl(file);
console.log(dataUrl);
// data:image/png;base64,iVBORw0KGgo...
});
// Create data URL from canvas
const canvas = document.querySelector('canvas');
const dataUrl = canvas.toDataURL('image/png');
// data:image/png;base64,...
// With quality for JPEG
const jpegUrl = canvas.toDataURL('image/jpeg', 0.8);The FileReader.readAsDataURL() method is particularly useful for image upload previews—you can show the image immediately without uploading to a server. For canvas, the second parameter controls JPEG quality (0 to 1), balancing file size against visual quality.
SVG graphics deserve special attention because they can be embedded more efficiently than bitmap images.
SVG Data URLs
SVGs can be embedded either as URL-encoded text or as Base64. URL encoding keeps the SVG readable and is often smaller; Base64 is better for SVGs containing special characters that cause encoding issues.
<!-- SVG as data URL -->
<!-- Option 1: URL-encoded (no Base64) -->
<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='40' fill='red'/%3E%3C/svg%3E">
<!-- Option 2: Base64 encoded -->
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIj48Y2lyY2xlIGN4PSI1MCIgY3k9IjUwIiByPSI0MCIgZmlsbD0icmVkIi8+PC9zdmc+">
<!-- In CSS background -->
<style>
.icon {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2L2 7l10 5 10-5-10-5z'/%3E%3C/svg%3E");
}
</style>// Generate SVG data URL
function svgToDataUrl(svgString, base64 = false) {
if (base64) {
const encoded = btoa(svgString);
return `data:image/svg+xml;base64,${encoded}`;
}
// URL encode for non-Base64
const encoded = encodeURIComponent(svgString)
.replace(/'/g, '%27')
.replace(/"/g, '%22');
return `data:image/svg+xml,${encoded}`;
}
// Example
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><circle cx="50" cy="50" r="40" fill="blue"/></svg>';
const dataUrl = svgToDataUrl(svg);
// Use in img tag or CSSThe svgToDataUrl function handles both encoding approaches. Note that URL-encoded SVGs need careful quoting in CSS—single quotes in the SVG must be escaped or the URL must use double quotes.
Data URLs are particularly useful in CSS for small background images and icons that should load with the stylesheet.
Data URLs in CSS
Embedding small images in CSS eliminates additional HTTP requests and ensures icons load instantly with your stylesheet. This is especially valuable for critical above-the-fold icons.
/* Inline small images */
.icon-star {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='gold' viewBox='0 0 24 24'%3E%3Cpath d='M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z'/%3E%3C/svg%3E");
}
/* Inline small PNG */
.bullet {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...");
}
/* Font face with data URL */
@font-face {
font-family: 'InlineFont';
src: url("data:font/woff2;base64,...") format('woff2');
}
/* Cursor */
.custom-cursor {
cursor: url("data:image/svg+xml,..."), auto;
}Data URLs embedded in CSS are cached along with the stylesheet, giving you the best of both worlds for small, frequently-used images. For larger images or images that change independently, regular URLs with separate caching are better.
Sometimes you need to extract and decode data from a data URL, for example, when processing user-provided content or converting between formats.
Decoding Data URLs
These functions parse data URLs to extract the MIME type and content, and convert between data URLs and Blob objects. The download function shows how to save data URL content as a file.
// Parse and decode data URL
function parseDataUrl(dataUrl) {
const match = dataUrl.match(/^data:([^;,]+)?(?:;([^,]+))?,(.*)$/);
if (!match) {
throw new Error('Invalid data URL');
}
const [, mimeType = 'text/plain', encoding, data] = match;
const isBase64 = encoding === 'base64';
let decoded;
if (isBase64) {
decoded = atob(data);
} else {
decoded = decodeURIComponent(data);
}
return {
mimeType,
isBase64,
data: decoded
};
}
// Convert data URL to Blob
function dataUrlToBlob(dataUrl) {
const { mimeType, data } = parseDataUrl(dataUrl);
// Convert to byte array
const byteArray = new Uint8Array(data.length);
for (let i = 0; i < data.length; i++) {
byteArray[i] = data.charCodeAt(i);
}
return new Blob([byteArray], { type: mimeType });
}
// Download data URL as file
function downloadDataUrl(dataUrl, filename) {
const link = document.createElement('a');
link.href = dataUrl;
link.download = filename;
link.click();
}The parseDataUrl function uses a regex to extract the MIME type, encoding flag, and data. Converting to a Blob allows you to use the data with APIs that expect Blob objects, like FormData for uploads or URL.createObjectURL for display.