Buffers
Represent and manipulate raw binary data in Node.js with the Buffer class
Overview
Key Points
- β’Buffer is a fixed-size array of bytes, allocated outside the V8 heap
- β’Buffer.from(string, encoding) converts a string to bytes; buf.toString(encoding) reverses it
- β’Buffer.alloc(size) creates a zero-filled buffer; Buffer.allocUnsafe(size) is faster but uninitialized
- β’Buffer.concat([buf1, buf2]) combines multiple buffers into one
- β’Common encodings: "utf8" (default), "hex", "base64", "latin1" ("binary")
- β’Buffer is a subclass of Uint8Array β you can use array indexing and typed array methods on it
Examples
Creating Buffers from strings and converting back
// From a UTF-8 string
const buf1 = Buffer.from('Hello, Node.js!', 'utf8');
console.log(buf1); // <Buffer 48 65 6c 6c 6f 2c ...>
console.log(buf1.length); // 15 (bytes, not characters)
console.log(buf1.toString()); // Hello, Node.js!
// Encoding conversions
console.log(buf1.toString('hex')); // 48656c6c6f2c204e6f64652e6a7321
console.log(buf1.toString('base64')); // SGVsbG8sIE5vZGUuanMh
// Decode hex back to string
const buf2 = Buffer.from('48656c6c6f', 'hex');
console.log(buf2.toString('utf8')); // HelloAllocating and writing to Buffers
// alloc: zero-filled, safe
const safe = Buffer.alloc(4);
console.log(safe); // <Buffer 00 00 00 00>
// Write individual bytes by index
safe[0] = 0xFF;
safe[1] = 0x00;
safe[2] = 0x7E;
safe[3] = 0x01;
console.log(safe); // <Buffer ff 00 7e 01>
// allocUnsafe: faster but may contain garbage data β always fill before reading
const unsafe = Buffer.allocUnsafe(10);
unsafe.fill(0); // manually zero it out
console.log(unsafe);Never expose data from Buffer.allocUnsafe to users without filling it first β it can contain previously freed memory.
Concatenating Buffers from a stream of chunks
// Simulating collecting chunks from a stream
const chunks = [
Buffer.from('Hello'),
Buffer.from(', '),
Buffer.from('World'),
Buffer.from('!'),
];
const combined = Buffer.concat(chunks);
console.log(combined.toString('utf8')); // Hello, World!
console.log(combined.length); // 13Never concatenate buffers with the + operator β it converts to strings. Always use Buffer.concat().
Using Buffers for base64 encoding/decoding (common for HTTP and data URIs)
// Encode binary data as base64 for HTTP transmission
function toBase64(data) {
return Buffer.from(data, 'utf8').toString('base64');
}
function fromBase64(encoded) {
return Buffer.from(encoded, 'base64').toString('utf8');
}
const original = 'secret data: Β£100';
const encoded = toBase64(original);
const decoded = fromBase64(encoded);
console.log('Encoded:', encoded); // c2VjcmV0IGRhdGE6IMKjMTAw
console.log('Decoded:', decoded); // secret data: Β£100
console.log('Match:', original === decoded); // trueCommon Mistakes
- Using Buffer.allocUnsafe() without filling with .fill(0) β the memory may contain sensitive data from previous allocations
- Concatenating Buffers with the + operator (buf1 + buf2 converts them to strings first, corrupting binary data)
- Assuming buf.length equals character count β for multi-byte Unicode, byte count > character count
- Using the deprecated `new Buffer()` constructor β it was removed for security; use Buffer.from(), Buffer.alloc(), or Buffer.allocUnsafe()
Note
When accumulating chunks from a stream, push each chunk into an array and call Buffer.concat() once at the end β this is far more efficient than repeated string concatenation or repeated Buffer.concat() calls in a loop.
Exercises
Write Node.js code in your local terminal. Use the editor below to follow along, then mark each exercise as done once it works.
Completed: 0 / 6 exercises
Knowledge Check
Question 1 of 4