Encoding Strings

Base64 carries bytes through text-only channels such as JSON, data URLs and headers. It writes every 3 bytes as four 6-bit characters from A-Z a-z 0-9 + /, so output grows by a third, and = or == pads a short final group. btoa() and atob() accept only "binary strings" of single-byte characters, so convert text to UTF-8 bytes with TextEncoder first (TextEncoder and TextDecoder).

Base64, UTF-8 bytes and decoding errorsJavaScript
console.log(btoa('Hi!'), btoa('Hi'), btoa('H'), atob('SGkh'));   // padding: none, =, ==
try { btoa('€5'); } catch (err) { console.log(err.name); }       // not a Latin-1 string
const bytes = new TextEncoder().encode('€5');                    // UTF-8: € takes 3 bytes
console.log(`[${bytes}]`, bytes.toBase64(), btoa(String.fromCharCode(...bytes)));
console.log(new TextDecoder().decode(new Uint8Array([0xe2, 0x82, 0x35])));  // cut-off €, then 5
Output
SGkh SGk= SA== Hi!
InvalidCharacterError
[226,130,172,53] 4oKsNQ== 4oKsNQ==
�5

toBase64() and Uint8Array.fromBase64() (Uint8Array Base64 and Hex) replace the String.fromCharCode(...bytes) workaround, which overflows for large arrays. TextDecoder swaps malformed bytes for U+FFFD; pass { fatal: true } to throw instead. Base64 is not encryption.