Base64 in Node.js — Buffer, btoa, and Streaming Large Files
Node.js provides Buffer for Base64 encoding/decoding and native btoa/atob since v16. Learn how to encode strings, binary files, streams, and JSON payloads, handle URL-safe...
Use the tool
Base64 Encoder / Decoder
Encode and decode Base64 strings and files. Client-side, safe for sensitive data.
Node.js has two ways to handle Base64: the Buffer class (Node-native, works everywhere) and btoa/atob (Web API, added in Node 16). Use Buffer for binary data; btoa only handles strings.
Use the base64 decoder and encoder to encode and decode online.
Buffer — the Node.js way
// Encode string to Base64:
const encoded = Buffer.from('Hello World').toString('base64');
// 'SGVsbG8gV29ybGQ='
// Decode Base64 to string:
const decoded = Buffer.from('SGVsbG8gV29ybGQ=', 'base64').toString('utf8');
// 'Hello World'
// Encode binary data:
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
const encoded = Buffer.from(bytes).toString('base64');
// 'SGVsbG8='
// Encode JSON:
const payload = { user: 'alice', role: 'admin' };
const encodedJson = Buffer.from(JSON.stringify(payload)).toString('base64');
// Decode JSON:
const raw = Buffer.from(encodedJson, 'base64').toString('utf8');
const data = JSON.parse(raw);
btoa / atob (Node 16+)
// btoa: string to Base64
const encoded = btoa('Hello World');
// 'SGVsbG8gV29ybGQ='
// atob: Base64 to string
const decoded = atob('SGVsbG8gV29ybGQ=');
// 'Hello World'
// Limitation: btoa only handles Latin-1 (bytes 0-255)
// For Unicode strings, use Buffer:
try {
btoa('Hello 🌍'); // Throws: character out of range!
} catch {}
// Correct Unicode handling:
const encoded = Buffer.from('Hello 🌍').toString('base64');
const decoded = Buffer.from(encoded, 'base64').toString('utf8');
Encode a file to Base64
import { readFile } from 'fs/promises';
async function fileToBase64(filepath) {
const buffer = await readFile(filepath);
return buffer.toString('base64');
}
// Usage:
const b64 = await fileToBase64('./image.png');
const dataUrl = `data:image/png;base64,${b64}`;
Stream large files (avoid memory issues)
For files > 50MB, streaming is more memory-efficient:
import { createReadStream, createWriteStream } from 'fs';
import { Transform } from 'stream';
function base64EncodeStream(inputPath, outputPath) {
return new Promise((resolve, reject) => {
const input = createReadStream(inputPath);
const output = createWriteStream(outputPath);
// Transform each chunk to base64:
const base64Transform = new Transform({
transform(chunk, encoding, callback) {
callback(null, chunk.toString('base64'));
},
});
input
.pipe(base64Transform)
.pipe(output)
.on('finish', resolve)
.on('error', reject);
});
}
// Decode stream:
function base64DecodeStream(inputPath, outputPath) {
return new Promise((resolve, reject) => {
const input = createReadStream(inputPath);
const output = createWriteStream(outputPath);
// Decode each chunk: must handle chunk boundaries carefully
let leftover = '';
const decoder = new Transform({
transform(chunk, encoding, callback) {
const text = leftover + chunk.toString('ascii');
const remainder = text.length % 4;
leftover = text.slice(text.length - remainder);
const toProcess = text.slice(0, text.length - remainder);
if (toProcess) {
callback(null, Buffer.from(toProcess, 'base64'));
} else {
callback();
}
},
flush(callback) {
if (leftover) callback(null, Buffer.from(leftover, 'base64'));
else callback();
},
});
input.pipe(decoder).pipe(output).on('finish', resolve).on('error', reject);
});
}
URL-safe Base64 in Node.js
// Standard Base64: uses +, /, and = padding
// URL-safe Base64: uses -, _ and no padding
function toBase64Url(input) {
return Buffer.from(input)
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, ''); // Remove padding
}
function fromBase64Url(encoded) {
// Add padding back:
const padded = encoded + '==='.slice(0, (4 - encoded.length % 4) % 4);
return Buffer.from(padded.replace(/-/g, '+').replace(/_/g, '/'), 'base64');
}
// JWT uses URL-safe Base64 for all three parts
toBase64Url(JSON.stringify({ alg: 'HS256', typ: 'JWT' }))
// 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9'
HTTP Basic Auth
// Create Authorization header:
function basicAuthHeader(username, password) {
return `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}`;
}
// Parse Authorization header:
function parseBasicAuth(header) {
if (!header?.startsWith('Basic ')) return null;
const decoded = Buffer.from(header.slice(6), 'base64').toString('utf8');
const colon = decoded.indexOf(':');
if (colon < 0) return null;
return {
username: decoded.slice(0, colon),
password: decoded.slice(colon + 1),
};
}
Related tools
- Base64 Encoder/Decoder — encode and decode Base64 online
- Base64 Command Line — base64 CLI commands
- Base64 How It Works — algorithm explained
Related posts
- Base64: How It Actually Works Under the Hood — Base64 is everywhere — in JWTs, data URLs, email attachments. This is the byte-l…
- When You Should NOT Use Base64 Encoding — Base64 is the duct tape of the web — and like real duct tape, it's used in place…
- Base64 Encoding on the Command Line — Linux, macOS, and Windows — Encode and decode Base64 on the command line using base64, openssl, and PowerShe…
- Base64 Image Encoding — Embed Images in HTML, CSS, and JSON — Base64 image encoding converts image files to text strings for embedding in HTML…
Related tool
Base64 Encoder / Decoder
Encode and decode Base64 strings and files. Client-side, safe for sensitive data.
Written by Mian Ali Khalid. Part of the Dev Productivity pillar.