Base64 in JavaScript (btoa/atob)
Master Base64 encoding and decoding in JavaScript using btoa(), atob(), and modern alternatives. Covers Unicode handling, browser vs Node.js differences.
Detailed Explanation
JavaScript provides two built-in global functions for Base64: btoa() for encoding and atob() for decoding. These names come from early Netscape implementations -- btoa stands for "binary to ASCII" and atob stands for "ASCII to binary."
Basic usage:
// Encoding
const encoded = btoa("Hello, World!");
console.log(encoded); // "SGVsbG8sIFdvcmxkIQ=="
// Decoding
const decoded = atob("SGVsbG8sIFdvcmxkIQ==");
console.log(decoded); // "Hello, World!"
The Unicode problem: btoa() only accepts strings where every character's code point is between 0 and 255 (Latin-1 range). Passing a string like btoa("café") or btoa("☃") throws an InvalidCharacterError. The fix is to encode to UTF-8 first:
// Encode Unicode to Base64
function utoa(str) {
return btoa(unescape(encodeURIComponent(str)));
}
// Decode Base64 to Unicode
function atou(b64) {
return decodeURIComponent(escape(atob(b64)));
}
// Modern approach (2024+)
const encoded = btoa(String.fromCodePoint(
...new TextEncoder().encode("Hello ☃")
));
Browser vs Node.js:
- Browsers have had
btoa()andatob()since the earliest days. They are available in window, worker, and service worker contexts. - Node.js added global
btoa()andatob()in version 16. Before that, you had to useBuffer:
// Node.js Buffer approach (still common)
Buffer.from("Hello").toString("base64"); // encode
Buffer.from("SGVsbG8=", "base64").toString(); // decode
File handling in the browser:
// Using FileReader for files
const reader = new FileReader();
reader.onload = () => console.log(reader.result);
reader.readAsDataURL(file); // returns data:...;base64,...
Performance note: For very large strings (several megabytes), btoa() may block the main thread. Consider using a Web Worker or chunking the data for better responsiveness.
Use Case
Building a client-side file converter that reads user-uploaded images, converts them to Base64, and displays them inline without any server round-trip.