Encoding a File to Base64: Data URIs, Inline Assets, and the 33% Tax
How to encode any file to Base64 or a data URI, embed small assets inline, ship binary through JSON and email, and why the output grows about a third.
Encoding a File to Base64: Data URIs, Inline Assets, and the 33% Tax
Most of the formats we move data through every day are text-only. A JSON request body is text. An email is text. A YAML config file is text. But the things we actually want to ship around are often binary: a 48×48 PNG icon, a one-page PDF, a tiny WAV beep. Base64 is the bridge between those two worlds. It takes raw bytes and rewrites them as a string of plain, printable characters that any text channel will carry without complaint.
This post walks through what that conversion actually does, when a data URI earns its keep, why the output is bigger than the file you started with, and how to encode a file in your browser without sending it anywhere.
What Base64 actually does to your bytes
Base64 is a mapping, not a cipher. It reads your file three bytes at a time. Three bytes is 24 bits, and 24 bits split evenly into four 6-bit groups. Each 6-bit group indexes a 64-character alphabet (A–Z, a–z, 0–9, plus + and /), so every three bytes of input become four printable characters of output. That is the whole trick: binary that might contain null bytes, control characters, or anything else a text parser would choke on gets re-expressed using only characters that survive copy-paste, JSON strings, and email headers.
Because four output characters now represent what used to be three input bytes, the encoded string is roughly 4/3 the size of the original. That is the famous ~33% overhead, and it is structural, not a flaw you can tune away. A 9 KB icon becomes about 12 KB of text. A 1 MB PDF becomes about 1.33 MB. For small assets this is a fine trade; for large files it is the reason you should think twice.
One thing worth being blunt about: Base64 is encoding, not encryption. Anyone with the string can decode it back to the exact original file. Treat the output with the same care you would the source.
Data URIs: a file that lives inside a string
A data URI is Base64 with a label glued to the front. The shape is:
data:<mime-type>;base64,<the-base64-payload>
So a PNG looks like data:image/png;base64,iVBORw0KGgo... and a PDF looks like data:application/pdf;base64,JVBERi0xLjQ.... The data: scheme tells the browser "what follows is not a URL to fetch, it is the resource itself." That MIME prefix matters: it is how the browser knows whether to paint the bytes as an image, render them as a PDF, or hand them to a download. If you are ever unsure what type a file will report, the File MIME Type Inspector will tell you before you build the URI.
Because a data URI is just a string, you can drop it anywhere a URL is allowed:
<img src="data:image/svg+xml;base64,...">in HTMLbackground-image: url("data:image/png;base64,...")in CSS- an
hrefon a download link - a field in a JSON payload
The asset travels with the document. No second HTTP request, no separate file to deploy, no broken-image box if a path is wrong.
Sending binary through text-only channels
The real reason this conversion exists is transport. Picture a few common situations:
- You are filing a bug report and want the failing 4 KB sample file to live inside the JSON request, so whoever reproduces it does not have to chase an attachment.
- You are writing a test fixture and want a tiny image baked directly into the test file, so the test has no external dependencies.
- You are templating an email and want a small logo to render even when the recipient's client blocks remote images.
In all three, the constraint is the same: the channel only carries text. Base64 lets the binary ride along as text, and the receiver decodes it back to the original bytes on the other end. The same logic powers MIME email attachments and many API upload formats under the hood — they are Base64 internally, you just rarely see the string.
A worked example
Say I have a 9 KB PNG sprite called pin.png and I want it inline in a stylesheet. Here is the flow:
- Open the File to Base64 Converter and select
pin.png. - Switch the output to data URL mode. The tool reads the file in the browser, keeps the MIME type the browser reports (
image/png), and produces a string that beginsdata:image/png;base64,iVBORw0KGgoAAAANSUhEUg.... - Copy that string and paste it straight into the CSS:
.map-pin {
width: 24px;
height: 24px;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...");
}
That is it. The 9 KB file is now ~12 KB of text living inside the stylesheet, and the browser renders it with no network round trip. The same steps work for a small PDF: pick data URL mode, copy the data:application/pdf;base64,... output, and use it as the href of a download link or the src of an embed.
To go the other direction — turning a pasted Base64 string or data URI back into a real file — the converter has a decode counterpart, so the round trip is symmetric.
When I reach for this, and when I don't
I keep this in my toolbelt for anything small and self-contained. The last time I used it, I was assembling an API example for our docs and wanted the request body to be copy-pasteable into a terminal and just work, with no "now download this fixture from somewhere" footnote. Encoding the 3 KB sample file into the JSON body turned a two-step setup into a one-paste setup, and the example stopped rotting every time we moved the asset.
What I do not do is encode large media. A 5 MB hero image as a data URI bloats your HTML to ~6.7 MB, can't be cached separately from the page, and blocks the parser while it loads. The 33% tax is cheap on a 4 KB icon and brutal on a multi-megabyte file. The rule of thumb I use: if the asset is small enough that you would not bother giving it its own request, inline it; otherwise, link to it normally.
Privacy: the encoding happens on your machine
Worth saying plainly, because it is the whole point of doing this in the browser: the conversion is local. The tool reads the file you pick with the browser's FileReader and produces the Base64 string entirely client-side. Nothing is uploaded, and there is no server that ever sees your bytes. That said, remember that the encoded output contains the full file, perfectly reversible — so a data URI for a sensitive document is exactly as sensitive as the document. Encode freely, but share the result with the same caution you would the original.
Base64 is one of those quiet primitives that runs under more of the web than people realize. Once you can picture the three-bytes-to-four-characters mapping and the data: prefix, you stop seeing it as magic and start seeing it as a plain, predictable tool for one job: getting binary safely through a text-shaped pipe.
Made by Toolora · Updated 2026-06-13