Base64 Encoder and Decoder

Base64 that handles more than English.

Direction

Base64 that handles more than English.

How to use it

  1. Paste what you have. Plain text to encode, or Base64 to decode.
  2. Pick the direction. Decoding accepts either alphabet, so a JWT segment works as pasted.
  3. Copy the result. Byte counts are shown underneath, which is usually what you are checking.

When you would use this

Base64 is a fixed algorithm and the tools for it still get one thing wrong constantly, which is everything that is not English. The browser's built in btoa works on code points rather than bytes. Above U+00FF it throws an error, which at least tells you something is wrong. Between U+0080 and U+00FF it succeeds and quietly gives you the Latin-1 encoding: an e acute becomes 6Q== when the UTF-8 answer is w6k=. Nothing warns you, and the value decodes to a different character anywhere it is read as UTF-8, which is everywhere. This encodes UTF-8 bytes. The output matches what Node, Python and every other correct implementation produces, and the tests check exactly that rather than only checking it can decode its own output. An encoder can round trip against itself perfectly while producing values nothing else can read. The URL safe alphabet is a switch on encoding and is detected automatically on decoding, so a JWT segment pasted straight in works without you having to know which variant it used.

Questions

Why do other Base64 tools break on accented characters?
Because they use the browser's btoa, which fails in two ways. Above U+00FF it throws. Between U+0080 and U+00FF it silently returns the Latin-1 byte, so an e acute encodes to 6Q== where the UTF-8 answer is w6k=. No error, and the value decodes to the wrong character everywhere it is read as UTF-8. This encodes bytes, so it matches what every other UTF-8 tool produces.
What is the URL safe alphabet?
The same encoding with plus and slash replaced by minus and underscore, and the padding dropped. It is defined in RFC 4648 and it is what JWTs and query string values use, because the standard characters need escaping in a URL. Decoding here accepts both without being told which.
Is anything I paste sent anywhere?
No. It runs in the page, which is the reason to use this one rather than the first result on a search. People paste production values into these boxes constantly, and every other version receives a copy.