---
url: https://findutils.com/blog/base64-images-in-css-and-html-when-a-data-uri-helps-and-when-it-hurts
title: "Base64 Images in CSS and HTML: When a Data URI Helps and When It Hurts"
description: "A data URI saves one request but costs about 33% in size, loses separate caching and can be blocked by CSP or email clients. Measured numbers with and without gzip, why SVG should be URL-encoded instead, length limits, and a checklist for when to inline an image."
category: converters
content_type: blog
cluster: image
locale: en
read_time: 8
status: published
author: "olgunozoktas"
published_at: 2026-10-28T08:08:00Z
excerpt: "Inlining an image as a Base64 data URI removes one HTTP request, and that is about the only thing it does better than a normal file. The text is a third larger, gzip wins back most but not all of it, the image can no longer be cached on its own, and some policies and mail apps refuse it. Here is what we measured, why SVG is better URL-encoded, and a short checklist for when a data URI is the right call."
tag_ids: ["converters", "base64", "data-uri", "web-performance", "css"]
tags: ["Converters", "Base64", "Data URI", "Web Performance", "CSS"]
primary_keyword: "base64 image data uri"
secondary_keywords: ["should i use base64 images", "data uri performance", "base64 image size increase", "base64 vs image file", "svg data uri without base64", "data uri caching"]
tool_tag: "image-to-base64"
related_tool: "image-to-base64"
related_tools: ["image-to-base64", "base64-encoder", "image-compressor", "url-encoder-decoder", "css-minifier", "image-resizer"]
updated_at: "2026-10-28T08:08:00Z"
og_image: "/images/content/blog/base64-images-in-css-and-html-when-a-data-uri-helps-and-when-it-hurts-cover-20261028.webp"
image_alt: "A balance scale on a dark navy background: on one side a small image file with a single arrow for one request, on the other a longer bar of Base64 characters marked +33%, with a small padlock and envelope icon below."
---

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](https://www.rfc-editor.org/rfc/rfc2397) 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](https://developer.mozilla.org/en-US/docs/Web/URI/Reference/Schemes/data) 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](https://www.rfc-editor.org/rfc/rfc4648)), 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:

| File | Original | Base64 | Original, gzipped | Base64, gzipped |
|---|---|---|---|---|
| 16 × 16 PNG | 82 B | 112 B | 96 B | 121 B |
| 563-byte SVG icon | 563 B | 752 B | 323 B | 470 B |
| 256 × 256 PNG logo | 38,037 B | 50,716 B | 37,834 B | 38,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](https://web.dev/articles/optimize-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)](https://www.rfc-editor.org/rfc/rfc9113) 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
.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](https://css-tricks.com/probably-dont-base64-svg/) reached the same conclusion with three icons of its own. The [URL Encoder/Decoder](/network/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](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/img-src)).

**Email.** [Can I email](https://www.caniemail.com/features/image-base64/) 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 URI | Use a normal image file |
|---|---|
| A tiny icon or pattern used on one page | Any photo or hero image |
| A self-contained HTML report, demo or offline file | An image repeated across many pages |
| Test fixtures and snapshots that must not depend on files | Images in a stylesheet that changes often |
| An SVG, written URL-encoded rather than Base64 | Email newsletters (Gmail will not show it) |
| A placeholder that must show before any other request | Sites 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](/convert/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](/guides/image-to-base64-guide/) walks through each output. To shrink an image before encoding, use the [Image Resizer](/convert/image-resizer/) and the [Image Compressor](/convert/image-compressor/). To decode a string back, use the [Base64 Encoder](/developers/base64-encoder/).

Need help with a project? The team behind FindUtils takes on freelance work through [Upwork](https://www.upwork.com/freelancers/~010a5875eab37b4bd7), including [turning a Figma or PSD design into pixel-perfect responsive HTML](https://www.upwork.com/services/product/design-pixel-perfect-html-file-converted-from-your-figma-or-psd-designs-1420455944316268544).

## 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.

## Related Reading

- [Image to Base64 guide: turn an image into a data URI for HTML, CSS and email](/guides/image-to-base64-guide/)
- [Complete guide to Base64 encoding](/guides/complete-guide-to-base64-encoding/)
- [URL encoding explained: percent-encoding and query strings](/blog/url-encoding-explained-percent-encoding-and-query-strings/)
- [Why CSS minification still matters](/blog/why-css-minification-still-matters/)

## Sources

- [RFC 2397: The "data" URL scheme](https://www.rfc-editor.org/rfc/rfc2397)
- [RFC 4648: The Base16, Base32, and Base64 Data Encodings](https://www.rfc-editor.org/rfc/rfc4648)
- [RFC 9113: HTTP/2](https://www.rfc-editor.org/rfc/rfc9113)
- [MDN: data: URLs](https://developer.mozilla.org/en-US/docs/Web/URI/Reference/Schemes/data) (length limits, top-level navigation)
- [MDN: Base64](https://developer.mozilla.org/en-US/docs/Glossary/Base64)
- [MDN: CSP img-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/img-src)
- [web.dev: Optimize Largest Contentful Paint](https://web.dev/articles/optimize-lcp)
- [Can I email: Base 64 image format](https://www.caniemail.com/features/image-base64/)
- [CSS-Tricks: Probably Don't Base64 SVG](https://css-tricks.com/probably-dont-base64-svg/)
