Skip to content

Node.js Buffers — Complete Guide to Binary Data Handling

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Node.js Buffers. We cover key concepts, practical examples, and best practices to help you master this topic.

Node.js Buffer provides a way to handle raw binary data in memory, essential for file I/O, network protocols, cryptography, and binary data manipulation.

What You'll Learn

By the end of this tutorial, you'll create and manipulate Buffer objects, convert between encodings, slice and copy binary data, and use buffers for practical tasks.

Why Buffers Matter

JavaScript's native typed arrays weren't designed for Node.js I/O. Buffer extends Uint8Array with Node-specific methods for encoding conversion and optimized memory allocation, making it essential for handling binary files and network data.

Real-World Use

An image processing service reads raw image bytes into a Buffer, inspects file headers to validate format, converts between encodings, and writes the processed result to disk.

Buffers Learning Path

flowchart LR
  A[Streams] --> B[Buffers]
  B --> C[Events]
  C --> D[Child Process]
  D --> E[Express.js]
  A --> F{You Are Here}
  style F fill:#f90,color:#fff

Creating Buffers

import { Buffer } from "node:buffer";

// From string
const buf1 = Buffer.from("Hello Node.js", "utf8");
console.log(buf1);  // <Buffer 48 65 6c 6c 6f 20 4e 6f 64 65 2e 6a 73>

// Allocate (zero-filled)
const buf2 = Buffer.alloc(10);  // 10 zero-filled bytes
console.log(buf2);  // <Buffer 00 00 00 00 00 00 00 00 00 00>

// Allocate (uninitialized - faster but may contain old data)
const buf3 = Buffer.allocUnsafe(10);
console.log(buf3);  // <Buffer ... old data>

Always use Buffer.alloc for new buffers. Buffer.allocUnsafe is faster but may expose sensitive data if not overwritten.

Reading and Writing Buffers

const buf = Buffer.alloc(8);
buf.writeUInt16BE(0x1234, 0);  // Write 16-bit value at byte 0
buf.writeUInt32LE(0xDEADBEEF, 2);  // Write 32-bit value at byte 2

console.log(buf);  // <Buffer 12 34 ef be ad de 00 00>
console.log(buf.readUInt16BE(0));  // 4660 (0x1234)
console.log(buf.readUInt32LE(2));  // 3735928559 (0xDEADBEEF)

Encoding Conversion

const buf = Buffer.from("Hello", "utf8");
console.log(buf.toString("hex"));         // 48656c6c6f
console.log(buf.toString("base64"));      // SGVsbG8=
console.log(buf.toString("ascii"));       // Hello
console.log(buf.toString("utf8"));        // Hello

Buffer Slicing

Slice creates a new view (not a copy) into the original buffer.

const original = Buffer.from("Hello World");
const slice = original.subarray(0, 5);
console.log(slice.toString());  // Hello

// Modifying the slice affects the original
slice[0] = 104;  // 'h'
console.log(original.toString());  // hello World

Buffer Comparison and Concatenation

const buf1 = Buffer.from("ABC");
const buf2 = Buffer.from("ABC");
const buf3 = Buffer.from("ABD");

console.log(buf1.equals(buf2));  // true
console.log(buf1.equals(buf3));  // false

console.log(Buffer.compare(buf1, buf3));  // -1 (buf1 comes first)
const combined = Buffer.concat([buf1, buf3]);
console.log(combined.toString());  // ABCABD

Buffer Length vs String Length

const str = "Hello";
const emoji = "🎉";
console.log(str.length);         // 5
console.log(Buffer.from(str).length);  // 5
console.log(emoji.length);       // 2 (JS string length)
console.log(Buffer.from(emoji).length);  // 4 (UTF-8 byte length)

UTF-8 characters like emoji take 4 bytes. Always use Buffer.from(str).length for accurate byte counts.

Common Mistakes

1. Using new Buffer() (Deprecated)

new Buffer(10) may allocate uninitialized memory containing sensitive data. Use Buffer.alloc() or Buffer.from().

2. Confusing String Length and Buffer Length

String .length counts UTF-16 code units. Buffer .length counts bytes. They differ for multi-byte characters.

3. Assuming toString Without Encoding

buf.toString() defaults to utf8. Binary data may produce garbled output. Always specify the encoding.

4. Modifying Shared Buffer Slices

subarray shares memory with the parent. Copy with Buffer.from(slice) if you need independent data.

5. Off-by-One Errors in read/write Position

Buffer write operations at a wrong offset corrupt data. Validate offsets against buffer length.

Practice Questions

1. What is the difference between Buffer.alloc and Buffer.allocUnsafe?

Buffer.alloc fills memory with zeros (safe). Buffer.allocUnsafe is faster but may contain old data (unsafe for sensitive information).

2. How do you convert a Buffer to a base64 string?

buf.toString("base64")

3. Does Buffer.subarray create a new copy?

No. It creates a new view that shares the same underlying memory. Modifications affect the original buffer.

4. What is the byte length of the string "cafe"?

4 bytes in UTF-8 (all ASCII characters are 1 byte each).

5. Challenge: Write a function that reads a file header (first 4 bytes) and returns whether it's a PNG file (starts with 0x89504E47).

import fs from "node:fs";
import { Buffer } from "node:buffer";
function isPNG(filePath) {
  const fd = fs.openSync(filePath, "r");
  const header = Buffer.alloc(4);
  fs.readSync(fd, header, 0, 4, 0);
  fs.closeSync(fd);
  return header.readUInt32BE(0) === 0x89504E47;
}
console.log(isPNG("image.png"));  // true or false

FAQ

What is the difference between Buffer and JavaScript Array?

Buffer stores raw bytes with fixed size. Arrays store any JavaScript values and are dynamically sized.

When is Buffer.allocUnsafe acceptable?

When you immediately fill the buffer with data (e.g., from a file read or network socket).

How do I convert a Buffer to a number?

Use readUInt8, readUInt16BE, readInt32LE, and similar methods depending on size and byte order.

What is maximum Buffer size?

Depends on system memory. On 64-bit systems, the maximum is 2GB (v8's array buffer size limit).

Is Buffer available in browsers?

No. Buffer is a Node.js API. Browsers use Uint8Array for binary data.

Mini Project: File Type Detector

Create a utility that reads the magic bytes of a file and detects its type.

import fs from "node:fs";
import { Buffer } from "node:buffer";
const MAGIC_NUMBERS = {
  "89504E47": "PNG",
  "FFD8FF": "JPEG",
  "25504446": "PDF",
  "504B0304": "ZIP/DOCX"
};
function detectFileType(filePath) {
  const fd = fs.openSync(filePath, "r");
  const header = Buffer.alloc(4);
  fs.readSync(fd, header, 0, 4, 0);
  fs.closeSync(fd);
  const hex = header.toString("hex").toUpperCase();
  for (const [magic, type] of Object.entries(MAGIC_NUMBERS)) {
    if (hex.startsWith(magic)) return type;
  }
  return "Unknown";
}
console.log(detectFileType("document.pdf"));  // PDF

What's Next

Node.js Events Node.js Error Handling Express.js

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro