zlib.gzipSync()
Compresses a buffer or string into gzip format synchronously and returns the result as a Buffer.
zlib.gzipSync(buffer[, options])- Added in Node.js v0.11.3
Parameters
| Parameter | Type | Description |
|---|---|---|
$buffer | Buffer | TypedArray | DataView | ArrayBuffer | string | The data to compress. A string is encoded as UTF-8 before compression. |
$optionsoptional | Object | zlib options: `level`, `strategy`, `memLevel`, `windowBits`, `chunkSize`, `flush`, `finishFlush`, `dictionary`, `info` and `maxOutputLength`. |
Return value
BufferA Buffer containing the gzip-compressed form of the input. With `options.info` set to `true`, an object `{ buffer, engine }` is returned instead.
Errors
Throws a synchronous error if the input cannot be compressed, or `ERR_BUFFER_TOO_LARGE` when the result would exceed `maxOutputLength` (or `buffer.kMaxLength` by default).
Changelog
- PHP v5.11.0The `finishFlush` option is supported.
- 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, capping the size of the returned buffer.
zlib.gzipSync() runs a full gzip compression in one call and hands back a Buffer. The output carries the standard gzip wrapper: the two magic bytes 1f 8b, a small header, and a CRC32 plus length trailer. That is the format gzip on the command line writes, the format Content-Encoding: gzip means, and the format any HTTP client will accept.
When to reach for it
Use the sync form when the data is already fully in memory and small enough that a blocking call is acceptable — build scripts, CLI tools, seeding a cache, compressing a JSON body before writing it to a database column. Compression is pure CPU work, so a synchronous call blocks the event loop for its entire duration. On a server handling requests, prefer zlib.gzip() or zlib.createGzip() so other work can proceed.
What trips people up
- Gzip has roughly 20 bytes of fixed overhead. Compressing a very short string produces output larger than the input. Always check the length before deciding to store the compressed form.
levelranges from 0 (store, no compression) to 9. The default,Z_DEFAULT_COMPRESSION, is level 6. Level 9 costs noticeably more CPU for a few percent of size.- Already-compressed bytes — JPEG, PNG, MP4, a zip — will not shrink. Gzipping them wastes CPU and adds bytes.
Example
When to use it
- Compress a JSON API response body before caching it in Redis or a database column
- Produce a .gz artifact in a build script without pulling in a dependency
- Measure how well a payload compresses before choosing a storage format
- Pack a log batch in a CLI tool before writing it to disk
Frequently asked questions
How do I gzip a string in Node.js?
Pass the string straight to zlib.gzipSync() — it accepts a string and encodes it as UTF-8 before compressing, so zlib.gzipSync('hello world') returns a gzip Buffer. Use zlib.gunzipSync(buf).toString() to get the text back.
Why is my gzipped output larger than the input?
Gzip adds roughly 20 bytes of header and trailer, so inputs under about 100 bytes usually grow. Compare the two lengths and store the original when compression does not help.
Should I use gzipSync or gzip in a server?
Use the async zlib.gzip() or zlib.createGzip() in a server, because gzipSync blocks the event loop for the entire compression and stalls every other request. The sync form is fine in build scripts and CLIs.
More examples
Gzip overhead makes short inputs bigger
The first two rows show the gzip header and trailer costing more than the payload saves, so the output is larger than the input. Only the 500-byte repetitive string actually shrinks. This is why production code stores the compressed form only when it is genuinely smaller.
const zlib = require('node:zlib');
for (const text of ['ok', 'hello world', 'x'.repeat(500)]) {
const out = zlib.gzipSync(text);
console.log(
`${String(Buffer.byteLength(text)).padStart(4)} bytes in ->` +
` ${String(out.length).padStart(4)} bytes out` +
` ${out.length < Buffer.byteLength(text) ? '(smaller)' : '(BIGGER)'}`
);
}Write a .gz file from a build script
A precompressed asset written next to the original, the pattern nginx's gzip_static and most CDNs expect. Level 9 is worth the extra CPU here because the file is compressed once at build time and served many times. The printed ratio is the number to compare against a Brotli build of the same bundle.
const zlib = require('node:zlib');
const fs = require('node:fs');
const bundle = fs.readFileSync('dist/app.js');
const gz = zlib.gzipSync(bundle, { level: 9 });
fs.writeFileSync('dist/app.js.gz', gz);
const ratio = ((1 - gz.length / bundle.length) * 100).toFixed(1);
console.log(`app.js ${bundle.length} B -> ${gz.length} B (${ratio}% saved)`);Guard against a decompression bomb with maxOutputLength
Five megabytes of zeroes compress to a few kilobytes. Decompressing untrusted input without a cap lets a small upload allocate hundreds of megabytes. maxOutputLength turns that into a catchable ERR_BUFFER_TOO_LARGE instead of memory pressure.
const zlib = require('node:zlib');
// A tiny payload that expands enormously.
const bomb = zlib.gzipSync(Buffer.alloc(5 * 1024 * 1024, 0));
console.log('compressed bytes:', bomb.length);
try {
zlib.gunzipSync(bomb, { maxOutputLength: 64 * 1024 });
} catch (err) {
console.log('rejected:', err.code); // ERR_BUFFER_TOO_LARGE
}
Discussion