Developer

Should You Use Base64 Images? Usually Only the Tiny Ones

Inlining saves one request and costs you 33% more bytes, separate caching and lazy loading. The line sits at about a kilobyte.

For anything larger than an icon, no. Inlining an image as a Base64 data URI saves you one network request and costs you 33% more bytes, separate caching, lazy loading and format negotiation. Under about a kilobyte that trade is fine — a bullet icon, a background pattern, a spinner. Above a few kilobytes, the request you avoided was far cheaper than everything you gave up for it.

How much bigger does Base64 make an image?

A third bigger, near enough. Base64 spends four characters on every three bytes, so the increase is a fixed 33%, plus the data:image/png;base64, prefix and up to two = characters of padding. A 12 KB PNG becomes roughly 16 KB of text. That is arithmetic, not a weakness in some encoder, and no tool is going to beat it. What Base64 actually is has the bit-level version if you want it.

Compression over the wire gives some of it back. Gzip and Brotli find a little redundancy in a Base64 string, so the transferred size is not the full 133%. But it is never back to the original either, and for a PNG, JPEG or WebP the underlying bytes were already compressed, which means there was nothing much left to squeeze in the first place. Budget for the overhead rather than assuming the transfer encoding erases it.

What do you lose by inlining an image?

An image with its own URL is downloaded once and reused everywhere. Give it a hashed filename and a long cache header and a returning visitor never fetches it again, on any page.

The same image inlined into a stylesheet is now part of that stylesheet. Change an unrelated colour, ship a new hash, and every visitor re-downloads the image along with it. Inline it into the HTML instead and it comes down on every single page view, because HTML is normally not cached at all.

The rest goes with it:

Does inlining still save time on HTTP/2?

Much less than it used to. The classic argument was request count: under HTTP/1.1 a browser kept around six connections open per host and everything else waited in line, which is why sprite sheets and data URIs were standard advice. HTTP/2, standardised in 2015 and supported by every current browser, multiplexes many requests over one connection. An extra small file is not free — it still carries its own headers and work on the server — but it no longer blocks anything else.

What survives is latency on the very first load. A request still needs a round trip, and on a slow mobile connection that is measurable. This is why the remaining honest use of inlining is tiny assets needed in the first paint — not photographs, not hero images, not anything you would call content.

When is inlining still the right call?

Notice what is not on that list: photographs, logos above a couple of kilobytes, anything that appears on one page only, and anything a user uploads.

What size is too big to inline?

Encode the file and look at how long the string is. That is the entire decision. Dropping the image into the data URI converter here puts the original bytes, the encoded bytes and the overhead side by side — the encoded figure counts the whole string, prefix included, so it lands a little above 33% rather than exactly on it. It warns you outright once the string passes 100 KB, but treat that as the point where inlining is indefensible, not the point where it stops being sensible. The table is the judgement the tool does not make for you. Nothing is uploaded, which matters more than usual here: a data URI is a complete copy of the file in plain text.

Encoded lengthWhat to do
Under 1 KBInline it. The request costs more than the bytes.
1–4 KBInline it only if it is needed for the first paint and used on most pages.
4–10 KBUsually leave it as a file. Let a build threshold decide rather than you.
Over 10 KBLeave it as a file. You are trading caching for one round trip.

If the number surprises you, the image is the problem and not the encoding. A 90 KB icon is not an icon. Resizing and compressing it before you encode anything often answers the question by itself, and where image weight actually comes from explains why the dimensions matter more than the quality slider.

Should you Base64 encode an SVG?

No, and it is the one case where the answer has nothing to do with size thresholds.

An SVG is already text. Base64 encoding it adds a third to the size for no benefit and turns something readable into noise. Percent-encoding only the characters that would break a CSS url()#, <, >, quotes — keeps it shorter, keeps it legible in the stylesheet, and compresses far better, because gzip finds repetition in XML and finds almost none in Base64. The converter linked above switches to percent-encoding automatically when you give it an SVG, and tells you that is what it did.

For an icon inside HTML, better still: paste the <svg> element itself rather than any kind of URI. Then currentColor works, CSS can style the paths, and there is no encoding overhead at all.

What breaks when you use a data URI?

Should your bundler decide instead of you?

Pasting data URIs into source by hand is how a repository ends up with unreviewable files and images nobody can find to update. Keep the image as a normal file and let the bundler inline it below a size threshold: Vite inlines assets under 4,096 bytes by default, and webpack's asset modules work the same way with a similar few-kilobyte cutoff. Both let you change the number or force either behaviour per file.

You keep readable source, you still get the small-file optimisation, and there is one number to change when the icon turns into a photograph. A pasted string gives you none of that. It is also the version that stays in the repository for years, because nobody can tell what it is or where it came from.

If you are weighing one specific file rather than the general case, the image to Base64 converter gives you the number that settles it — original size, encoded size and the overhead, with the file never leaving your browser.

And when a data URI ends up inside a JSON config or an API response, it collapses the payload into a single line that nobody can read or review. Formatting minified JSON is how you get that back to something a person can check.

Frequently asked questions

Should I use Base64 images?

Only for images under roughly one or two kilobytes that appear on most pages, such as small icons and background patterns. Above that, inlining costs more than the request it saves, because the bytes can no longer be cached separately, lazy loaded or served in a modern format. Anything user-facing and photographic should stay a normal file.

Do Base64 images load faster?

They avoid one network request, which mattered under HTTP/1.1 and matters much less with HTTP/2 multiplexing. Against that, they add 33% to the size, block the first paint when they sit in CSS, and are re-downloaded every time the file containing them changes. For small assets it is a win; for large ones it is a clear loss.

How much bigger is a Base64 image than the original?

About 33% bigger, plus a short prefix and up to two padding characters. Base64 encodes every three bytes as four characters, so a 12 KB image becomes roughly 16 KB of text. Gzip or Brotli recovers part of the difference in transit but never all of it.

Can I use a Base64 image in an email?

Usually not. Gmail and several other mail clients block data URIs in image tags, so the recipient sees a broken image instead. Host the file and reference it with a normal URL, even though that means the image can be blocked until the reader loads remote content.

Is Base64 bad for SEO?

An inlined image has no URL, so a crawler cannot fetch or index it and it will not appear in image search. It also adds weight to the HTML or CSS that has to arrive before the page renders, which affects loading metrics. For a decorative 500-byte icon neither point matters; for a product photo both do.

Should I Base64 encode an SVG?

No. SVG is already text, so Base64 makes it a third larger, unreadable, and harder to compress. Percent-encode the few characters that break a CSS url() instead, or paste the SVG element directly into your HTML so CSS can still style it.

Last updated September 19, 2026