base-64 vs base64-js vs btoa vs js-base64
Encoding Binary Data and Strings in JavaScript
base-64base64-jsbtoajs-base64Similar Packages:

Encoding Binary Data and Strings in JavaScript

These libraries provide solutions for Base64 encoding and decoding in JavaScript environments. While browsers and modern Node.js include native btoa and atob functions, they fail when handling Unicode characters (like emojis or non-English text). base-64, base64-js, and js-base64 offer robust alternatives that handle UTF-8 correctly, while the btoa npm package serves primarily as a polyfill for older environments. Choosing the right tool depends on whether you are processing text strings or raw binary data like files.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
base-640520-126 years agoMIT
base64-js08809.62 kB46 years agoMIT
btoa0---8 years ago(MIT OR Apache-2.0)
js-base6404,36639 kB1110 months agoBSD-3-Clause

Encoding Data in JavaScript: base-64 vs base64-js vs btoa vs js-base64

Handling Base64 encoding in JavaScript seems simple until you encounter Unicode characters. The native btoa function breaks when given emojis or non-ASCII text. This comparison looks at four npm packages that address this problem — each with a different focus on strings, binary data, or compatibility.

📝 Text Encoding: Handling Unicode Correctly

The most common mistake is using native btoa for user input. It expects Latin1 strings. If you pass a emoji, it throws an error. These packages solve that by converting text to UTF-8 bytes first.

base-64 handles UTF-8 strings automatically. It is lightweight and focused purely on string conversion.

import * as base64 from 'base-64';

const text = 'Hello 🌍';
const encoded = base64.encode(text);
const decoded = base64.decode(encoded);

console.log(decoded); // 'Hello 🌍'

js-base64 also handles UTF-8 strings and provides a familiar static class interface. It is widely used in larger applications.

import { Base64 } from 'js-base64';

const text = 'Hello 🌍';
const encoded = Base64.encode(text);
const decoded = Base64.decode(encoded);

console.log(decoded); // 'Hello 🌍'

btoa (npm package) mimics the native browser function. It does not fix Unicode issues by itself. You still need to escape the string manually.

import btoa from 'btoa';

const text = 'Hello 🌍';
// This will throw an error or produce garbage without manual UTF-8 escaping
// const encoded = btoa(unescape(encodeURIComponent(text))); 

base64-js does not accept strings directly. It works with binary arrays. You must convert the string to bytes first.

import * as base64js from 'base64-js';

const text = 'Hello 🌍';
const uint8 = new TextEncoder().encode(text);
const encoded = base64js.fromUint8Array(uint8);

// Decoding requires reversing the process
const decodedUint8 = base64js.toUint8Array(encoded);
const decoded = new TextDecoder().decode(decodedUint8);

🗂️ Binary Data: Uint8Array and Buffers

When working with files, images, or network packets, you often deal with binary data rather than text. This is where the packages diverge significantly.

base64-js is built specifically for this. It converts between Uint8Array and Base64 strings efficiently.

import * as base64js from 'base64-js';

const binaryData = new Uint8Array([72, 101, 108, 108, 111]); // 'Hello'
const base64String = base64js.fromUint8Array(binaryData);
const restoredBinary = base64js.toUint8Array(base64String);

base-64 works primarily with strings. To use it with binary data, you must convert bytes to a string first, which adds overhead.

import * as base64 from 'base-64';

// Requires manual conversion to string representation of bytes
// Not ideal for raw binary workflows

js-base64 focuses on strings. While it can handle binary data represented as strings, it is not optimized for raw Uint8Array manipulation like base64-js.

import { Base64 } from 'js-base64';

// Best for string payloads, not raw binary buffers
const encoded = Base64.encode('binary-like-string');

btoa expects a "binary string" where each character represents a byte. Passing real binary data requires careful mapping.

import btoa from 'btoa';

// Only works if input is a Latin1 string representing bytes
// Not safe for arbitrary Uint8Array without conversion

🔗 URL Safety: Special Characters

Standard Base64 uses + and /, which have special meanings in URLs. If you put Base64 in a URL query parameter, it might break. You need URL-safe Base64 (using - and _).

js-base64 has built-in methods for this. It is the strongest choice for URL parameters.

import { Base64 } from 'js-base64';

const safeEncoded = Base64.encodeURI('data+with/special');
// Uses - and _ instead of + and /

base-64 does not have a dedicated URL-safe method. You must replace characters manually.

import * as base64 from 'base-64';

const encoded = base64.encode('data+with/special');
const urlSafe = encoded.replace(/\+/g, '-').replace(/\//g, '_');

base64-js produces standard Base64. You must implement URL-safe logic yourself if needed.

import * as base64js from 'base64-js';

const encoded = base64js.fromUint8Array(data);
const urlSafe = encoded.replace(/\+/g, '-').replace(/\//g, '_');

btoa produces standard Base64. No URL-safe support included.

import btoa from 'btoa';

const encoded = btoa('data');
// Manual replacement required for URL safety

⚠️ Maintenance and Environment Support

Knowing where these packages run helps avoid build errors.

btoa is largely obsolete. Modern Node.js (v16+) and all browsers have global btoa. The npm package is only useful for very old Node versions.

// Modern Node.js or Browser
const encoded = btoa('text'); // Native global available

base-64 works everywhere. It has no dependencies and is small.

// Works in Node, Browser, Web Workers
import * as base64 from 'base-64';

js-base64 works everywhere. It is slightly larger but offers more features.

// Works in Node, Browser, TypeScript projects
import { Base64 } from 'js-base64';

base64-js works everywhere. It is the standard for binary conversion.

// Works in Node, Browser, React Native
import * as base64js from 'base64-js';

📊 Summary Table

Featurebase-64base64-jsbtoa (npm)js-base64
Unicode Support✅ Yes✅ Yes (via Uint8)❌ No (Manual)✅ Yes
Input TypeStringUint8ArrayStringString
URL Safe❌ Manual❌ Manual❌ Manual✅ Built-in
Binary Focus❌ Low✅ High❌ Low❌ Low
Status✅ Active✅ Active⚠️ Legacy✅ Active

💡 Final Recommendation

For most frontend developers, the choice comes down to what you are encoding.

If you are encoding text strings (like JSON payloads or user input) and need Unicode support, use base-64 for simplicity or js-base64 if you need URL-safe variants. They handle the UTF-8 conversion automatically, which saves you from subtle bugs.

If you are encoding binary files (like images or blobs) and already have a Uint8Array, use base64-js. It is optimized for byte manipulation and avoids unnecessary string conversions.

Avoid the btoa npm package. It solves a problem (missing global function) that no longer exists in modern environments, and it does not fix the Unicode issue that actually matters.

Final Thought: Native APIs are improving, but for cross-platform Unicode safety, a dedicated library is still the safest bet for production apps.

How to Choose: base-64 vs base64-js vs btoa vs js-base64

  • base-64:

    Choose base-64 if you need a lightweight, dependency-free solution for encoding UTF-8 strings in both browser and Node.js. It is ideal for simple text encoding tasks where you want to avoid the Unicode pitfalls of the native btoa function without adding a heavy library.

  • base64-js:

    Choose base64-js if you are working directly with binary data such as Uint8Array or Buffer objects. It is the best fit for low-level operations like file processing, image manipulation, or WebSocket binary frames where string encoding is not the primary goal.

  • btoa:

    Avoid the btoa npm package in new projects. It is essentially a polyfill for the native browser function and does not solve Unicode issues on its own. Modern Node.js versions and all browsers already include global btoa, making this package redundant for most use cases.

  • js-base64:

    Choose js-base64 if you need advanced features like URL-safe encoding or comprehensive Unicode support out of the box. It is well-suited for complex applications that require encoding data for URLs, cookies, or transmission over protocols that restrict standard Base64 characters.

README for base-64

base64 Build status Code coverage status

base64 is a robust base64 encoder/decoder that is fully compatible with atob() and btoa(), written in JavaScript. The base64-encoding and -decoding algorithms it uses are fully RFC 4648 compliant.

Installation

Via npm:

npm install base-64

In a browser:

<script src="base64.js"></script>

In Narwhal, Node.js, and RingoJS:

var base64 = require('base-64');

In Rhino:

load('base64.js');

Using an AMD loader like RequireJS:

require(
  {
    'paths': {
      'base64': 'path/to/base64'
    }
  },
  ['base64'],
  function(base64) {
    console.log(base64);
  }
);

API

base64.version

A string representing the semantic version number.

base64.encode(input)

This function takes a byte string (the input parameter) and encodes it according to base64. The input data must be in the form of a string containing only characters in the range from U+0000 to U+00FF, each representing a binary byte with values 0x00 to 0xFF. The base64.encode() function is designed to be fully compatible with btoa() as described in the HTML Standard.

var encodedData = base64.encode(input);

To base64-encode any Unicode string, encode it as UTF-8 first:

var base64 = require('base-64');
var utf8 = require('utf8');

var text = 'foo © bar 𝌆 baz';
var bytes = utf8.encode(text);
var encoded = base64.encode(bytes);
console.log(encoded);
// → 'Zm9vIMKpIGJhciDwnYyGIGJheg=='

base64.decode(input)

This function takes a base64-encoded string (the input parameter) and decodes it. The return value is in the form of a string containing only characters in the range from U+0000 to U+00FF, each representing a binary byte with values 0x00 to 0xFF. The base64.decode() function is designed to be fully compatible with atob() as described in the HTML Standard.

var decodedData = base64.decode(encodedData);

To base64-decode UTF-8-encoded data back into a Unicode string, UTF-8-decode it after base64-decoding it:

var encoded = 'Zm9vIMKpIGJhciDwnYyGIGJheg==';
var bytes = base64.decode(encoded);
var text = utf8.decode(bytes);
console.log(text);
// → 'foo © bar 𝌆 baz'

Support

base64 is designed to work in at least Node.js v0.10.0, Narwhal 0.3.2, RingoJS 0.8-0.9, PhantomJS 1.9.0, Rhino 1.7RC4, as well as old and modern versions of Chrome, Firefox, Safari, Opera, and Internet Explorer.

Unit tests & code coverage

After cloning this repository, run npm install to install the dependencies needed for development and testing. You may want to install Istanbul globally using npm install istanbul -g.

Once that’s done, you can run the unit tests in Node using npm test or node tests/tests.js. To run the tests in Rhino, Ringo, Narwhal, and web browsers as well, use grunt test.

To generate the code coverage report, use grunt cover.

Author

twitter/mathias
Mathias Bynens

License

base64 is available under the MIT license.