Skip to content

Base64 Encode / Decode — JavaScript source

Encode text to Base64 or decode it back. UTF-8 safe, runs entirely in your browser, with a shareable link to your exact input.

This is the JavaScript implementation — the same logic the interactive tool runs, in a shareable, citable form.

/**
 * base64 - UTF-8 safe Base64 encode/decode.
 *
 * Language: JavaScript (ES module; runs in browsers, Node >= 16, Bun, Deno).
 * CosmoDev polyglot showcase port of the `base64` tool.
 * Ported from src/lib/base64.ts (the canonical TypeScript implementation).
 *
 * Why this file exists: the classic btoa(str) / atob(b64) operate on Latin-1
 * code points, so they silently corrupt any character above U+00FF - emoji,
 * accents, CJK, etc. Routing the string through its UTF-8 byte sequence first
 * makes Base64 round-trip arbitrary Unicode text correctly.
 *
 * display source - part of CosmoDev's polyglot tool pages.
 */

// Web Platform primitives. TextEncoder / TextDecoder are globals in every
// modern browser and in Node >= 11; btoa / atob are globals in browsers and
// in Node >= 16. (Node-only code could also use Buffer.from(str, "utf8")
// .toString("base64"), but the TextEncoder path below is the portable one and
// mirrors the live TypeScript lib exactly.)
const encoder = new TextEncoder();
const decoder = new TextDecoder();

/**
 * Encode a Unicode string to standard, padded Base64.
 *
 * 1. Turn the string into its UTF-8 byte sequence.
 * 2. Project each byte onto a single Latin-1 code point (0-255) so btoa can
 *    swallow it as a binary string.
 * 3. Base64-encode that binary string.
 */
export function b64encode(str) {
  const bytes = encoder.encode(str);
  let binary = '';
  for (const byte of bytes) binary += String.fromCharCode(byte);
  return btoa(binary);
}

/**
 * Decode a standard Base64 string back to the original Unicode text.
 *
 * Whitespace inside the input (spaces, tabs, newlines, …) is tolerated and
 * stripped before decoding - handy for Base64 that has been line-wrapped.
 * Malformed input re-throws atob's DOMException, preserving the same
 * "throw on bad input" contract as the TypeScript original.
 */
export function b64decode(b64) {
  const cleaned = b64.replace(/\s+/g, '');
  const binary = atob(cleaned);
  const bytes = new Uint8Array(binary.length);
  for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
  return decoder.decode(bytes);
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →