Base64 Encode & Decode in JavaScript
Encode or decode below — it runs locally in your browser — then grab the canonical JavaScript code. The built-in btoa() and atob() only handle Latin-1, so Unicode text needs TextEncoder / TextDecoder first.
Last updated
Encode and decode a string
For plain ASCII, btoa() encodes and atob() decodes:
// Encode
const encoded = btoa("Hello, world!");
console.log(encoded); // "SGVsbG8sIHdvcmxkIQ=="
// Decode
const decoded = atob("SGVsbG8sIHdvcmxkIQ==");
console.log(decoded); // "Hello, world!"
For Unicode (emoji, accents, non-Latin scripts), encode to UTF-8 bytes first, then convert to a binary string for btoa():
// Unicode-safe encode
function encodeBase64(str) {
const bytes = new TextEncoder().encode(str);
const binary = String.fromCharCode(...bytes);
return btoa(binary);
}
// Unicode-safe decode
function decodeBase64(base64) {
const binary = atob(base64);
const bytes = Uint8Array.from(binary, c => c.charCodeAt(0));
return new TextDecoder().decode(bytes);
}
encodeBase64("Hello 🌍"); // "SGVsbG8g8J+MjQ=="
Tip: btoa() only accepts Latin-1 (code points 0–255). Passing emoji or accented text raises InvalidCharacterError — always run Unicode strings through TextEncoder first.
The modern way: Uint8Array.toBase64()
As of 2025 (ES2026), browsers and Node.js 22+ ship native Uint8Array.prototype.toBase64() and Uint8Array.fromBase64(). They work directly on bytes, so Unicode "just works" with no String.fromCharCode dance:
// Encode: string -> bytes -> Base64
const bytes = new TextEncoder().encode("Hello 🌍");
bytes.toBase64(); // "SGVsbG8g8J+MjQ=="
bytes.toBase64({ alphabet: "base64url", omitPadding: true }); // URL-safe
// Decode: Base64 -> bytes -> string
const decoded = Uint8Array.fromBase64("SGVsbG8g8J+MjQ==");
new TextDecoder().decode(decoded); // "Hello 🌍"
Support: shipped in Chrome, Firefox, Safari, Node 22+, Deno, and Bun. For older runtimes, fall back to the TextEncoder + btoa() pattern above.
URL-safe Base64
For JWTs, URLs, and filenames, swap + and / for - and _ and drop the padding:
// Encode to URL-safe Base64
function toBase64URL(str) {
return encodeBase64(str)
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/, ""); // remove padding
}
// Decode URL-safe Base64
function fromBase64URL(base64url) {
let base64 = base64url.replace(/-/g, "+").replace(/_/g, "/");
while (base64.length % 4) base64 += "="; // restore padding
return decodeBase64(base64);
}
Encode a file
In the browser, use the FileReader API to read a file as a Base64 data URI:
function fileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result); // data:mime;base64,...
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
// Usage with a file input
input.addEventListener("change", async (e) => {
const dataUri = await fileToBase64(e.target.files[0]);
console.log(dataUri); // "data:image/png;base64,iVBOR..."
});
Base64 in Node.js
On the server there's no btoa() needed — the Buffer class is the idiomatic API and handles Unicode automatically:
// Encode / decode a string
const encoded = Buffer.from("Hello, world! 🌍").toString("base64");
const decoded = Buffer.from(encoded, "base64").toString("utf8");
// URL-safe Base64 (Node 16+)
Buffer.from("Hello").toString("base64url");
// Encode a file
const fs = require("fs");
const b64 = fs.readFileSync("image.png").toString("base64");
fs.writeFileSync("copy.png", Buffer.from(b64, "base64"));
See the Node.js tool page for a runnable version, or the Node.js guide for streams and large files.
Frequently asked questions
How do I Base64 encode a string in JavaScript?
Use btoa("Hello") for ASCII, which returns "SGVsbG8=". For Unicode, encode to UTF-8 with new TextEncoder().encode(str) first, then btoa() the binary string.
How do I Base64 decode in JavaScript?
atob("SGVsbG8=") returns the binary string "Hello"; for Unicode, pass the bytes through new TextDecoder().decode().
Why does btoa() throw an InvalidCharacterError?
btoa() only accepts Latin-1 characters (0–255). Emoji and non-Latin text throw — encode to UTF-8 bytes with TextEncoder first.
How do I do URL-safe Base64?
Apply .replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "") to the standard output, then reverse it before atob(). Or in modern runtimes, bytes.toBase64({ alphabet: "base64url" }).
How do I Base64 encode in Node.js?
Use Buffer: Buffer.from("Hello").toString("base64") to encode and Buffer.from(b64, "base64").toString("utf8") to decode. It handles Unicode automatically and supports "base64url" for URL-safe output.
Is btoa() deprecated?
No — btoa()/atob() are not deprecated and still work everywhere. But the newer Uint8Array.toBase64()/fromBase64() methods are the recommended modern approach: they operate on bytes, so they handle Unicode and URL-safe alphabets without workarounds.
Need image, file, or URL-safe modes?
The main base64.dev tool handles text, images, files, and URL-safe Base64 with auto-detect.
Open base64.dev →