A virtual teacher who reveals to you the great secrets of Base64

Implementing Unicode support for btoa() and atob()

By default JavaScript built-in functions btoa and atob do not support Unicode strings, because these functions treat all characters as 16-bit-encoded strings (that is, are accepted only characters from the extended ASCII table, up to 255 char code). Thus, trying to encode a multibyte character to Base64, the btoa function will throw exception “Character Out Of Range” or “Invalid Character Error”. On other hand, trying to decode a Base64 string that contains multibyte characters, the atob function will return some “weird” characters.

To bypass this limitation we should apply some hacks. For example, on the MDN portal are provided atou and utoa functions.

 * ASCII to Unicode (decode Base64 to original data)
 * @param {string} b64
 * @return {string}
function atou(b64) {
  return decodeURIComponent(escape(atob(b64)));
 * Unicode to ASCII (encode data to Base64)
 * @param {string} data
 * @return {string}
function utoa(data) {
  return btoa(unescape(encodeURIComponent(data)));

Let’s do some tests, to be sure that the functions above support Unicode strings:

// Both the “pi” and the “approximately equal” symbols are Unicode characters
// As you can see, btoa() fails to encode `str`, while utoa() works like a charm
var str = 'π ≈ 3.14159';
console.log(btoa(str)); //-> "InvalidCharacterError: String contains an invalid character"
console.log(utoa(str)); //-> "z4Ag4omIIDMuMTQxNTk="

// This is the Base64 value for `str` above (I encoded it using the https://base64.guru/converter)
// As you can see, atob() decodes it but return wrong result, while atou() does it properly
var b64 = 'z4Ag4omIIDMuMTQxNTk=';
console.log(atob(b64)); //-> "Ï� â�� 3.14159"
console.log(atou(b64)); //-> "π ≈ 3.14159"

For more info, please check the MDN documentation: Base64 encoding and decoding.

Add new comment
