What Is Base64 Image Encoding?
Base64 is an encoding scheme that converts binary data, such as the bytes of an image file, into a string of printable ASCII characters. For images the result is called a data URI (or data URL): a self-contained string that represents the entire image as text.
A Base64 image URI looks like this:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
The format is always data:[MIME type];base64,[encoded data]. The browser can use this string directly in an <img> src attribute or a CSS background-image value, with no separate image file and no HTTP request.
The encoding itself is mechanical. Base64 takes your data three bytes at a time, which is 24 bits, and re-expresses those 24 bits as four characters drawn from a 64-character alphabet of A to Z, a to z, 0 to 9, plus and slash. Each of those characters therefore carries only 6 bits of information instead of the 8 bits a byte holds. That ratio, four characters for every three bytes, is the whole story of Base64 and the source of everything else in this guide.
How to Convert an Image to Base64
The fastest way is our free Image to Base64 Converter. Drop your image in and get the complete data URI in one click. The conversion happens entirely in your browser, so the file is never uploaded to a server.
If you prefer JavaScript, the browser FileReader API handles it natively:
const reader = new FileReader();
reader.onload = (e) => console.log(e.target.result); // data URI
reader.readAsDataURL(file);
Both routes produce an identical payload. There is no such thing as a better or worse Base64 encoder, because the transformation has exactly one correct answer.
Using Base64 Images in HTML
Use the data URI as the src attribute of an img element. A real, working example, truncated in the middle for readability:
<img
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAIAAADA
AbR1AAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTw
AAAAGYktHRP///////wlY99wAAAAHdElNRQfqCAITAido..."
alt="Embedded icon"
width="16" height="16">
That is a real 16 by 16 PNG: 678 bytes as a file, 904 characters once encoded. The image renders with the HTML, so there is no second request, no flash of missing content, and no broken icon if a CDN is slow. Keep the width and height attributes on it. An inline image can still cause layout shift while the surrounding page settles, and those attributes are what let the browser reserve the space in advance.
Using Base64 Images in CSS
Use it as a background-image value:
.icon {
background-image: url("data:image/svg+xml;base64,PHN2Zy...");
background-size: contain;
width: 24px; height: 24px;
}
SVG is the common case here, because an icon that is a few hundred bytes of markup survives the encoding penalty comfortably. Quoting the URL is worth doing: an unquoted data URI containing a comma or a parenthesis will break the CSS parser, and Base64 payloads routinely contain both.
The 33 Percent Size Penalty, and Where It Comes From
Four characters for every three bytes means the encoded string is 4/3 the size of the file, which is an increase of one third. The overhead is not an implementation detail or something a better tool avoids. It is arithmetic, and it applies to every Base64 encoder that has ever existed.
We encoded two real files to confirm the theory matches practice:
| File | Binary size | Base64 length | Overhead |
|---|---|---|---|
| Small JPEG, 120 × 80 | 859 bytes | 1,148 characters | 33.6% |
| Small PNG, 120 × 80 | 627 bytes | 836 characters | 33.3% |
The extra fraction above a clean 33.3% is padding. Base64 output is always a multiple of four characters, so files whose length is not divisible by three get one or two = characters at the end to fill the gap. Add the data:image/png;base64, prefix on top and the practical figure is a little over a third.
Scale that up and the consequence is obvious. A 500 KB photograph becomes roughly 667 KB of text. A 2 MB hero image becomes about 2.7 MB. And unlike a real image file, that weight lands inside your HTML or CSS document.
Inline Base64 vs an External File
The trade is always the same: you are spending bytes and cacheability to buy one fewer request. Whether that is a good trade depends almost entirely on the size of the image.
| Factor | Inline Base64 | External file | Winner |
|---|---|---|---|
| HTTP requests | None, it arrives with the document | One per image, though HTTP/2 makes them cheap | Inline |
| Transferred size | About 33% larger than the file | The file, exactly | External |
| Browser caching | Cannot be cached separately; re-downloads with every page that embeds it | Cached once, reused across the whole site | External |
| Page weight | Counts against your HTML or CSS document | Separate, and can be lazy-loaded | External |
| Blocking behaviour | Delays the document it sits in | Loads in parallel, can be deferred | External |
| Maintainability | Replacing the image means editing code and redeploying | Overwrite the file, nothing else changes | External |
| Self-containment | One file with no dependencies | Breaks if the path or host moves | Inline |
Inline wins on exactly two rows, and both matter most when the image is tiny or the document has to stand alone. Everything else favours a real file.
What Base64 Does to Page Performance
The size penalty is the part people know about. The blocking behaviour is the part that actually hurts, and it comes from where the string lives rather than how big it is.
A data URI in your stylesheet is inside a render-blocking resource. The browser will not paint the page until that CSS has downloaded and parsed, so 200 KB of encoded icons in a stylesheet delays the first paint of the entire page, not just the icons. An external icon file, by contrast, loads alongside everything else and its absence delays nothing.
A data URI in your HTML has a related problem: it inflates the document itself, the first thing the browser fetches and the one resource that can never be deferred. On top of that sits a caching failure. An external image is downloaded once and reused everywhere, while the same image inlined into five pages is downloaded five times, because a cached HTML page is much rarer than a cached image. Inlining a site-wide logo is one of the few genuinely bad ideas in this area.
The practical threshold most teams settle on is a few kilobytes. Under that, one fewer request is worth a third more bytes. Above it the maths turns against you quickly.
When to Use Base64 Encoding
Use it when at least one of these is true:
- Small images under about 5 KB. Icons, bullets, small decorative elements, where a third of very little is still very little.
- HTML emails. Mail clients frequently block external images by default, and an inline image displays regardless. This is the strongest case for Base64 that exists.
- Single-file documents. Reports, invoices, prototypes and anything that has to survive being emailed around as one file with no broken links.
- API responses. Returning a thumbnail inside a JSON payload avoids a second round trip for something the client needs immediately.
When NOT to Use Base64
- Large photos. A 500 KB photo becomes about 667 KB of text sitting in your markup. Compress it and serve it as a file instead. Our image compressor will usually take more off the file than Base64 adds back.
- Repeated images. Anything that appears on more than one page loses the caching benefit that makes external files fast.
- Anything in critical CSS. Inlining images into a render-blocking stylesheet trades a fast first paint for a slow one.
- Images you expect to change. Swapping a file is a deploy-free operation. Swapping an inlined string is a code change.
Decoding Base64 Back to an Image
If you have a string and need the file, our free Base64 to Image Decoder takes it with or without the data:image/ prefix and gives you the image back. Decoding is exact: Base64 is an encoding rather than a compression method, so the bytes you get out are the bytes that went in.
This is the everyday half of the workflow. Strings turn up in page source, stylesheets, API responses and bug reports, and none of them can be read until something turns them back into pixels.