zlib.inflateSync()

Decompresses zlib-format (DEFLATE) data synchronously and returns the original bytes as a Buffer.

Signature
zlib.inflateSync(buffer[, options])
  • Added in Node.js v0.11.3

Parameters

ParameterTypeDescription
$bufferBuffer | TypedArray | DataView | ArrayBuffer | stringzlib-format compressed data to expand.
$optionsoptionalObjectzlib options: `windowBits`, `chunkSize`, `flush`, `finishFlush`, `dictionary`, `info` and `maxOutputLength`.

Return value

BufferA Buffer holding the decompressed data. With `options.info` set to `true`, an object `{ buffer, engine }` is returned instead.

Errors

Throws `Z_DATA_ERROR` when the input is not a valid zlib stream or the Adler-32 checksum fails, `Z_NEED_DICT` when a required dictionary was not supplied, and `ERR_BUFFER_TOO_LARGE` when the output exceeds `maxOutputLength`.

Changelog

  • PHP v5.11.0The `finishFlush` option is supported, allowing a truncated stream to be decoded up to the cut.
  • PHP v8.0.0The `dictionary` option can be a `Uint8Array`.
  • PHP v9.4.0The `dictionary` option can be an `ArrayBuffer`.
  • PHP v14.5.0, v12.19.0The `maxOutputLength` option is supported.

zlib.inflateSync() reverses zlib.deflateSync(). It expects the RFC 1950 framing — a two-byte header, the DEFLATE payload, and an Adler-32 checksum — verifies that checksum, and returns the original bytes.

When to reach for it

Use it for data your own code deflated, and for the many file formats that embed zlib streams: PNG IDAT chunks, PDF FlateDecode objects, ZIP entries (those are raw DEFLATE, so inflateRawSync()), and Git loose objects. Because the call blocks, keep it to data already held in memory; use a stream for anything large or arriving incrementally.

What trips people up

  • Format mismatch. Handing gzip data to inflateSync() throws Z_DATA_ERROR: incorrect header check. Gzip needs gunzipSync(); header-less DEFLATE needs inflateRawSync(). If you are sniffing, gzip starts with 1f 8b and zlib almost always with 78.
  • Missing dictionary. Data compressed with a dictionary fails with Z_NEED_DICT unless you pass the identical dictionary back in. The dictionary is not stored in the stream.
  • Unbounded expansion. Compressed input from a network or a user upload can expand by orders of magnitude. Set maxOutputLength so an oversized result throws ERR_BUFFER_TOO_LARGE instead of consuming memory.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Read back a blob that was stored with deflateSync in a database column
  • Decode a PDF FlateDecode object or a PNG IDAT chunk in a parser
  • Expand a WebSocket permessage-deflate frame captured for debugging
  • Assert in a test that a compression helper round-trips byte for byte

Frequently asked questions

How do I decompress deflate data in Node.js?

Call zlib.inflateSync(buffer) for zlib-framed data produced by deflateSync, or zlib.inflateRawSync(buffer) for header-less DEFLATE from deflateRawSync or a ZIP entry. Gzip data needs gunzipSync instead.

What causes Z_DATA_ERROR incorrect header check in inflateSync?

The buffer is not in zlib format — usually it is gzip data, which starts with 1f 8b and needs gunzipSync(), or raw DEFLATE with no header at all, which needs inflateRawSync().

What does Z_NEED_DICT mean?

The data was compressed with a preset dictionary that you have not supplied, so pass the identical bytes as options.dictionary to inflateSync. The dictionary is never embedded in the stream and must be shared out of band.

More examples

Pick the right decompressor from the header bytes

All three rows recover the same byte count from three different framings. The zlib check is the RFC 1950 rule: the first two bytes read as a big-endian integer must be divisible by 31. Raw DEFLATE has no header, so it is the fallback rather than something you can positively detect.

Example · javascript
const zlib = require('node:zlib');

function decompress(buf) {
  if (buf[0] === 0x1f && buf[1] === 0x8b) return zlib.gunzipSync(buf);
  // zlib header: low nibble 8 (deflate) and the two bytes form a multiple of 31.
  if ((buf[0] & 0x0f) === 0x08 && ((buf[0] << 8) + buf[1]) % 31 === 0) {
    return zlib.inflateSync(buf);
  }
  return zlib.inflateRawSync(buf); // assume bare DEFLATE
}

const text = 'detect the framing '.repeat(20);
for (const [name, buf] of [
  ['gzip', zlib.gzipSync(text)],
  ['zlib', zlib.deflateSync(text)],
  ['raw ', zlib.deflateRawSync(text)]
]) {
  console.log(name, '->', decompress(buf).length, 'bytes recovered');
}

Inflating dictionary-compressed data

The first call fails with Z_NEED_DICT because the stream references bytes that only exist in the dictionary. Note the failure mode is an explicit error, not silent corruption — but it also means the dictionary is part of your data format and must be versioned alongside the stored blobs.

Example · javascript
const zlib = require('node:zlib');

const dictionary = Buffer.from('status:active,role:member,region:');
const record = Buffer.from('status:active,role:member,region:eu-west-1');
const packed = zlib.deflateSync(record, { dictionary });

try {
  zlib.inflateSync(packed);
} catch (err) {
  console.log('without dictionary:', err.code); // Z_NEED_DICT
}

console.log('with dictionary:', zlib.inflateSync(packed, { dictionary }).toString());

Discussion

  • Be the first to comment on this lesson.