Data URI Generator
Turn a file or text into a data URI you can embed directly in HTML or CSS — and know when that is the wrong choice.
Preview
The crossover between the two encodings is exactly one sixth
Base64 costs a flat four characters for every three bytes, whatever the content. Percent-encoding costs one character for a byte it leaves alone and three for a byte it escapes, so if a fraction f of the bytes get escaped the cost is 1 + 2f. Setting the two equal needs no measurement at all:
1 + 2f = 4/3 → f = 1/6 = 16.667%
Escape fewer than a sixth of the bytes and percent-encoding wins; escape more and base64 does. Built to order and measured, the switch lands exactly where the algebra says:
| Bytes escaped | Base64 | Percent | Smaller |
|---|---|---|---|
| 0% | 1336 | 1000 | percent |
| 5% | 1336 | 1100 | percent |
| 10% | 1336 | 1200 | percent |
| 16% | 1336 | 1320 | percent |
| 17% | 1336 | 1340 | base64 |
| 20% | 1336 | 1400 | base64 |
| 30% | 1336 | 1600 | base64 |
| 50% | 1336 | 2000 | base64 |
At 16% percent-encoding is smaller; at 17% it is not. Which is why this page chooses by MIME type: images, fonts, audio and video are effectively random bytes, so nearly everything escapes and base64 is right. Text is mostly letters, so little escapes. SVG is explicitly carved out of the image branch and sent down the text path for exactly that reason.
| MIME type | Encoding chosen |
|---|---|
image/png | base64 |
image/jpeg | base64 |
image/svg+xml | percent |
text/plain | percent |
text/css | percent |
application/json | percent |
application/xml | percent |
application/pdf | base64 |
font/woff2 | base64 |
audio/mpeg | base64 |
Except that for SVG it does not actually win
Measured rather than assumed, and the result was not what the reasoning above predicts:
| Content | Raw | Base64 | As encoded here | Minimal escaping |
|---|---|---|---|---|
| a small SVG | 95 | 128 | 167 | 95 |
| CSS | 46 | 64 | 60 | 46 |
| JSON | 40 | 56 | 84 | 40 |
| plain prose | 43 | 60 | 59 | 43 |
For the one format the rule names, the percent-encoded version is
167 characters against base64's 128. The
reason is that JavaScript's encodeURIComponent is built for query strings rather
than data URIs, and it is far more cautious than a data URI needs.
| Count | Characters | |
|---|---|---|
| escaped by encodeURIComponent | 24 | " # $ % & + , / : ; < = > ? @ [ \ ] ^ ` { | } |
| strictly required by a data URI | 2 | % # |
| escaped as insurance | 21 | $ & + , / : ; < = > ? @ [ \ ] ^ ` { | } |
A data URI genuinely requires two: %, which starts an escape, and #,
which would otherwise start a fragment. A double quote matters too, but only because the URI
usually ends up inside a double-quoted attribute. The other 21 are legal
unescaped, and each one costs two extra characters — and an SVG is made almost entirely
of them.
So is the conservative version wrong?
Not exactly, and it is worth being precise about the trade. Escaping conservatively produces a
URI that is safe everywhere — in a quoted attribute, an unquoted one, a CSS
url(), a bare link, pasted into a shell. Escaping minimally produces a smaller
URI that is safe in most of those and not all. That is a defensible choice, not a bug, and the
output decodes back to exactly what went in either way.
What is fair to say is that the size win goes the other way for the one format most people reach for. On all 4 samples above, minimal escaping is smallest — and for the SVG it is 95 characters, the same as the raw bytes, because a well-formed SVG contains nothing a data URI has to escape at all.
The same holds for ordinary text: 43 bytes of prose stay 43 characters, against 60 as base64. That is the practical rule for
hand-writing an SVG data URI into a stylesheet — escape only %,
#, and the quote character you are not using, and the URI stays readable
and stays small. A base64 one does neither.
How to use
- Choose a file, or enter text directly.
- Copy the generated data URI or the ready-made tag.
- Use it only for genuinely small assets.
- Check the resulting size before committing to it.
- Prefer an ordinary file reference for anything substantial.
Frequently asked questions
When is embedding actually worthwhile?
For very small assets — an icon, a tiny repeating pattern, a custom cursor — where saving one network request outweighs the size penalty. It is also genuinely useful for self-contained documents and for email that must carry its own images with it.
What does it cost?
About 33 per cent in size from the Base64 encoding, plus the complete loss of caching. An embedded asset cannot be cached independently, so an image embedded across five pages is downloaded five separate times rather than once — which outweighs the saved request very quickly.
Why does it slow a page down?
Because the data becomes part of the HTML or CSS itself, which must be downloaded and parsed before rendering can proceed. A large data URI inside a stylesheet delays the entire stylesheet, which delays the page — precisely the opposite of the intended effect.
What size is too large?
Above a few kilobytes the trade-off has usually reversed. Very large data URIs bloat the source file, slow parsing noticeably, and make the code unreadable to anyone maintaining it. Some older tooling also has length limits that produce silent truncation rather than an error.
What about SVG?
For SVG there are better options available. Inlining the markup directly keeps it styleable with CSS and often occupies less space than the Base64 version. If you do need a data URI, URL-encoding an SVG is generally smaller than Base64 because the content is already text.
Does my file get uploaded?
No. The file is read and encoded entirely in your browser, so nothing is transmitted at any point — which matters if the file is not something you would hand to an unfamiliar website.
Can I use a data URI for a downloadable file?
Yes, paired with a download attribute on a link, and it works well for small generated files such as a CSV or a configuration snippet. For anything large, generating a blob URL is considerably more efficient than embedding the whole file in the page.
🔒 This tool runs entirely in your browser. Nothing you enter is uploaded, logged, or stored.