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 →