How can you encode/decode a string to Base64 in JavaScript?

To encode and decode strings to Base64 in JavaScript, you can use the built-in btoa() (encode) and atob() (decode) functions. However, these methods only handle Latin1 characters (ASCII) natively. For Unicode strings (e.g., emojis, accents), you need additional steps to encode/decode UTF-8 properly. Below are detailed solutions with examples:

1. Basic Encoding/Decoding (ASCII/Latin1)

For simple ASCII strings (no Unicode):

Encode a string to Base64:

const text = "Hello World!";
const encoded = btoa(text); // "SGVsbG8gV29ybGQh"

Decode a Base64 string:

const base64 = "SGVsbG8gV29ybGQh";
const decoded = atob(base64); // "Hello World!"

2. Handling Unicode Strings (UTF-8)

To support characters like Ç, ñ, or emojis (🦄), use TextEncoder and TextDecoder:

Encode a Unicode string to Base64:

function encodeBase64(str) {
  // Convert UTF-8 string to a Uint8Array
  const encoder = new TextEncoder();
  const data = encoder.encode(str);

  // Convert bytes to a binary string and encode as Base64
  const binaryString = String.fromCharCode(...data);
  return btoa(binaryString);
}

const unicodeText = "Hello, 世界! 🦄";
const encodedUnicode = encodeBase64(unicodeText); // "SGVsbG8sIOS4lueVjCEg8J+ajA=="

Decode a Base64 string to Unicode:

function decodeBase64(base64) {
  // Decode Base64 to a binary string
  const binaryString = atob(base64);

  // Convert binary string to Uint8Array
  const bytes = new Uint8Array(binaryString.length);
  for (let i = 0; i < binaryString.length; i++) {
    bytes[i] = binaryString.charCodeAt(i);
  }

  // Decode UTF-8 bytes back to a string
  const decoder = new TextDecoder();
  return decoder.decode(bytes);
}

const decodedUnicode = decodeBase64(encodedUnicode); // "Hello, 世界! 🦄"

3. Edge Cases

Empty String:

const emptyEncoded = btoa(""); // ""
const emptyDecoded = atob(""); // ""

Special Characters:

const textWithSymbols = "Password!@#$%^&*";
const encodedSymbols = btoa(textWithSymbols); // "UGFzc3dvcmQhQCMkJV4mKg=="
const decodedSymbols = atob(encodedSymbols); // "Password!@#$%^&*"

4. Node.js Compatibility

In Node.js, use the Buffer class instead of btoa/atob:

// Encode
const encoded = Buffer.from("Hello World!", 'utf8').toString('base64');

// Decode
const decoded = Buffer.from(encoded, 'base64').toString('utf8');

5. URL-Safe Base64

Replace + with - and / with _ for URL-safe encoding:

function encodeUrlSafeBase64(str) {
  const base64 = encodeBase64(str);
  return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

function decodeUrlSafeBase64(base64) {
  // Replace URL-safe characters and add padding
  let safeBase64 = base64.replace(/-/g, '+').replace(/_/g, '/');
  while (safeBase64.length % 4 !== 0) {
    safeBase64 += '=';
  }
  return decodeBase64(safeBase64);
}

const urlSafe = encodeUrlSafeBase64("Data? Yes!"); // "RGF0YT8gWWVzIQ"
const original = decodeUrlSafeBase64(urlSafe); // "Data? Yes!"

Key Notes

  • btoa() and atob(): Only handle Latin1 characters (no Unicode).
  • UTF-8 Support: Use TextEncoder and TextDecoder for Unicode.
  • Node.js: Replace btoa/atob with Buffer.
  • URL Safety: Adjust characters for URLs or filenames.

Full Example Workflow

// Encode
function encodeBase64(str) {
  return btoa(
    String.fromCharCode(...new TextEncoder().encode(str))
  );
}

// Decode
function decodeBase64(base64) {
  const bytes = Uint8Array.from(atob(base64), c => c.charCodeAt(0));
  return new TextDecoder().decode(bytes);
}

// Test with emojis and accents
const text = "Héllø, 𝓦orld! 👋";
const encoded = encodeBase64(text); // "SMOpbGzDuCwg8J+aksOybGTDpyEg8J+Piw=="
const decoded = decodeBase64(encoded); // "Héllø, 𝓦orld! 👋"

This approach ensures compatibility with all modern browsers and handles Unicode seamlessly!

Leave a Reply

Your email address will not be published. Required fields are marked *