Base64 encoding
btoa() and atob(), with TextEncoder for text
Baseline widely available
Chrome38
Edge79
Firefox19
Safari10.1
Features it needs
- Base64 encoding and decodingWidely available
- Text encoding and decodingWidely available
btoa() and atob() have been in browsers since the beginning, and the reason people reach for a library instead is that btoa() throws on any character above U+00FF. Encoding through TextEncoder first fixes that: turn the string into UTF-8 bytes, map them to a binary string, then encode. That is four lines, and it is exactly what the libraries do.
When this applies
Encoding or decoding base64 in the browser.
The native approach
function encode(text) {
const bytes = new TextEncoder().encode(text);
const binary = String.fromCharCode(...bytes);
return btoa(binary);
}
function decode(encoded) {
const binary = atob(encoded);
const bytes = Uint8Array.from(binary, (c) => c.charCodeAt(0));
return new TextDecoder().decode(bytes);
}
encode("caffè ☕"); // "Y2FmZsOoIOKYlQ=="When the dependency is still right
An answer that always says "the platform covers it" is worse than no answer. These are the cases where this one does not hold.
- You encode large binary payloads. String.fromCharCode(...bytes) spreads the whole array onto the stack and blows up past a few hundred thousand bytes, so a chunked loop is needed and the library already has one.
- You need URL-safe base64 with the - and _ alphabet and no padding. btoa does not produce it, so the substitution is yours to write on both sides.
- You want the encoding to be synchronous and allocation-light on a hot path, where a library tuned for it can beat the two-step conversion.
- You are on a runtime where Buffer is available and simpler, such as server code that never runs in a browser.
- You rely on the library accepting input types beyond a string, for example ArrayBuffers or streams.