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.