base-64 vs js-base64
Base64 Encoding and Decoding in JavaScript Environments
base-64js-base64Similar Packages:

Base64 Encoding and Decoding in JavaScript Environments

base-64 and js-base64 are both JavaScript libraries designed to handle Base64 encoding and decoding operations. While the Web API provides native atob() and btoa() functions, they have limitations regarding Unicode characters and server-side (Node.js) compatibility. base-64 is a minimal, strict implementation focused on RFC 4648 compliance, often used in Node.js environments. js-base64 is a more feature-rich library that handles Unicode strings gracefully without requiring manual encoding steps, making it popular for frontend applications dealing with international text. Both libraries aim to provide reliable Base64 transformations where native browser APIs fall short.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
base-640519-126 years agoMIT
js-base6404,36639 kB1110 months agoBSD-3-Clause

Base64 Encoding in JavaScript: base-64 vs js-base64

When working with binary data, URLs, or storage in JavaScript, Base64 encoding is a common requirement. While browsers provide native atob() and btoa() functions, they fail with Unicode characters (throwing errors on emojis or non-Latin scripts) and are unavailable in older Node.js versions without buffers. Two popular npm packages solve this: base-64 and js-base64. Let's compare how they handle encoding, Unicode, and environment compatibility.

📝 Basic Encoding and Decoding

Both libraries provide standard functions to convert strings to Base64 and back. However, their input expectations differ slightly regarding binary data handling.

base-64 exports simple encode and decode functions. It treats input strictly as binary data represented in a string.

import base64 from 'base-64';

const encoded = base64.encode('Hello World');
console.log(encoded); // 'SGVsbG8gV29ybGQ='

const decoded = base64.decode(encoded);
console.log(decoded); // 'Hello World'

js-base64 offers a similar API but is often used via a global Base64 object or imported methods. It focuses on string safety.

import { encode, decode } from 'js-base64';

const encoded = encode('Hello World');
console.log(encoded); // 'SGVsbG8gV29ybGQ='

const decoded = decode(encoded);
console.log(decoded); // 'Hello World'

🌍 Unicode and Character Encoding

This is the most critical difference. Native btoa() fails on characters outside the Latin-1 range. The libraries handle this differently.

base-64 does not automatically handle Unicode. You must encode the string to UTF-8 bytes first, or you risk data corruption or errors with special characters.

import base64 from 'base-64';

// ❌ This can fail or corrupt data with Unicode
// base64.encode('👋'); 

// ✅ Correct way: manually handle UTF-8 encoding first
const utf8Bytes = new TextEncoder().encode('👋');
// Convert bytes to binary string for base-64 lib
const binaryString = Array.from(utf8Bytes, b => String.fromCharCode(b)).join('');
const encoded = base64.encode(binaryString);

js-base64 handles Unicode strings automatically. It internally manages the UTF-8 conversion, making it safer for user-facing text.

import { encode, decode } from 'js-base64';

// ✅ Works out of the box with Unicode
const encoded = encode('👋 Hello');
console.log(encoded); // '8J+RkyBIZWxsbw=='

const decoded = decode(encoded);
console.log(decoded); // '👋 Hello'

🖥️ Environment Compatibility: Node.js vs Browser

Both packages aim for isomorphic usage, but their historical roots influence their design.

base-64 is heavily optimized for Node.js. It works well with Node's Buffer class, often serving as a polyfill or alternative to Buffer's base64 methods in specific contexts.

// base-64 in Node.js
import base64 from 'base-64';
import { Buffer } from 'buffer';

// Can interoperate with Buffer
const buf = Buffer.from('data');
const encoded = base64.encode(buf.toString('binary'));

js-base64 was built with the browser in mind first, ensuring it works in environments where Buffer is not available (like older browsers or strict CSP environments). It avoids Node-specific dependencies.

// js-base64 in Browser
import { encode } from 'js-base64';

// No Buffer dependency required
const token = encode(localStorage.getItem('user_data'));
// Works directly in Chrome, Firefox, Safari without polyfills

⚙️ URL Safety and Variants

Standard Base64 includes characters like + and / which are not URL-safe. Both libraries offer ways to handle this, but the API differs.

base-64 requires you to manually replace characters for URL safety, as it focuses on the raw RFC 4648 standard.

import base64 from 'base-64';

const raw = base64.encode('data+with/special');
// Manual replacement for URL safety
const urlSafe = raw.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');

js-base64 provides built-in methods specifically for URL-safe encoding (encodeURI or similar variants depending on version), reducing boilerplate.

import { encodeURL } from 'js-base64';

// Built-in URL safe encoding
const urlSafe = encodeURL('data+with/special');
// Automatically handles + to - and / to _

🛠️ API Surface and Extras

The scope of each library dictates how much else they offer.

base-64 is minimal. It exports encode, decode, and map. It does one thing and avoids extra features.

import base64 from 'base-64';

// Only core methods available
console.log(typeof base64.encode); // 'function'
console.log(typeof base64.decode); // 'function'
// No extra utilities included

js-base64 includes additional utilities for common web tasks, such as decoding to byte arrays or handling specific string formats.

import { decodeToUint8Array } from 'js-base64';

// Extra utilities for binary manipulation
const bytes = decodeToUint8Array(encodedString);
// Useful for file uploads or crypto operations

📊 Summary Table

Featurebase-64js-base64
Unicode Support❌ Manual UTF-8 handling required✅ Automatic handling
Primary FocusNode.js / Binary DataBrowser / Text Data
URL Safety❌ Manual replacement needed✅ Built-in methods
Bundle FootprintVery SmallSmall
API ComplexityMinimalModerate
Node Buffer✅ High Compatibility⚠️ Works but not primary focus

💡 The Big Picture

base-64 is like a surgical tool 🔪—precise, minimal, and perfect for backend systems where you control the input encoding. Use it when you are already working with Buffers or binary streams in Node.js and want zero magic.

js-base64 is like a Swiss Army Knife 🇨🇭—ready for the messy reality of web text. Use it when dealing with user input, international characters, or when you need code that runs identically in the browser and server without worrying about UTF-8 conversion bugs.

Final Thought: For most frontend architects, js-base64 is the safer default because Unicode bugs are subtle and costly. Reserve base-64 for specialized backend binary processing where performance and strict standard compliance are the only metrics that matter.

How to Choose: base-64 vs js-base64

  • base-64:

    Choose base-64 if you need a lightweight, strict RFC 4648 compliant library primarily for Node.js environments or when you want minimal abstraction over the encoding process. It is suitable for backend services, binary data processing, or scenarios where you are already handling UTF-8 encoding manually before passing data to the library. It is best when you prioritize a small footprint and don't need built-in Unicode string handling.

  • js-base64:

    Choose js-base64 if you are working in a browser environment or need to handle Unicode strings (like emojis or non-Latin scripts) directly without manual preprocessing. It is ideal for frontend applications, full-stack JavaScript projects where code sharing is key, or when you want a 'batteries-included' approach that automatically manages character encoding issues. It is the safer default for general web development involving user-generated text.

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.