JavaScript DecompressionStream API Explained
This article explores the native DecompressionStream
interface in JavaScript, explaining how it enables web applications to
unpack compressed network payloads without external libraries. You will
learn what the interface is, which compression algorithms it supports,
and how to pipe streamed responses directly into memory-efficient,
uncompressed data formats.
What is the DecompressionStream Interface?
The DecompressionStream interface is a built-in feature
of the Compression Streams API available in modern web browsers and
server-side runtimes like Node.js, Deno, and Bun. It functions as a
TransformStream that takes a stream of compressed binary
data as an input and outputs a stream of decompressed bytes.
Before this API, developers had to rely on heavy third-party
libraries (such as pako or fflate) or depend
solely on automatic browser decompression via HTTP headers like
Content-Encoding: gzip. DecompressionStream
provides native, performant decompression that can be executed directly
inside the JavaScript runtime.
The API supports three standard compression formats: *
'gzip': Decompresses data formatted with the GZIP file
format (RFC 1952). * 'deflate': Decompresses data using the
ZLIB data format with headers and checksum (RFC 1950). *
'deflate-raw': Decompresses raw DEFLATE byte streams
without headers or checksums (RFC 1951).
How JavaScript Unpacks Deflated Network Payloads
Browsers naturally unpack standard HTTP responses when the server
sets the Content-Encoding: gzip or
Content-Encoding: deflate headers. However, if your
application receives custom binary blobs, raw compressed WebSocket
frames, or fetches files where manual decompression is required, you
must unpack the data in JavaScript.
Because DecompressionStream is built on the Streams API,
it processes chunks of data sequentially as they arrive over the
network, drastically reducing peak memory usage.
1. Decompressing a Stream from a Fetch Request
To decompress a streamed network response, take the body
of a fetch() request (which is a
ReadableStream) and pipe it through a
DecompressionStream instance using
.pipeThrough().
async function fetchAndDecompressJson(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
// Create a decompression stream for deflate-compressed data
const decompressionStream = new DecompressionStream('deflate');
// Pipe the incoming network stream through the decompression stream
const decompressedStream = response.body.pipeThrough(decompressionStream);
// Wrap the resulting stream in a new Response to parse it as JSON or text
const decompressedResponse = new Response(decompressedStream);
const data = await decompressedResponse.json();
return data;
}2. Decompressing In-Memory Binary Buffers
If your payload arrives as an ArrayBuffer,
Uint8Array, or Blob (such as via a WebSocket
message or File API), you can convert the buffer into a
ReadableStream, decompress it, and read the output back
into memory.
async function decompressBuffer(compressedBuffer, format = 'deflate') {
// Convert buffer to a stream
const inputStream = new Response(compressedBuffer).body;
// Transform through DecompressionStream
const decompressedStream = inputStream.pipeThrough(new DecompressionStream(format));
// Collect the stream into an ArrayBuffer
const decompressedResponse = new Response(decompressedStream);
return await decompressedResponse.arrayBuffer();
}3. Reading Chunks Manually
For streaming architectures where you need to process data
chunk-by-chunk rather than waiting for the entire payload to complete,
consume the stream using a ReadableStreamDefaultReader:
async function processStreamInChunks(stream, format = 'gzip') {
const decompressedStream = stream.pipeThrough(new DecompressionStream(format));
const reader = decompressedStream.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
// 'value' is a Uint8Array containing an uncompressed chunk
console.log(`Received decompressed chunk of size: ${value.byteLength} bytes`);
}
}Summary
The DecompressionStream API provides a fast, standard,
and memory-efficient way to decode compressed network data in
JavaScript. By chaining this transform stream to incoming network
requests or buffers, you can unpack gzip,
deflate, and deflate-raw payloads natively
without increasing bundle size.