btoa()
A byte-to-base64 converter that takes a string, which is the source of all its trouble. Feeding it real Unicode text throws, and the fix is to encode to UTF-8 bytes first.
Demo
ASCII encodes cleanly, and the = padding appears whenever the input length is not a multiple of three. The é case works because U+00E9 fits in one byte — but note that it encodes the LATIN-1 byte, not the UTF-8 pair, so decoding it elsewhere as UTF-8 gives the wrong character. The fourth case is the hard limit: 中 is U+4E2D, above 255, and btoa throws rather than encoding it. Any text that might contain non-Latin-1 characters must be converted to UTF-8 bytes first.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| string | string | yes | A "binary string" — one where every character is in the range U+0000 to U+00FF and stands for one byte. Anything above that throws. |
Return value
string — The base64 encoding of the input, treating each character as ONE BYTE. Throws InvalidCharacterError for any code point above 255.
Common patterns
const bytes = new TextEncoder().encode(text); const b64 = btoa(String.fromCharCode(...bytes));
const bytes = Uint8Array.from(atob(b64), c => c.charCodeAt(0)); const text = new TextDecoder().decode(bytes);
const src = `data:image/svg+xml;base64,${btoa(svg)}`;
Examples
Pitfalls
btoa('中文')
btoa(String.fromCharCode(...new TextEncoder().encode('中文')))
btoa('é')
btoa(String.fromCharCode(...new TextEncoder().encode('é')))
atob(btoa('my-secret'))
await crypto.subtle.encrypt(alg, key, data)
btoa('\xff\xfe')
btoa(s).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
When to use
- Data URLs for inline images and SVG
- Basic auth headers, which the spec defines in base64
- Putting binary data into JSON or a text field
- Round-tripping bytes through something that only accepts text
- Unicode text → encode to UTF-8 bytes first
- Hiding secrets → it is not encryption
- URLs → translate to the URL-safe alphabet
- Large binary data → work with ArrayBuffer and streams instead
Notes
FAQ
Because it contains a character above U+00FF and btoa only handles bytes. Convert to UTF-8 with TextEncoder first, then turn those bytes into a binary string.
const b64 = btoa(String.fromCharCode(...new TextEncoder().encode(text)));