Base64 Encoder / Decoder
Convert text or a whole file to and from Base64 — handling UTF-8 and emoji correctly, with a URL-safe option, byte-size readouts, a data-URL preview and copy or download buttons.
Choose any file — an image, a PDF, a small archive. It is read in your browser and never leaves the page.
Image preview
How Base64 encoding works
Base64 exists to move binary data through channels that only tolerate text: JSON fields, XML
documents, email bodies, HTTP headers and data URLs. The algorithm takes the raw bytes, groups
them into sets of three, and rewrites each 24-bit group as four 6-bit numbers. A 6-bit number has
64 possible values, so each one maps to a single printable character — the 62 letters and digits
A–Z, a–z and 0–9, plus + and /.
That three-bytes-to-four-characters ratio is the whole trick, and it is also the whole cost: the
encoded text is roughly 33% larger than the source. If the input length is not a multiple of three,
the final group is short and is padded with = characters so the length always lands on
a multiple of four. Those = signs carry no data — they are a checksum-free way of
telling a decoder how many bytes the last group really contains.
The subtle part in a browser is text. JavaScript strings are sequences of UTF-16 code units, and the
legacy btoa() function rejects anything above U+00FF with an
InvalidCharacterError. So btoa("café") and any string containing an emoji both
throw. The correct route, and the one this tool takes, is to turn the text into UTF-8 bytes first
with new TextEncoder().encode(text), Base64-encode those bytes, and on the way back
decode to bytes and run them through new TextDecoder().decode(bytes). That round-trip
is lossless for every character the Unicode standard defines, accents and emoji included.
| Input | UTF-8 bytes | Standard Base64 | URL-safe Base64 |
|---|---|---|---|
Man | 3 | TWFu | TWFu |
Ma | 2 | TWE= | TWE |
café | 5 | Y2Fmw6k= | Y2Fmw6k |
~? | 2 | fj8= | fj8 |
Accuracy, limits and honest caveats
Base64 is a bijection over byte strings, so for well-formed input the round-trip here is exact. The honest limitations are about ill-formed input, and about what Base64 is not for.
- Invalid input is reported, never guessed. If the string contains characters outside the Base64 alphabet, or its length is impossible once padding is considered, the tool says so instead of returning empty output. It deliberately does not invent characters to force a decode.
- Padding and whitespace are tolerated. Missing
=at the end is fine — it is re-added automatically, because the length already tells the decoder what is missing. Line breaks from MIME-encoded data are stripped too, which matters for Base64 copied out of email. - Bytes are not always text. Decoding a Base64 string that really contains an image or a compressed archive produces replacement characters, because those bytes were never valid UTF-8. Nothing is lost — the file input pane is the right way to look at binary data — but the text pane will look like noise.
- Base64 is not compression and not security. It adds about a third to the size, and it protects nothing: it is a public, keyless transform. Treating Base64 as obfuscation is a common and costly mistake.
- Large files stay in memory. Everything happens on the main thread, so a multi-megabyte file will pause the page briefly while the string is built. For very large payloads a chunked streaming encoder is a better fit than a single-page tool.
A Data URL is Base64 plus a media type, for example
data:image/png;base64,iVBORw0…. It is perfect for small inline icons, but the browser
cannot cache it separately and it inflates the HTML, so keep it for payloads of a few kilobytes.
How to use this tool
- Encode text. Type or paste into the left pane — the output updates as you type, so there is no need to press anything. Accents and emoji are handled through UTF-8 and never throw.
- Decode a string. Paste the Base64 into the same left pane and press
Decode. Both alphabets are accepted: a value containing
-or_is read as URL-safe automatically, and missing padding is repaired. - Switch to the URL-safe alphabet. Tick the box before encoding when the result
will travel inside a URL, a filename or a JWT-style token. The encoded string updates immediately,
with
+and/replaced and the padding removed. - Encode a file. Drop a file onto the dashed area, or press Enter there to pick one. It is read as an ArrayBuffer and converted to Base64, and the readouts show the original byte size next to the encoded character count.
- Preview images. When the file is an image, a data-URL preview appears so you can confirm you encoded the file you meant. The browser renders the preview itself; nothing is uploaded.
- Take the result away. Copy result puts the string on the clipboard and
Download result as .txt saves it to a file, ready to paste into a config value, an API
payload or an
imgtag.
Because the page is a single static document with no network calls, it keeps working on a plane, on a locked-down machine, or anywhere an online encoder would be a bad idea for the data you are handling.
Frequently asked questions
Is Base64 encryption?
No. Base64 is a reversible transport encoding, not encryption. Anyone who has the string can decode it with the same public algorithm, so it hides nothing. If you need confidentiality, encrypt the data first with a real cipher and keep the key secret — Base64 only makes binary bytes safe to paste into text-only channels.
Why does btoa() fail on accented or emoji text?
btoa() was defined for binary strings and throws an InvalidCharacterError on any code unit above U+00FF, so "café" or a single emoji breaks the naive call. The fix, used here, is to convert the text to UTF-8 bytes with new TextEncoder().encode(text) first and then Base64-encode those bytes; decoding reverses the process with new TextDecoder().decode(bytes).
What is the URL-safe alphabet and why drop the padding?
Standard Base64 uses "+" and "/", which have reserved meanings inside a URL path or query string, so the URL-safe variant defined in RFC 4648 section 5 substitutes "-" and "_" and commonly strips the trailing "=" characters. This tool accepts either alphabet on input and re-adds padding automatically when you decode, so mismatched padding is never a hard failure.
How much larger is Base64 than the original data?
Base64 packs three bytes into four characters, so the encoded text is about 33% larger than the source, plus a little more for line breaks or a Data URL header. A 300 KB image becomes roughly 400 KB of text. That overhead is why Base64 is for embedding and transport, not for storing large files.
Sources & further reading
- RFC 4648 — The Base16, Base32 and Base64 Data Encodings — The normative definition of the standard alphabet, the padding rules, and the URL- and filename-safe variant using "-" and "_".
- MDN Web Docs — Base64 encoding and decoding — Explains why btoa() throws on non-Latin-1 text and documents the TextEncoder/TextDecoder workaround this tool relies on.
- WHATWG Encoding Standard — TextEncoder and TextDecoder — Defines the UTF-8 encode and decode steps, including that invalid byte sequences are replaced rather than thrown, which is why corrupt input can decode to placeholder characters.