adm-zip vs extract-zip vs node-unzip-2 vs node-zip vs unzipper vs yauzl
Node.js Libraries for ZIP File Handling
adm-zipextract-zipnode-unzip-2node-zipunzipperyauzlSimilar Packages:

Node.js Libraries for ZIP File Handling

adm-zip, extract-zip, node-unzip-2, node-zip, unzipper, and yauzl are Node.js libraries for working with ZIP archive files. They provide varying levels of support for reading, writing, extracting, and streaming ZIP content. Some focus exclusively on extraction, others support full archive manipulation, and a few are designed for in-memory operations only. These tools are commonly used in backend services for handling file uploads, generating downloadable bundles, or processing compressed data feeds.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
adm-zip02,162122 kB144a month agoMIT
extract-zip0398-556 years agoBSD-2-Clause
node-unzip-2044-217 years agoMIT
node-zip0217-2011 years ago-
unzipper047356.6 kB862 years agoMIT
yauzl080297.7 kB15a month agoMIT

Handling ZIP Files in Node.js: A Deep Dive into Popular Libraries

When you need to work with ZIP archives in a Node.js environment β€” whether extracting user-uploaded files, packaging build artifacts, or processing compressed data streams β€” choosing the right library matters. The ecosystem offers several options, each with distinct trade-offs in terms of streaming support, memory usage, API design, and maintenance status. Let’s examine adm-zip, extract-zip, node-unzip-2, node-zip, unzipper, and yauzl through the lens of real-world engineering constraints.

πŸ“¦ Core Capabilities: What Each Library Actually Does

adm-zip provides full read/write support for ZIP files using synchronous and asynchronous APIs. It loads entire archives into memory, which simplifies usage but limits scalability.

// adm-zip: extract all entries to disk
const AdmZip = require('adm-zip');
const zip = new AdmZip('./archive.zip');
zip.extractAllTo('./output/');

// adm-zip: create a new ZIP
const zip2 = new AdmZip();
zip2.addLocalFile('./file.txt');
zip2.writeZip('./new.zip');

extract-zip is purpose-built for one task: extracting ZIP files to disk. It wraps yauzl under the hood and only supports extraction (no creation or in-memory reading).

// extract-zip: simple extraction
const extract = require('extract-zip');
await extract('./archive.zip', { dir: './output/' });

node-unzip-2 is a fork of the deprecated node-unzip package. It offers streaming extraction via Node.js streams but hasn’t seen active maintenance in recent years.

// node-unzip-2: stream-based extraction
const fs = require('fs');
const unzip = require('node-unzip-2');

fs.createReadStream('./archive.zip')
  .pipe(unzip.Extract({ path: './output/' }))
  .on('close', () => console.log('Done'));

node-zip is a wrapper around JSZip, designed primarily for in-browser use but usable in Node.js via buffer. It doesn't interact with the filesystem directly and requires manual buffer handling.

// node-zip: in-memory only
const Zip = require('node-zip');
const zip = new Zip();
zip.file('hello.txt', 'Hello World!');
const data = zip.generate({ type: 'nodebuffer' }); // Buffer

unzipper supports both streaming and buffered operations for reading ZIP files. It can extract to disk or parse entries in memory, and it handles large files efficiently by avoiding full archive loading.

// unzipper: streaming extraction
const fs = require('fs');
const unzipper = require('unzipper');

fs.createReadStream('./archive.zip')
  .pipe(unzipper.Extract({ path: './output/' }))
  .on('close', () => console.log('Extracted'));

// unzipper: parse entries without extraction
fs.createReadStream('./archive.zip')
  .pipe(unzipper.Parse())
  .on('entry', (entry) => {
    console.log(entry.path);
    entry.autodrain(); // discard content
  });

yauzl ("yet another unzip library") is a low-level, streaming-first library focused exclusively on reading ZIP files. It does not support writing ZIPs or extracting to disk directly β€” you must handle file system operations yourself.

// yauzl: manual entry processing
const yauzl = require('yauzl');

yauzl.open('./archive.zip', (err, zipfile) => {
  zipfile.on('entry', (entry) => {
    zipfile.openReadStream(entry, (err, readStream) => {
      readStream.on('end', () => zipfile.readEntry());
      readStream.pipe(process.stdout); // or write to file
    });
    if (!zipfile.isOpen) zipfile.readEntry();
  });
  zipfile.readEntry();
});

πŸ’Ύ Memory vs Streaming: The Critical Trade-off

If your application processes small ZIP files (<50MB), libraries like adm-zip or node-zip are convenient because they abstract away streaming complexity. However, they load the entire archive into memory, which becomes problematic with larger files.

For server applications handling user uploads or large datasets, streaming is essential. unzipper and yauzl excel here:

  • yauzl gives you fine-grained control but requires more boilerplate.
  • unzipper provides higher-level abstractions (like Extract) while still being memory-efficient.

extract-zip inherits yauzl’s streaming behavior but hides the complexity behind a promise-based API β€” ideal when you just need to dump contents to disk.

node-unzip-2 also streams, but its outdated dependencies and lack of recent updates raise reliability concerns for production use.

πŸ”§ Write Support: Do You Need to Create ZIPs?

Only three packages support creating ZIP archives:

  • adm-zip: Full read/write with filesystem integration.
  • node-zip: In-memory only (via JSZip), no direct file I/O.
  • unzipper: Read-only β€” despite the name, it cannot create ZIPs.

If you need to generate ZIP files from buffers or streams, adm-zip is the most straightforward choice in Node.js. For browser-compatible generation that also works in Node, node-zip (JSZip) is viable but requires manual file writing.

⚠️ Maintenance and Deprecation Status

Based on official npm and GitHub sources:

  • node-unzip-2 is a community fork of the abandoned node-unzip. While functional, it lacks active maintenance and modern security updates. Avoid in new projects.
  • node-zip is a thin wrapper over JSZip, which is actively maintained, but the wrapper itself sees infrequent updates. Use only if you specifically need JSZip compatibility.
  • adm-zip, extract-zip, unzipper, and yauzl are all actively maintained as of 2024, with recent releases addressing security and compatibility.

πŸ› οΈ Real-World Selection Guide

Scenario 1: Extract user-uploaded ZIPs to disk

  • βœ… Best: extract-zip β€” simple, secure, streaming, and purpose-built.
  • Alternative: unzipper if you need more control over entry filtering.
// Preferred: extract-zip
await extract('./upload.zip', { dir: './uploads/extracted' });

Scenario 2: Process large ZIPs without exhausting memory

  • βœ… Best: yauzl or unzipper.
  • Choose yauzl for maximum control; unzipper for simpler syntax.
// With unzipper
fs.createReadStream('large.zip')
  .pipe(unzipper.Parse())
  .on('entry', entry => {
    if (entry.path.endsWith('.json')) {
      entry.pipe(fs.createWriteStream(`./data/${entry.path}`));
    } else {
      entry.autodrain();
    }
  });

Scenario 3: Generate ZIP files from application data

  • βœ… Best: adm-zip β€” native filesystem support and intuitive API.
  • Avoid node-zip unless you’re already using JSZip in the browser.
// With adm-zip
const zip = new AdmZip();
zip.addFile('config.json', Buffer.from(JSON.stringify(config)));
zip.writeZip('./bundle.zip');

Scenario 4: Parse ZIP metadata without extraction

  • βœ… Best: yauzl β€” lightweight and fast for listing entries.
// With yauzl
yauzl.open('archive.zip', (err, zipfile) => {
  zipfile.on('entry', entry => console.log(entry.fileName));
  zipfile.readEntry();
});

πŸ“Š Summary Table

PackageRead ZIPWrite ZIPStream SupportExtract to DiskIn-Memory OnlyActively Maintained
adm-zipβœ…βœ…βŒβœ…βŒβœ…
extract-zipβœ…βŒβœ… (via yauzl)βœ…βŒβœ…
node-unzip-2βœ…βŒβœ…βœ…βŒβŒ (avoid)
node-zipβœ…βœ…βŒβŒβœ…βš οΈ (wrapper only)
unzipperβœ…βŒβœ…βœ…βœ…βœ…
yauzlβœ…βŒβœ…βŒ (manual)βœ…βœ…

πŸ’‘ Final Recommendation

  • For extraction only: Use extract-zip β€” it’s safe, simple, and efficient.
  • For large-file processing: Choose unzipper for balance or yauzl for precision.
  • For ZIP creation: Stick with adm-zip unless you have cross-environment (browser + Node) requirements.
  • Avoid node-unzip-2 in new codebases due to maintenance risks.

Remember: ZIP handling often involves untrusted input. Always validate file paths during extraction to prevent directory traversal attacks β€” libraries like extract-zip and unzipper include built-in protections, but lower-level tools like yauzl leave this to you.

How to Choose: adm-zip vs extract-zip vs node-unzip-2 vs node-zip vs unzipper vs yauzl

  • adm-zip:

    Choose adm-zip when you need a simple, all-in-one solution for both reading and writing ZIP files with direct filesystem integration. It’s ideal for small to medium archives where loading the entire file into memory is acceptable, such as generating report bundles or processing trusted internal files. Avoid it for large files or untrusted inputs due to its synchronous defaults and memory usage.

  • extract-zip:

    Choose extract-zip when your only requirement is to safely extract ZIP files to disk. It’s built on yauzl, supports streaming, includes path sanitization to prevent directory traversal, and offers a clean promise-based API. This is the go-to choice for handling user-uploaded ZIPs in web applications where security and simplicity matter most.

  • node-unzip-2:

    Avoid node-unzip-2 in new projects. It’s a community-maintained fork of the deprecated node-unzip and lacks active development or security updates. While it supports streaming extraction, modern alternatives like unzipper or extract-zip offer better reliability, features, and maintenance. Only consider it if you’re maintaining legacy code that already depends on it.

  • node-zip:

    Choose node-zip only if you need JSZip compatibility between browser and Node.js environments. It operates entirely in memory and doesn’t interact with the filesystem directly, so you’ll need to handle file reads/writes manually. It’s suitable for client-side-like ZIP generation in Node scripts but less practical for typical server-side file processing tasks.

  • unzipper:

    Choose unzipper when you need flexible, streaming-based ZIP parsing with support for both disk extraction and in-memory entry processing. It handles large files efficiently, provides high-level utilities like Extract, and allows fine-grained control via Parse. Ideal for server applications that process untrusted or large archives without excessive memory consumption.

  • yauzl:

    Choose yauzl when you require a minimal, low-level, streaming-first library for reading ZIP files. It gives you full control over entry processing but requires manual implementation of file writing and security checks like path validation. Best suited for performance-critical or specialized use cases where you need to inspect or filter archive contents without full extraction.

README for adm-zip

ADM-ZIP for NodeJS

ADM-ZIP is a pure JavaScript implementation for zip data compression for NodeJS.

Build Status

Installation

With npm do:

$ npm install adm-zip

Electron file system support described below.

What is it good for?

The library allows you to:

  • decompress zip files directly to disk or in memory buffers
  • compress files and store them to disk in .zip format or in compressed buffers
  • update content of/add new/delete files from an existing .zip

Dependencies

There are no other nodeJS libraries that ADM-ZIP is dependent of

Examples

Basic usage

var AdmZip = require("adm-zip");

// reading archives
var zip = new AdmZip("./my_file.zip");
var password = "1234567890";
var zipEntries = zip.getEntries(); // an array of ZipEntry records - add password parameter if entries are password protected

zipEntries.forEach(function (zipEntry) {
    console.log(zipEntry.toString()); // outputs zip entries information
    if (zipEntry.entryName == "my_file.txt") {
        console.log(zipEntry.getData().toString("utf8"));
    }
});
// outputs the content of some_folder/my_file.txt
console.log(zip.readAsText("some_folder/my_file.txt"));
// extracts the specified file to the specified location
zip.extractEntryTo(/*entry name*/ "some_folder/my_file.txt", /*target path*/ "/home/me/tempfolder", /*maintainEntryPath*/ false, /*overwrite*/ true);
// extracts everything
zip.extractAllTo(/*target path*/ "/home/me/zipcontent/", /*overwrite*/ true);

// creating archives
var zip = new AdmZip();

// add file directly
var content = "inner content of the file";
zip.addFile("test.txt", Buffer.from(content, "utf8"), "entry comment goes here");
// add local file
zip.addLocalFile("/home/me/some_picture.png");
// get everything as a buffer
var willSendthis = zip.toBuffer();
// or write everything to disk
zip.writeZip(/*target file name*/ "/home/me/files.zip");

// ... more examples in the wiki

For more detailed information please check out the wiki.

Electron original-fs

ADM-ZIP has supported electron original-fs for years without any user interractions but it causes problem with bundlers like rollup etc. For continuing support original-fs or any other custom file system module. There is possible specify your module by fs option in ADM-ZIP constructor.

Example:

const AdmZip = require("adm-zip");
const OriginalFs = require("original-fs");

// reading archives
const zip = new AdmZip("./my_file.zip", { fs: OriginalFs });
.
.
.