File to Base64
Encode a file for a JSON body, a data: URI or a Secret
File
Base64 Output
Getting bytes through a channel that only carries text
JSON has strings, numbers, booleans, arrays and objects. It has no type for a sequence of bytes. Neither does a YAML value, an environment variable, a CSS declaration or an HTTP header. So when a file has to travel through one of those — an avatar in a request body, a certificate in a Secret, an icon inlined into a stylesheet — it gets rewritten in an alphabet those channels can carry, and that alphabet is Base64.
Drop a file in and you get that rewriting, done correctly for binary. Correctness is not automatic here: the browser's own btoa() works on one character per byte, so it mangles anything above code point 255 without raising an error. btoa('café') returns Y2Fm6Q== when the right answer is Y2Fmw6k=, and the damage only surfaces at the far end. MDN sets out the whole problem. Reading the file as bytes sidesteps it entirely, which is what happens here.
The one number worth knowing before you start: Base64 turns every three bytes into four characters, so the result is a third larger than what went in — and the MIME variant adds a line break every 76 characters on top of that. A 4 MB PDF becomes about 5.5 MB of text. That is how a request that worked in testing meets a 5 MB body limit in production, and the figures are shown live beside the output so the surprise happens here instead.
The file is read in this tab. Nothing is uploaded, which is the point when the thing you are encoding is a private key, a keystore or a document belonging to a customer.
Encoding a file
- Drop the file in, or pick one – Any type — the encoding treats every file as bytes, so an image, a PDF, a font, a
.p12keystore and a plain text file all work the same way. The panel shows the size, the type the browser reported, and the type the leading bytes actually say. - Choose the alphabet – Standard is what an API means when it asks for Base64. URL-safe swaps
+and/for-and_and drops the padding, for anything going into a query string or a path. MIME wraps at 76 characters, which is whatopenssl base64and mail attachments produce. - Turn on the data: URI if that is where it is going – The output then carries the
data:<type>;base64,prefix a stylesheet, an<img>tag or an email template expects, using the media type detected from the file itself rather than from its extension. - Copy it, or save it as a file – Copy takes the whole string even when the editor is only showing the start of it. Download writes it as a
.b64.txtnext to whatever you were going to paste it into.
Pick the alphabet for the destination, not by preference. MIME wrapping inside a JSON string is invalid — a raw newline is not allowed there — and inside a Kubernetes Secret it produces a value the API server rejects. Standard Base64 in a URL is just as broken the other way: + means a space in a query string and / ends a path segment, so the value silently arrives as something else. The wrong choice usually fails somewhere far from where it was made.
A 180-byte icon, inlined
The Sample button loads a small PNG so you can watch every part of this happen. Here is what goes in and what comes out with the data: URI switched on — which is exactly what a stylesheet or an <img> tag wants.
# what the panel reports subscriber-avatar.png 180 bytes Browser says: image/png Bytes say: PNG image # 89 50 4E 47 - the signature, # not the file name
.avatar { background-image: url( data:image/png;base64, iVBORw0KGgoAAAANSUhEUg… ); } # 240 characters for 180 bytes
What people use it for
Putting a file in a JSON request body
Plenty of APIs take file contents inline, because there is nowhere else in a JSON body to put them — committing a file through the GitHub contents endpoint means sending a content field that is Base64 and nothing else. Encode here, paste into the body, done. Standard alphabet, no wrapping.
Inlining a small asset as a data: URI
A sprite, an icon, a font subset — inlining removes a request, and for something under a couple of kilobytes that is usually the right trade. Past that it stops being one: the asset can no longer be cached on its own, it is a third larger than the file it replaced, and every deploy re-downloads it because one character of the stylesheet changed.
Getting a binary into a Kubernetes Secret
Every value under data: in a Secret is Base64, and the Kubernetes documentation is explicit that this is encoding rather than protection — anyone who can read the Secret can read the contents. Encode a keystore or a certificate here, paste it in as a single unwrapped line, and read it back later with Base64 to File.
Attaching a file to an email or a signed message
MIME has wrapped Base64 at 76 characters since RFC 2045, because the mail systems it was designed around could not be relied on to carry longer lines. If you are hand-building a message body, or comparing your output against what openssl base64 printed, that is the variant to pick.
What it does
- Any file, any size up to 9 MB. Read as bytes, so binary formats encode correctly rather than being quietly mangled the way
btoa()mangles them. - Three alphabets. Standard, URL-safe without padding, and MIME wrapped at 76 characters.
- A data: URI on demand. Built with the media type detected from the file's own leading bytes, not from its extension.
- Honest size figures. Bytes in, characters out, and the percentage the encoding added — before it meets a body limit rather than after.
- Drag and drop. Drop anywhere on the file panel, or pick one the usual way.
- Nothing is uploaded. The file is read in this tab and stays there.
Questions that come up
Why is the output bigger than my file?
Base64 spends four characters on every three bytes, because it only uses 64 of the available symbols and each one therefore carries six bits rather than eight. Four sixes for three eights is a fixed 33% increase, plus up to two padding characters, plus one byte per line if you choose MIME wrapping. There is no setting that avoids it — it is what the encoding costs.
Which variant do I need?
Standard unless something told you otherwise. URL-safe when the value goes into a URL, a path segment or a filename, since + and / both mean something else there. MIME when you are building a mail body by hand or matching output from openssl base64. If the destination is a JSON string or a Kubernetes Secret, it must be one of the unwrapped forms — a literal newline inside a JSON string is a parse error.
Should I inline images as data: URIs?
For small ones, often yes; for large ones, almost never. An inlined asset costs a third more bytes, cannot be cached separately from the file it lives in, and is re-sent in full whenever that file changes. RFC 2397 introduced the scheme for short inline content and it is still the right way to read it — a few hundred bytes is comfortable, a few hundred kilobytes is a mistake you feel on every page load.
Is Base64 a way of protecting a file?
It is not. There is no key and nothing secret — the transformation is public, and reversing it takes one click on the sister page. It exists so bytes survive a text-only channel. A credential that is "only Base64" in a config file is a credential in a config file.
My encoded value is rejected but it looks right.
Three causes, in the order they turn up. Line breaks that the destination will not accept — switch away from MIME. Padding that a strict URL-safe consumer refuses — switch to URL-safe, which drops it. Or the value was copied from an editor that had already wrapped it visually, in which case the breaks are in your clipboard rather than in the output. Copy from the button rather than by selecting the text, and that one goes away.
Can I encode something larger than 9 MB?
Not comfortably in a browser tab — the file, the encoded string and the clipboard copy are all resident at once, so the real cost is several times the file size. At a terminal, base64 -w0 file.bin > file.b64 streams it and produces a single unwrapped line; drop -w0 and you get the MIME-wrapped form instead.
Related tools
Worth reading
- RFC 4648 — Base16, Base32 and Base64 – Both alphabets, and exactly when padding is required
- MDN: data URLs – The syntax, the browser limits, and what inlining costs you
- MDN: FileReader – How a browser reads a local file without it going anywhere