A Base64 data URI puts an image's bytes inside your HTML or CSS as text, such as data:image/png;base64,iVBORw0.... It helps in one way: the browser does not have to make a separate request for the image. It hurts in several: the text is about 33% larger than the file, the image can no longer be cached on its own, it delays a stylesheet it sits in, and strict Content Security Policies and some mail apps (Gmail among them) do not show it. A data URI makes sense for a tiny image used in one place, and for files that must be self-contained. For almost everything else, a normal image file is the better choice.

Below are the numbers behind that answer, measured on real files, plus the cases where the usual advice is wrong.

What a Data URI Is

The data: scheme was defined in RFC 2397 in 1998 as a way to "embed (small) media type data directly inline". Its form is:

data:[<mediatype>][;base64],<data>

Without ;base64, the data is written as URL text with %xx escapes. With ;base64, it is Base64, which is the usual choice for binary images such as PNG and JPEG. The RFC itself was modest about it: it calls the scheme "only useful for short values", and says its own example, a small GIF, "is probably near the limit of utility".

Current browsers accept far longer values. MDN lists a limit of 512 MB in Chromium and Firefox and 2048 MB in Safari; Firefox allowed only 256 KB before version 97. So the length limit is no longer the practical constraint. Size, caching and rendering are.

The 33%, and What Compression Does to It

Base64 writes every 3 bytes as 4 characters from a 64-character alphabet (RFC 4648, section 4), so the text is 4/3 the size of the file, plus up to two = padding characters. That part is fixed.

What reaches the user also depends on HTTP compression. We encoded three files and gzipped both the original and the Base64 text at level 9:

FileOriginalBase64Original, gzippedBase64, gzipped
16 × 16 PNG82 B112 B96 B121 B
563-byte SVG icon563 B752 B323 B470 B
256 × 256 PNG logo38,037 B50,716 B37,834 B38,262 B

Two different stories come out of this:

  • Already-compressed images (PNG, JPEG, WebP) barely compress further, but their Base64 text compresses back to almost the original size: 38,262 bytes against 37,834 for the logo, about 1% more on the wire. The 33% overhead is mostly a parsing and memory cost, not a download cost, when compression is on.
  • Text images (SVG) suffer more. The gzipped SVG is 323 bytes; gzipped Base64 of the same SVG is 470 bytes, 46% larger. Base64 hides the repetition in the markup that gzip would otherwise remove.

So "Base64 adds 33%" is true of the text, and only roughly true of the transfer. It is the other costs that usually decide the question.

The Cost That Matters Most: Caching

A data URI has no URL of its own. It is cached, or not, as part of the file that contains it. That changes several things:

  • Repeated images are downloaded repeatedly. A logo inlined in the HTML of every page is sent again with every page. As a file, it would be fetched once and served from the cache afterwards.
  • Any change invalidates everything around it. Edit one rule in a stylesheet that holds ten inlined icons, and visitors download the icons again with the new stylesheet.
  • You cannot give images their own cache rules. Image files usually change rarely and can be cached for a long time, while HTML is often revalidated on each visit. Inlining ties the image to the shortest lifetime of its host file.

Google's web.dev guide to LCP sums it up: inlining a small resource as a data URL removes the request, but such resources "cannot be cached and in some cases can lead to longer render delays because of the additional decode cost." The same guide makes the same point about inlined stylesheets: "inlined content in the HTML cannot benefit from caching in subsequent page loads."

Rendering: Where the Image Sits Matters

In CSS, a data URI makes the stylesheet bigger, and stylesheets block rendering. As web.dev puts it, style sheets loaded from the HTML "will block rendering of all content that follows them", so every icon inlined in the main stylesheet delays the first paint of every page, including pages that never use the icon.

In HTML, an inlined <img> adds to the document size but needs no further request, so the image is ready as soon as that part of the HTML is parsed. For a tiny above-the-fold image, that can be a small win. For a large one, it pushes the rest of the page further down the download, and loading="lazy" cannot help, because the bytes are already in the document.

The request you save is cheaper than it used to be. Much of the old case for inlining came from the cost of each extra request over HTTP/1.1. HTTP/2 (RFC 9113) allows "multiple concurrent exchanges on the same connection", so one more small file from the same site no longer has to wait for a free connection.

SVG: Skip Base64, URL-Encode Instead

SVG is text, so it can go into a data URI without Base64. Only a few characters need percent-encoding: <, >, #, %, and quotes that clash with the surrounding url("...").

CSS
1
2
3
.star {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E...%3C/svg%3E");
}

For our 563-byte icon, the Base64 data URI was 778 characters and the URL-encoded one 594. The gap grows with repetition: a stylesheet with the same icon in two colours was 1,614 bytes (561 gzipped) with Base64 and 1,256 bytes (396 gzipped) URL-encoded. CSS-Tricks reached the same conclusion with three icons of its own. The URL Encoder/Decoder handles the escaping if you do not want to do it by hand.

Two Places a Data URI Is Simply Blocked

Content Security Policy. The 'self' source does not cover data: URLs. In our Chrome test, a page with img-src 'self' refused a data URI image and logged a CSP violation; the image appeared only after the policy became img-src 'self' data:. If your site has a strict policy, inlined images need that explicit permission (MDN: img-src).

Email. Can I email reports that Gmail does not display Base64 images on the web or in its iOS and Android apps (the desktop result was retested in May 2024), and neither does Outlook for Windows 2007 to 2016. Apple Mail, Outlook.com, Yahoo Mail and Thunderbird do. For a newsletter, a hosted image or an inline (CID) attachment reaches more readers.

When to Use a Data URI

Use a data URIUse a normal image file
A tiny icon or pattern used on one pageAny photo or hero image
A self-contained HTML report, demo or offline fileAn image repeated across many pages
Test fixtures and snapshots that must not depend on filesImages in a stylesheet that changes often
An SVG, written URL-encoded rather than Base64Email newsletters (Gmail will not show it)
A placeholder that must show before any other requestSites with a strict CSP you do not want to loosen

If you do inline, make the file as small as possible first. Scale it to the size it is displayed at, compress it, then encode it. Base64 never makes a file smaller, so every byte you remove beforehand saves 4/3 of a byte afterwards.

Try It on Your Own Images

The FindUtils Image to Base64 converter shows the original size and the Base64 size side by side, and copies the result as raw Base64, a data URI, a CSS line or an <img> tag. The Image to Base64 guide walks through each output. To shrink an image before encoding, use the Image Resizer and the Image Compressor. To decode a string back, use the Base64 Encoder.

Need help with a project? The team behind FindUtils takes on freelance work through Upwork, including turning a Figma or PSD design into pixel-perfect responsive HTML.

FAQ

Does Base64 make images load faster?

Only in narrow cases. It removes one request, which helps for a tiny image on a single page. For larger or repeated images it is usually slower, because the image is no longer cached separately and makes the HTML or CSS bigger.

How much bigger is a Base64 image?

The text is about 33% larger: 4 characters for every 3 bytes. With gzip, an already-compressed PNG came within about 1% of its original size on the wire in our test, but a Base64 SVG stayed 46% larger than the gzipped SVG.

Is there a size limit for data URIs?

Not a practical one in current browsers. MDN lists 512 MB for Chromium and Firefox and 2048 MB for Safari. The real limits are performance and caching.

Should I Base64-encode SVG?

Usually not. A URL-encoded SVG data URI is shorter and compresses better. Encode <, >, #, % and clashing quotes, and leave the rest as text.

Why does my data URI image not show up?

The usual causes are a Content Security Policy without data: in img-src, an email client such as Gmail that strips Base64 images, or a wrong media type or a missing comma in the URI itself.

Sources