Base64 Encoder / Decoder3 min readOct 21, 2026

How to Fix 'Failed to execute btoa on Window: character outside Latin1 range'

Resolve the 'character outside Latin1 range' DOMException when calling btoa() on UTF-8 strings. Learn the modern TextEncoder solution.

Direct Summary (TL;DR)

The native browser window.btoa() function only supports characters within the Latin-1 range (code points 0x00 to 0xFF). When given Unicode strings containing emojis, accented characters, or non-Latin alphabets, it throws a DOMException: character outside Latin1 range. Fix it using the modern TextEncoder and Uint8Array API.

Interactive Mickytool Utility

Solve this problem now with our free Base64 Encoder / Decoder

Try it instantly in your browser — zero tracking, 100% client-side privacy.

Open Base64 Encoder / Decoder

Specification & Architecture Reference

How to Fix 'Failed to execute btoa on Window: character outside Latin1 range' — Technical Summary
MethodUnicode / Emoji SupportRecommended Modern Environment
window.btoa(str)❌ Throws DOMException for code points > 255Legacy ASCII-only strings
btoa(unescape(encodeURI(str)))⚠️ Deprecated, uses legacy unescape()Legacy IE11 workarounds
TextEncoder + Uint8Array✅ Full UTF-8 compliantModern Browsers & Node.js 18+
Buffer.from(str).toString('base64')✅ Full UTF-8 compliantNode.js runtime server-side

Why window.btoa Fails on Modern Strings

The name `btoa` stands for "binary to ASCII". Developed in early browser eras, the function assumes that every character in the provided string occupies exactly 1 byte (8 bits, representing the **Latin-1 / ISO-8859-1** character set).

However, modern JavaScript strings use **UTF-16 encoding**. When you pass characters with code points above 255—such as emojis (🚀), em-dashes (—), or non-Latin alphabets (e.g., Chinese, Arabic, Cyrillic)—`btoa` cannot fit the multi-byte code units into Latin-1 bytes and throws: ```text Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range. ```

The Modern, Standards-Compliant Solution Use the standardized **TextEncoder API** to encode the string into an array of UTF-8 bytes, then convert those bytes into a Base64 string:

javascript
function utf8ToBase64(str) {
  const bytes = new TextEncoder().encode(str);
  const binString = Array.from(bytes, (byte) => String.fromCharCode(byte)).join("");
  return btoa(binString);

function base64ToUtf8(base64) { const binString = atob(base64); const bytes = Uint8Array.from(binString, (m) => m.charCodeAt(0)); return new TextDecoder().decode(bytes); }

// Example: const encoded = utf8ToBase64("Hello 🌍! Mickytool makes dev tools."); console.log(encoded); // "SGVsbG8g8J+MjfCfkJkhIE1pY2t5dG9vbCBtYWtlcyBkZXYgdG9vbHMu" console.log(base64ToUtf8(encoded)); // Restored with emoji intact! ```

Avoid encoding errors by formatting and validating your Unicode strings in Mickytool's **Base64 Encoder / Decoder**, which handles multi-byte UTF-8 streams out of the box.

Interactive Mickytool Utility

Solve this problem now with our free Base64 Encoder / Decoder

Execute this workflow immediately without saving data on remote servers.

Open Base64 Encoder / Decoder

Frequently Asked Questions

Why was encodeURI(str) used in older solutions?

Older workarounds used unescape(encodeURIComponent(str)) to turn multi-byte UTF-8 characters into percent-escaped byte values. However, unescape() is officially deprecated.

Does atob() also fail when decoding UTF-8 strings?

Yes. Calling atob() on Base64 produced from UTF-8 bytes produces a scrambled binary string (Mojibake) unless decoded via TextDecoder.

Related Engineering Guides