A 3 KB icon becomes a 4 KB string the moment you base64-encode it. That is not a rounding error or a bad encoder, it is what the format does by definition, and it is the number every guide about inlining images skips past on the way to the part where it looks convenient.
Why It Is Always 33%, Not Roughly 33%
Base64 exists to move binary data through channels that only trust text: 1970s mail transports, JSON, CSS, HTML attributes. None of those can carry an arbitrary byte, so base64 re-spells the data using only 64 printable characters, defined in RFC 4648.
The mechanism is fixed, not tunable: three input bytes are read as 24 bits, and those 24 bits are cut into four 6-bit groups, each one mapped to one of the 64 printable characters (A-Z, a-z, 0-9, + and /). Three bytes in, four characters out, every time. That ratio, 4 divided by 3, is exactly 1.333, which is where the 33% comes from. Encoding a length that is not a multiple of three pads the last group with one or two = characters, which only ever adds a byte or two, not a meaningful amount.
There is no better base64 encoder that avoids this. The overhead is the cost of using 6 bits of every 8-bit character to carry information, and the other 2 bits to stay inside the printable-ASCII range every one of those old text channels could survive.
What a Few Common Sizes Actually Become
Exact 4/3 growth before padding; real files round to the nearest multiple of 4 characters.
| Original file | Base64 output | Growth |
|---|---|---|
| 1 KB | 1.33 KB | +33% |
| 4 KB | 5.33 KB | +33% |
| 50 KB | 66.7 KB | +33% |
| 500 KB | 667 KB | +33% |
Where the Trade Actually Pays Off
The 33% is not the only cost, and it is not always the deciding one. What a data URI buys back is one fewer HTTP request, and for a genuinely tiny image, that request was the expensive part: even over HTTP/2, a request still costs a round trip's worth of latency and a slice of the browser's connection budget.
Most build tooling has already settled on where that trade stops paying off. Vite's `assetsInlineLimit` defaults to 4096 bytes, and webpack's `url-loader`, which originated the pattern, shipped with the same 4 KB default. Below that line, an asset is inlined as a data URI automatically; above it, it stays a separate file. That number was not picked at random, it is the point where the community consensus lands, and it is the threshold this site's own Image to Base64 tool warns past.
For an icon, a 1x1 tracking pixel, or a tiny placeholder blurred into an image's own CSS, inlining is close to free and saves a request outright. For anything a normal camera or a stock photo site would produce, the 33% and the caching cost below outweigh the one request saved.
The email client that ignores it entirely
Base64 images are commonly recommended for HTML email, since inline images survive being forwarded and don't break when hosted images get blocked by a mail client. The catch: classic Outlook for Windows (2007 and every version since) renders HTML mail with Microsoft Word's layout engine rather than a browser engine, and Word has never supported the data: URI scheme. The image simply does not appear, with no error and no fallback, in one of the most widely deployed corporate mail clients. The reliable option for email is a real attachment referenced by a cid: URI, not base64.
The Cost That Does Not Show Up in File Size
A separate image file has a URL, and a URL is the unit browser caching works on. Request logo.png once and, with reasonable cache headers, every later page load reuses the copy already on disk, even after the user closes the tab and comes back tomorrow.
A data URI has no URL. It is a string embedded inside whatever CSS or HTML file contains it, so it is only ever as cacheable as that surrounding file. If the CSS changes for any reason, unrelated to the image, the browser re-downloads and re-decodes the image too, because from the cache's point of view it never existed as its own resource. Inline ten images this way into one stylesheet and the whole stylesheet is invalidated whenever any one of them, or anything else in the file, changes.
This is the cost the file-size number never shows, and it is usually the bigger one on a page that gets more than one visit.
See the exact overhead on your own image
Base64, a data URI, and ready CSS and HTML snippets, with the real byte count before you commit to any of them.
A Short List of When to Reach for Each Option
The 4 KB line is a default, not a law. These are the situations that actually move it.
Inline it: a tiny, one-off, rarely-changing icon
Under a few KB, used in one place, not swapped often. The saved request is worth more than the 33% and the lost cache entry.
Keep it a file: anything a camera or designer produced
Photographs and full illustrations are already well past the point where 33% is a meaningful number of bytes, and they benefit the most from independent caching across repeat visits.
Inline it: a placeholder meant to be replaced by JavaScript
A 1x1 transparent pixel or a blurred low-resolution stand-in that swaps out on load has no long-term caching value anyway, so the request saved is pure upside.
Keep it a file: anything going into an email
Given how unevenly mail clients support data URIs, a real attachment with a cid: reference is the only version that is guaranteed to render everywhere.
Keep it a file: an image reused across many pages
Every page that inlines the same icon pays the 33% overhead again and gets none of the benefit a shared, cached file would give the second and third visit.
Frequently Asked Questions
Related Tools
Keep Reading
Base64 Is Not Encryption: What It Does and Why It Exists
Three bytes become four characters, which is where the 33 percent size increase and the trailing equals signs come from. And why it hides nothing.
Minifying CSS Saves Almost Nothing, Until You Delete the Comments
Three stylesheets measured as they would be served: stripping whitespace bought 3 to 5 percent, stripping comments bought up to 58. Why the gap is that wide.
Rounded Image Corners: When to Use CSS and When to Bake Them In
border-radius is ignored by Outlook and dropped by most PDF exporters. Where a permanent round is the only option, and why the file must be PNG.
Why Resized Images Come Out Noisy, and the Fix Nobody Applies
Bilinear sampling reads four pixels no matter how far you shrink, so a 20:1 reduction ignores 396 of every 400. Halving in steps reads all of them.