Explain Codes LogoExplain Codes Logo

Base64 encoding and decoding in client-side Javascript

javascript
base64
encoding
decoding
Alex KataevbyAlex Kataev·Jan 30, 2025
TLDR
**Encode** text to Base64: ```javascript // Btoa in action: it does "behind the scenes" String "magic" const encoded = btoa('Text to encode');

Decode Base64 to text:

// Atob returns: it's like you've caught a falling star const decoded = atob(encoded);

Use encodeURIComponent for URLs:

// A well-formatted URL is the key to every door... or at least many! const urlEncoded = btoa(encodeURIComponent('Text to encode'));

Tackling the wild unicorns of Unicode in encoding

Ever felt lost handling Unicode characters while encoding with btoa()? Fear not, because we have a fix: UTF-8 encode strings before turning them into Base64.

// Taming unicorns by UTF-8 encoding; catch 'em all! function utf8_to_b64(str) { return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) => String.fromCharCode('0x' + p1))); }

Reverting the magic: decoding Unicode

When it's time to turn the magic off and revert Base64 encoding of a Unicode string:

// Reviving unicorns from their deep sleep function b64_to_utf8(str) { return decodeURIComponent(atob(str).split('').map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join('')); }

Buffers, Buffers, Buffers: Node.js tango with Base64

For Node.js users, btoa() and atob() unfortunately don't make the cut. Instead, we use Buffer.

// Encoding Base64: Node.js does some weightlifting using Buffers let buff = Buffer.from('Text to encode', 'utf-8'); let base64data = buff.toString('base64'); // Decoding Base64: Buffers are like the Swiss army knife of Node.js let buff = Buffer.from(base64data, 'base64'); let text = buff.toString('utf-8');

Dance like no one is watching: Cross-browser encoding with CryptoJS

If you want to ensure your Base64 encoding gets along with older browsers too, CryptoJS is your best friend.

var CryptoJS = require('crypto-js'); // Encoding: CryptoJS jots on the Base64 string with style var encodedWord = CryptoJS.enc.Utf8.parse('Text to encode'); var encoded = CryptoJS.enc.Base64.stringify(encodedWord); // Decoding: CryptoJS deciphers the encoded string back in text. Abracadabra! var decodedWord = CryptoJS.enc.Base64.parse(encoded); var decoded = decodedWord.toString(CryptoJS.enc.Utf8);

Best practices, tips and tricks

Here are a handful of ideas that can help improve performance, avoid errors, and make sure your Base64 game is on point.

  1. Break down: Handle large Base64 strings in segments to prevent your app from stumbling.
  2. Clean up: Always remove newline characters (\r or \n) before decoding, and trailing nulls (\0) from the decoded results.
  3. Custom Maps: If you're implementing custom Base64 functions, consider mapping Base64 characters to decimals.
  4. Bitwise Operations: Optimize custom decoding through bitwise operations.
  5. Incremental processing: Consider handling Base64 data incrementally. Every millisecond counts!

Visualization

To visualize Base64 encoding and decoding in client-side Javascript:

🏷️ is your data ⇒ btoa() wraps it like a gift 🎁 ⇒ and atob() unwraps it back to 🏷️ whenever you want. Pretty cool, eh?

File handling and binary data

Usually binary data are like an adrift ship in the vast JavaScript ocean. To guide them properly:

  1. FileReader.readAsDataURL() to convert files into Base64 strings.

    const reader = new FileReader(); reader.readAsDataURL(fileBlob); reader.onloadend = () => { let base64data = reader.result; console.log(base64data); };
  2. Converting binary arrays into Base64:

let uintArray = new Uint8Array(buffer); // You gotta byte your way through these tiny bits* let string = String.fromCharCode.apply(null, uintArray); let encodedData = btoa(string);