Uint8Array Base64 and Hex

btoa() and atob() handle only "binary strings", so they throw on text outside Latin-1. ES2026 adds direct conversions (Baseline 2025; also in Node.js 25.8 2,131 ): toBase64({ alphabet, omitPadding }), Uint8Array.fromBase64(), setFromBase64() into an existing array, and toHex(), Uint8Array.fromHex() and setFromHex(). The 'base64url' alphabet uses - and _ as in URLs and JWTs.

UTF-8 text to Base64, Base64URL and hex, and backJavaScriptLive
const bytes = new TextEncoder().encode('Hi? ✓');           // UTF-8 bytes
console.log(bytes.toBase64(), bytes.toBase64({ alphabet: 'base64url', omitPadding: true }));
console.log(bytes.toHex(), new TextDecoder().decode(Uint8Array.fromHex('4869')));
const target = new Uint8Array(4);                          // preallocated
console.log(target.setFromBase64('SGk/IOKckw=='), target);

setFromBase64() stops at the last whole chunk that fits and reports read so you can resume. Invalid input throws a SyntaxError. For older browsers, feature-detect and load the core-js 25,536 polyfill (Polyfills).