What a data URI actually is, and why a picture turns into a wall of text
A picture on the web is normally a file. The browser reads <img src="logo.png">, opens a second connection, asks the server for logo.png, and waits. A data URI removes that second step by carrying the picture inside the link itself. Instead of pointing at a file, the src contains the file — every byte of it, rewritten as plain text.
The rewriting is base64. Binary files contain all 256 possible byte values, and a great many of those bytes are meaningless or actively dangerous inside an HTML attribute or a CSS declaration — a stray quote mark ends the attribute early, a null byte ends the string. Base64 solves this by taking three bytes at a time, chopping the 24 bits into four groups of six, and writing each group as one of 64 harmless characters: A–Z, a–z, 0–9, plus + and /. The alphabet and the padding rules are set out in RFC 4648, section 4, and the data: URL scheme that wraps it around a media type dates back to RFC 2397, published in 1998.
Three bytes in, four characters out. That ratio is the whole story of base64, and it is where the famous overhead comes from: four divided by three is 1.333, so the encoded text is a third bigger than the file it describes, before you add the data:image/png;base64, prefix at the front. Nothing is compressed and nothing is lost. It is the same picture, spelled differently.
This page encodes your file — not a redrawn copy of it
That distinction sounds pedantic until you see what the alternative does. There are two ways a browser can produce base64 from a picture you have chosen. It can read the file off your disk and encode the bytes exactly as they are. Or it can draw the picture onto a canvas and ask the canvas to re-export it, which produces a brand-new file that merely looks the same.
The second route is easier to write and it is quietly destructive. A canvas has no memory of what it was given; it holds pixels. Ask it for a data URL and, unless you say otherwise, you get PNG — a lossless format that stores every pixel. Feed it a photograph that JPEG had compressed down to 12 KB and the PNG re-export comes back at a quarter of a megabyte, because JPEG’s compression has been undone and replaced with PNG’s, which is far worse at photographs. Feed it an SVG and you get a fixed-size raster: the vector maths, the crispness at any zoom, the ability to restyle it in CSS, all gone.
This tool takes the first route. Your file is read with the browser’s own FileReader.readAsDataURL, which hands back the bytes on disk and the type they already had. A JPEG comes out as data:image/jpeg. An SVG comes out as data:image/svg+xml and is still vector text you can read. Decode what this page gives you and you get back a file that is byte-for-byte identical to the one you dropped in — not a lookalike.
The practical consequence: the number of characters you see here is the honest cost of inlining your picture. It is roughly a third above the file size, never twenty times it.
The seven ways this page will write it out
A data URI is just a string, but the string almost never goes in on its own. It goes into a CSS rule, or an <img> tag, or a JSON field, and each of those has its own quoting. Choosing the shape here saves you assembling it by hand and getting the quotes wrong.
- A data URI — the bare string. Anywhere a URL is accepted, this can take its place.
- CSS background-image — wrapped in
url("…")and ready to paste into a rule. - A CSS custom property — declared once, usually on
:root, then used asbackground-image: var(--name). Worth it the moment the same graphic appears in more than one rule, because otherwise you are storing the whole picture twice in your stylesheet. - An HTML
<img>tag — complete, with the alt text pre-filled from the file name. Change it to something a screen reader can use; a file name is not a description. - Markdown — for a README. Renderers differ here, and several sanitise image sources and silently drop a data URI, so check that the picture actually appears where you publish it.
- A JSON string — escaped and quoted, ready for a request body or a config file.
- Raw base64, no prefix — for APIs that supply their own type and want only the payload. Many image-upload endpoints and several AI vision APIs want exactly this.
The character count updates with the format, because the wrapper is part of what you paste. Switch to raw base64 on any file and you will see the figure settle at about +33% — the encoding’s true cost, with the prefix taken away.
When inlining a picture helps, and when it quietly hurts
The case for a data URI is simple: one fewer request. The case against it is subtler and, for anything of size, stronger.
An inlined picture cannot be cached on its own. A normal image file is fetched once and reused across every page that references it; browsers keep it under the rules described in MDN’s HTTP caching guide. A picture inlined into a stylesheet is part of that stylesheet, so it is re-downloaded whenever the stylesheet changes — including when you changed a colour somewhere else entirely. A picture inlined into an HTML page is re-downloaded on every page view, because HTML is usually not cached at all.
It also delays the things around it. A stylesheet blocks rendering. Thirty kilobytes of base64 sitting in the middle of your CSS is thirty kilobytes the browser must receive before it can paint anything, where the same picture as a separate file would have loaded alongside the page rather than in front of it. This is a common way to make a page feel slower while believing you have made it faster, and it works directly against the largest-contentful-paint advice in Google’s LCP guidance.
And the request you saved is worth less than it used to be. The “inline everything small” habit dates from HTTP/1.1, when browsers held perhaps six connections per host and each extra file waited its turn. HTTP/2 multiplexes many requests over one connection, so a small extra file costs far less than it did. The advice survived the reason for it.
The jobs data URIs are genuinely good at
Set against all that, there are places where inlining is exactly right, and they share a shape: tiny, unchanging, and needed everywhere.
Interface graphics inside CSS. A custom checkbox tick, a select-box arrow, a chevron, a repeating texture. Each is a few hundred bytes as an optimised SVG, each would otherwise be its own request, and they are needed at the moment the stylesheet applies rather than a moment later. Inlining them removes a small flash of unstyled interface.
Email. HTML email clients block remote images by default until the reader clicks “show images”, which is why so many newsletters open looking broken. An inlined logo displays immediately. Support is imperfect — some desktop Outlook builds ignore data URIs entirely — so test rather than assume.
Anything that must survive being moved. A single-file HTML report, a self-contained SVG, a document a colleague will open from a memory stick. With the pictures inlined there are no broken links, because there are no links.
API payloads. A great many services accept an image as a base64 string in a JSON body rather than as a multipart upload, precisely because JSON cannot carry raw bytes. That is what the raw-base64 output is for.
Placeholders. A deliberately tiny, blurred version of a photograph — a couple of hundred bytes — inlined so it appears instantly, with the real file loading over it. The trick only works because the placeholder is small enough that inlining is free.
Turning base64 back into a picture
The second tab does the reverse, and it is the half most encoders leave out. Paste a whole data:image/…;base64,… URI, or just the base64 on its own, and you get the picture back with a download button.
Two details are worth knowing. If there is no data: prefix, the type is worked out from the first few bytes rather than guessed: PNG begins with a specific eight-byte signature, JPEG with FF D8 FF, GIF with GIF8, WebP with RIFF followed by WEBP four bytes later. Getting this wrong would hand you a file with the wrong extension that half your software refuses to open, so the signature is checked, not assumed.
And if the prefix disagrees with the bytes — a string labelled image/png whose content is plainly a JPEG, which happens constantly when someone hand-edits a URI — you are told, and the bytes win. Line breaks and stray whitespace in a pasted string are removed before decoding, because base64 copied out of a config file or an email is very often wrapped.
Nothing leaves your browser
Encoding and decoding both happen on your own machine. Your file is read from disk into this page and converted here; the base64 you paste is decoded here. Nothing is uploaded, nothing is stored, and there is no server involved at any point — which is the difference between a convenience and a disclosure when the thing you are encoding is a signature, an identity document, a medical scan or an unreleased logo.
It also means the work happens at the speed of your own computer and continues if your connection drops. Close the tab and everything goes with it.
Questions people ask about base64 images
Does base64 make my image smaller?
No — it makes it about a third larger, always. Base64 is a way of writing bytes as text, not a compression method. If you need the file smaller, compress it first with the Image Compressor or convert it with the Image to WebP Converter, then encode the smaller result.
Is base64 encoding the same as encryption?
Not remotely, and the confusion is worth killing. Base64 is reversible by anyone, needs no key, and is decoded by a single built-in browser function. It hides nothing. Treat a base64 string as being exactly as public as the file it came from.
Why is the string so much bigger than a third on my small icon?
Because the fixed prefix — data:image/svg+xml;base64, and its cousins — is a constant 22 to 30 characters, and on a 100-byte file that overhead is a quarter of the total on its own. The encoding still costs its usual third; the prefix is simply a large share of something small. Switch the output to raw base64 and the figure drops back to +33%.
Will my transparency survive?
Yes. Nothing is re-encoded, so a transparent PNG stays a transparent PNG and its alpha channel is untouched. Every preview on this page sits on a chequerboard so you can see the transparency rather than take it on faith.
Can I encode an animated GIF?
Yes, and the animation survives — again because the file is encoded rather than redrawn. A tool that routes pictures through a canvas would give you back a single still frame. Animated GIFs are large, though, so this is usually a poor candidate for inlining. Build one with the GIF Maker first if you need it.
Is there a size limit on data URIs?
There is no limit in the specification, but there are limits in practice. Browsers cap what they accept in the address bar at a couple of megabytes, and inside a page a very large data URI will work while making everything around it slower to parse. Support itself is universal in modern browsers, as caniuse records. The practical ceiling is your patience, not the standard.
Will a data URI work if the site has a Content-Security-Policy?
Only if the policy allows it. A strict img-src 'self' blocks data URIs along with everything else off-origin; you need data: listed explicitly, as the MDN img-src reference sets out. If an inlined image works locally and vanishes in production, this is very often why.
What about encoding something that is not an image?
This page is built for pictures — it previews them, measures them and decodes them back. For text, JSON, tokens or arbitrary strings, use the Base64 Encoder & Decoder, and for URL-safe percent encoding the URL Encoder & Decoder.
Does it work on a phone?
Yes. Choosing files opens the usual photo picker, and everything after that runs in the browser as it does on a desktop. Very large photographs from a modern phone camera are slower to read and produce a great deal of text, which is a reason to resize first with the Image Resizer rather than a reason not to.
Where the facts on this page come from
- RFC 4648 — The Base16, Base32, and Base64 Data Encodings, IETF, October 2006. The alphabet, the 3-to-4 ratio and the padding rules.
- RFC 2397 — The “data” URL scheme, IETF, August 1998. The
data:[mediatype][;base64],datashape itself. - MDN — Data URLs and MDN — FileReader.readAsDataURL(), Mozilla. The browser API this page uses to read files faithfully.
- MDN — HTTP caching and MDN — CSP: img-src, Mozilla.
- RFC 9113 — HTTP/2, IETF, June 2022, on multiplexing.
- Optimize Largest Contentful Paint, Google web.dev, on render-blocking resources.
- caniuse — data URIs, for browser support.
Related tools on this site: Base64 Encoder & Decoder, Image to WebP Converter, Favicon Generator, CSS Gradient Generator, QR Code Generator.