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.

INPUT
OUTPUT
Type or paste to encode / decode

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.

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..."
});

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().

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 →