Base64 to Text JS: Decoding in JavaScript Correctly
Decoding Base64 in JavaScript is one function call — and that function predates Unicode support in the language, which is why so much JavaScript Base64 code is subtly broken.
atob and its blind spot
atob(b64) returns a binary string where each character is one byte. For pure ASCII content that is already the text you want. For anything else it is not:
atob('aGVsbG8='); // 'hello' — fine
atob('Y2Fmw6k='); // 'café' — wrong, bytes shown as Latin-1
The mangled output is the signature of this bug: correct bytes, wrong interpretation.
The correct decode
Convert the binary string to a byte array, then decode those bytes as UTF-8:
const fromBase64 = (b64) =>
new TextDecoder().decode(
Uint8Array.from(atob(b64), (c) => c.charCodeAt(0))
);
fromBase64('Y2Fmw6k='); // 'café'
atob throws InvalidCharacterError on malformed input, so wrap it in try/catch whenever the string comes from a user, a URL or an API.
base64url
JWT segments and URL-safe payloads use a different alphabet and usually no padding. Translate before decoding:
const fromBase64Url = (s) => {
const b64 = s.replace(/-/g, '+').replace(/_/g, '/');
return fromBase64(b64.padEnd(b64.length + ((4 - (b64.length % 4)) % 4), '='));
};
Node.js
In Node.js, Buffer replaces the whole atob routine: it handles both directions and both alphabets, and you name the text encoding explicitly:
Buffer.from('Y2Fmw6k=', 'base64').toString('utf8'); // 'café'
Buffer.from('café', 'utf8').toString('base64'); // 'Y2Fmw6k='
Buffer.from(token, 'base64url').toString('utf8'); // Node 16+
Frequently asked questions
Why does my decoded text show "é"?
atob returned bytes that were displayed as Latin-1. Decode them as UTF-8 with TextDecoder.
Is atob deprecated?
Not in browsers, where it remains part of the HTML standard. Node.js does mark its global `atob` as legacy and recommends `Buffer.from(data, 'base64')` instead.
What is the Node equivalent?
`Buffer.from(str, 'base64').toString('utf8')`. The `base64url` encoding was added in Node.js 15.7.0 and 14.18.0.