Repacking 8-bit bytes into a 64-symbol alphabet
Base64 takes binary data, three bytes (24 bits) at a time, and re-groups those bits into four 6-bit chunks, each mapped to one of 64 printable characters: A–Z, a–z, 0–9, plus + and /. When the input length is not a multiple of three bytes, the output is padded with one or two = characters so its length is always a multiple of four. That 6-bit-per-character packing is also why Base64 output is reliably about a third larger than its input — four output characters for every three input bytes.
Unicode-safe by construction, not by accident
The browser's native btoa function only accepts single-byte (Latin-1) character codes, so encoding text containing accents, CJK characters, or emoji directly through it throws or corrupts the input. This tool avoids that by running encodeURIComponent and unescape first — converting the text to its raw UTF-8 byte sequence dressed up as a Latin-1 string — before calling btoa. Decoding reverses the same chain: atob, then escape, then decodeURIComponent, to reconstruct the original Unicode text exactly.
- "hello" encodes to aGVsbG8= — one padding character, since 5 bytes needs 2 extra bits of padding logic to reach a multiple of four output characters
- "hi" encodes to aGk= — 2 bytes produces exactly 3 output characters plus one =
- "Hello, World!" encodes to SGVsbG8sIFdvcmxkIQ== — 13 bytes needs two padding characters
- "Ship it 🚀" encodes to U2hpcCBpdCDwn5qA — the rocket emoji, four UTF-8 bytes on its own, is encoded losslessly through the same byte-level path
URL-safe mode swaps two characters and drops padding
Standard Base64's + and / characters both have special meaning inside a URL, so the URL-safe checkbox produces a variant with + replaced by -, / replaced by _, and any trailing = padding stripped entirely. Encoding ">>>" produces Pj4+ in standard mode and Pj4- in URL-safe mode — the same underlying bytes, just re-mapped. Decoding a URL-safe string reverses both substitutions and re-adds however many = characters are needed to reach a multiple of four, before the shared decode path runs.
What happens with malformed or truncated input
Decoding runs inside a try/catch, and any failure — an illegal character outside the 64-symbol alphabet, or a byte sequence that cannot be reassembled into valid UTF-8 after atob — collapses to the same message: "Invalid Base64 string." The tool does not distinguish between "you typed a character that isn't in the alphabet" and "the length was cut short mid-character" in its error text; both surface identically, so a garbled decode always means checking the input for stray characters or a copy-paste that dropped trailing characters.
Base64 is an encoding, not a protection
Base64 is fully reversible by design — anyone can decode it back to the original text with no key, password, or secret involved, using the same public, published alphabet this tool uses. It is the right tool for making binary data safe to embed in text formats (a data: URI, an email attachment, a JSON field) — it is never the right tool for hiding a password, API key, or anything meant to stay confidential. If something looks like Base64 in a config file, assume it is fully readable by anyone who copies it.
When decoded output is actually an image
In decode mode, if the input already starts with data:image/ or looks like a long Base64 string (over 100 characters of only Base64-alphabet characters), the tool renders an inline image preview above the text output, trying common formats — PNG, JPEG, GIF, WebP — until one displays. This makes round-tripping a data: URI copied out of browser dev tools, or checking a Base64-encoded image before embedding it in CSS, a one-paste operation instead of a manual reconstruction.