Base64 in Node.js

Node.js Buffer is the idiomatic way to handle Base64. It works with strings, binary data, and files out of the box — no extra packages needed. Node.js 16+ also added global btoa() and atob() for browser compatibility.

Encoding and Decoding Strings

// Encode a string to Base64
const encoded = Buffer.from('Hello, world!').toString('base64');
console.log(encoded); // "SGVsbG8sIHdvcmxkIQ=="

// Decode Base64 back to a string
const decoded = Buffer.from('SGVsbG8sIHdvcmxkIQ==', 'base64').toString('utf8');
console.log(decoded); // "Hello, world!"

No Unicode issues: Unlike browser btoa(), Buffer.from(str) defaults to UTF-8, so emoji and non-ASCII characters work correctly without extra steps.

URL-Safe Base64 (Node 16+)

// base64url encoding — no +, /, or = characters
const encoded = Buffer.from('Hello, world!').toString('base64url');
console.log(encoded); // "SGVsbG8sIHdvcmxkIQ"

// Decode base64url
const decoded = Buffer.from(encoded, 'base64url').toString('utf8');
console.log(decoded); // "Hello, world!"

For older Node versions, implement it manually:

function toBase64URL(str) {
  return Buffer.from(str).toString('base64')
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}
function fromBase64URL(b64url) {
  let b64 = b64url.replace(/-/g, '+').replace(/_/g, '/');
  while (b64.length % 4) b64 += '=';
  return Buffer.from(b64, 'base64').toString('utf8');
}

Encoding Files

const fs = require('fs');

// Encode a file to Base64 string
const fileBuffer = fs.readFileSync('image.png');
const encoded = fileBuffer.toString('base64');
console.log(`Encoded size: ${encoded.length} chars`);

// Decode Base64 back to a file
const decoded = Buffer.from(encoded, 'base64');
fs.writeFileSync('output.png', decoded);

Streaming Large Files

const fs = require('fs');
const { pipeline } = require('stream/promises');

// Encode large file using streams
async function encodeFileStream(input, output) {
  const readable = fs.createReadStream(input);
  const writeable = fs.createWriteStream(output, { encoding: 'ascii' });

  let buffer = Buffer.alloc(0);
  for await (const chunk of readable) {
    buffer = Buffer.concat([buffer, chunk]);
    // Process in 3-byte aligned chunks
    const aligned = Math.floor(buffer.length / 3) * 3;
    if (aligned > 0) {
      writeable.write(buffer.slice(0, aligned).toString('base64'));
      buffer = buffer.slice(aligned);
    }
  }
  // Flush remaining bytes
  if (buffer.length > 0) writeable.write(buffer.toString('base64'));
  writeable.end();
}

HTTP Responses — Sending Binary as Base64

const http = require('http');
const fs = require('fs');

const server = http.createServer((req, res) => {
  if (req.url === '/image-base64') {
    const imageBuffer = fs.readFileSync('logo.png');
    const base64 = imageBuffer.toString('base64');
    const dataUri = `data:image/png;base64,${base64}`;

    res.setHeader('Content-Type', 'application/json');
    res.end(JSON.stringify({ image: base64, dataUri }));
  }
});

server.listen(3000);

btoa() and atob() in Node.js 16+

// Available globally in Node 16+ for browser compatibility
const encoded = btoa('Hello');      // "SGVsbG8="
const decoded = atob('SGVsbG8=');   // "Hello"

// Note: btoa/atob still have the same Unicode limitation as browsers.
// For Unicode strings, Buffer is the better choice in Node.js.

Working with Streams and Base64 Transform

const { Transform } = require('stream');

class Base64Encode extends Transform {
  constructor() {
    super();
    this._buffer = Buffer.alloc(0);
  }
  _transform(chunk, enc, cb) {
    this._buffer = Buffer.concat([this._buffer, chunk]);
    const aligned = Math.floor(this._buffer.length / 3) * 3;
    if (aligned > 0) {
      this.push(this._buffer.slice(0, aligned).toString('base64'));
      this._buffer = this._buffer.slice(aligned);
    }
    cb();
  }
  _flush(cb) {
    if (this._buffer.length) this.push(this._buffer.toString('base64'));
    cb();
  }
}

// Usage
fs.createReadStream('input.bin')
  .pipe(new Base64Encode())
  .pipe(fs.createWriteStream('output.b64'));

Inspect your Node.js Base64 output

Paste the encoded string from your Node.js script into base64.dev to decode and verify it instantly.

Open base64.dev →