An emoji can make btoa() throw. An accented letter can pass without an error—and still produce bytes your UTF-8 decoder cannot read. Those are different failures, and confusing them makes debugging harder.
Correction, 10 October 2026: the earlier version said that decoding the Latin-1 result as UTF-8 produces é. That direction was wrong. A strict UTF-8 decoder rejects the Latin-1 byte; café appears in our example when UTF-8 bytes are treated as Latin-1 characters. The examples below separate the two. We also reproduced and corrected an invisible leading-BOM loss in the text tool.
Why btoa() rejects emoji but accepts é
The browser’s btoa encodes a string whose characters stand for byte values from 0 to 255. It does not automatically turn ordinary JavaScript text into UTF-8.
An emoji such as 🌍 cannot be passed directly: btoa('Hello 🌍') throws InvalidCharacterError. But é (U+00E9) fits inside the byte range. btoa('café') therefore succeeds and returns Y2Fm6Q==. Its last decoded byte is E9, not the UTF-8 sequence C3 A9 for é.
Accepting the input is not the same as choosing the encoding you intended. MDN’s btoa reference distinguishes byte-valued strings from Unicode text.
Same-looking text, different bytes
These invented examples have no newline at the end:
| Path | Base64 | Result |
|---|---|---|
btoa('café') → atob | Y2Fm6Q== | café as byte-valued Latin-1 characters |
btoa('café') → this UTF-8 text decoder | Y2Fm6Q== | explicit non-UTF-8 error; no text to copy |
UTF-8 bytes for café → this decoder | Y2Fmw6k= | café |
UTF-8 bytes for café → atob treated as text | Y2Fmw6k= | café |
Try the two Base64 values in the English text tool with Decode selected. One returns café; the other reports that its bytes are not valid UTF-8. An error does not mean you need a password. This is a text decoder, not a file or image viewer.
We checked the byte values with Node Buffer, the browser-style btoa/atob APIs and the site’s conversion tests. These checks cover the stated samples—not every possible input or a security audit of your device.
Encode UTF-8 bytes, then decode them as UTF-8
For ordinary Unicode text, first use TextEncoder to get UTF-8 bytes and encode those bytes as Base64. Decode the bytes through a UTF-8 TextDecoder with errors reported rather than replaced.
Hello 🌍 produces SGVsbG8g8J+MjQ== in this tool. Decoding that value returns the same text. A JavaScript string containing an unmatched UTF-16 surrogate is rejected instead of silently becoming �. A literal � that was already part of valid input is a different case and is preserved.
What if an invisible character disappears?
A leading U+FEFF can look like nothing on screen. Its UTF-8 bytes are EF BB BF. The harmless value 77u/Y2Fmw6k= represents U+FEFF followed by café—five Unicode code points, not four.
The previous tool silently removed that first character. The corrected decoder keeps it and displays a BOM notice explaining that copied output includes the invisible character. Re-encoding the preserved text returns 77u/Y2Fmw6k=; it must not quietly become Y2Fmw6k=. This is deliberate preservation, not automatic cleanup of a text file. The Encoding Standard specifies how the decoder’s BOM option controls that behavior.
The output counter is labelled UTF-16 code units, not visible symbols. For example, the moon 🌙 takes two UTF-16 code units, while this BOM-plus-café example takes five. Do not use that counter as a UTF-8 byte count.
URL-safe is an alphabet, not a privacy guarantee
Standard Base64 uses + and /; base64url uses - and _. This tool removes trailing = in its URL-safe encoding mode and accepts missing padding when decoding. Other formats can have different padding requirements, so check the receiving format. RFC 4648 describes the alphabets and padding rules.
The URL-safe form of Hello 🌍 here is SGVsbG8g8J-MjQ. A test JWT viewer can inspect a harmless token’s structure, but this alphabet does not verify a signature or protect the contents. For a complete value destined for a query string, use the URL encoder as required by that URL format.
Before you paste or share
Base64 is reversible encoding, not encryption. This code is not a secret offers another invented example to try. Do not paste production access tokens, passwords or private conversations to investigate them; follow an approved local workflow.
Conversion functions run in the browser. That describes their execution location—not a guarantee about the entire page, clipboard, extensions or device. Use the supplied sample or non-sensitive test values only.
The cover is an AI-generated concept illustration, not a tool screenshot or a photograph of a tested conversion.