adm-zip vs archiver vs jszip vs yazl vs zip-lib vs zip-stream
JavaScript ZIP Libraries for File Compression and Archiving
adm-ziparchiverjszipyazlzip-libzip-streamSimilar Packages:

JavaScript ZIP Libraries for File Compression and Archiving

adm-zip, archiver, jszip, yazl, zip-lib, and zip-stream are JavaScript libraries for creating, reading, and manipulating ZIP archives. They differ significantly in their architecture: some are designed for in-browser use, others for Node.js; some support streaming for memory efficiency, while others load entire archives into memory; and not all support both creation and extraction. These differences make each library better suited for specific scenarios, such as serving dynamic ZIPs from a server, processing large files without memory spikes, or enabling ZIP manipulation directly in a web application.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
adm-zip02,161121 kB1482 years agoMIT
archiver02,95343.1 kB1562 years agoMIT
jszip010,330762 kB410-(MIT OR GPL-3.0-or-later)
yazl037558.7 kB19a year agoMIT
zip-lib04163.6 kB13 days agoMIT
zip-stream01669.33 kB27a year agoMIT

JavaScript ZIP Libraries Compared: adm-zip, archiver, jszip, yazl, zip-lib, and zip-stream

When you need to create or extract ZIP files in a JavaScript environment β€” whether in Node.js or the browser β€” choosing the right library can make a big difference in performance, memory use, and code clarity. The six packages under review (adm-zip, archiver, jszip, yazl, zip-lib, and zip-stream) all handle ZIP operations but with very different design goals, APIs, and trade-offs. Let’s break down what each does well and where it falls short.

πŸ“¦ Core Capabilities: Creation vs Extraction vs Streaming

adm-zip: Full-featured ZIP reader/writer for Node.js

adm-zip supports both reading and writing ZIP files, including extracting entries to disk and adding files from buffers or paths. It loads the entire archive into memory, which makes it simple but unsuitable for large files.

// Read and extract
const zip = new AdmZip("./archive.zip");
zip.extractAllTo("./output/");

// Add file and write
zip.addFile("new.txt", Buffer.from("Hello"));
zip.writeZip("./updated.zip");

archiver: High-level streaming ZIP (and TAR) creator

archiver is built on streams and excels at creating ZIPs incrementally without loading everything into memory. It supports compression, directory recursion, and piping to any writable stream (like HTTP responses). However, it cannot read or extract ZIPs.

const archive = archiver('zip');
const output = fs.createWriteStream('archive.zip');

archive.pipe(output);
archive.file('file.txt', { name: 'file.txt' });
archive.finalize();

jszip: Browser-first ZIP manipulation with limited Node support

jszip works well in browsers and can load, modify, and generate ZIPs from memory. In Node.js, it requires additional setup (e.g., using fs.promises to read files as buffers). It doesn’t support streaming and holds everything in RAM.

// Load and add
const zip = await JSZip.loadAsync(fs.readFileSync('input.zip'));
zip.file('new.txt', 'Hello');
const buffer = await zip.generateAsync({ type: 'nodebuffer' });
fs.writeFileSync('output.zip', buffer);

yazl: Low-level, streaming ZIP generator only

yazl (Yet Another Zip Library) is a minimal, streaming-only ZIP writer. It gives fine control over entry metadata and compression but provides no extraction capability. Ideal when you need predictable memory usage and full control over the ZIP structure.

const zipfile = new yazl.ZipFile();
zipfile.addBuffer(Buffer.from('Hello'), 'hello.txt');
zipfile.end();
zipfile.outputStream.pipe(fs.createWriteStream('out.zip'));

zip-lib: Simple promise-based ZIP utility (Node.js only)

zip-lib wraps lower-level libraries to offer a clean promise API for basic tasks like compressing directories or decompressing archives. It’s easy to use but lacks advanced features like streaming or fine-grained entry control.

// Compress a folder
await zipLib.compress('./folder', './archive.zip');

// Extract
await zipLib.extract('./archive.zip', './output');

zip-stream: Barebones streaming ZIP core (used by archiver)

zip-stream is the underlying engine that powers archiver’s ZIP functionality. It’s a transform stream that converts input entries into ZIP format. You typically won’t use it directly unless you’re building your own archiving tool.

const zip = new ZipStream();
const output = fs.createWriteStream('out.zip');

zip.pipe(output);
zip.entry('Hello', { name: 'hello.txt' }, () => {
  zip.finish();
});

βš–οΈ Memory and Performance Trade-offs

  • Streaming vs In-Memory: archiver, yazl, and zip-stream use streams and scale to large datasets. adm-zip, jszip, and zip-lib load everything into memory β€” avoid them for files >100MB.
  • Extraction Support: Only adm-zip, jszip, and zip-lib can extract ZIPs. If you need to read archives, rule out archiver, yazl, and zip-stream.
  • Browser Compatibility: Only jszip is designed for the browser. The others are Node.js-only (they rely on fs, stream, or native modules).

πŸ”§ Real-World Use Cases

Need to serve dynamic ZIPs from an Express route?

Use archiver β€” it streams directly to the HTTP response without buffering.

app.get('/download', (req, res) => {
  res.setHeader('Content-Type', 'application/zip');
  const archive = archiver('zip');
  archive.pipe(res);
  archive.file('report.pdf', { name: 'report.pdf' });
  archive.finalize();
});

Building a web app that lets users upload and inspect ZIP contents?

Use jszip β€” it runs in the browser and handles in-memory archives cleanly.

// In browser
const arrayBuffer = await file.arrayBuffer();
const zip = await JSZip.loadAsync(arrayBuffer);
const text = await zip.file('readme.txt').async('text');

Processing massive log directories into ZIPs on a server?

Use yazl or archiver β€” both stream and avoid memory spikes.

Just need to zip/unzip a config folder in a CLI tool?

Use zip-lib β€” its promise API keeps your script concise.

🚫 Deprecated or Limited Packages?

As of 2024:

  • adm-zip is actively maintained but has known security issues in older versions; always use the latest release.
  • zip-lib appears minimally maintained but still functional for basic tasks.
  • None of the listed packages are officially deprecated, but yazl and zip-stream are low-level tools best used indirectly via archiver unless you need their specific control.

πŸ“Š Summary Table

PackageCreate ZIPExtract ZIPStreamingBrowserBest For
adm-zipβœ…βœ…βŒβŒSimple Node scripts needing full read/write
archiverβœ…βŒβœ…βŒServer-side dynamic ZIP generation
jszipβœ…βœ…βŒβœ…Browser-based ZIP manipulation
yazlβœ…βŒβœ…βŒLow-level, high-control ZIP writing
zip-libβœ…βœ…βŒβŒQuick CLI zipping/unzipping
zip-streamβœ…βŒβœ…βŒBuilding custom archiving pipelines

πŸ’‘ Final Guidance

  • For most Node.js servers: Start with archiver β€” it’s robust, streaming, and well-documented.
  • For browser apps: jszip is your only realistic choice.
  • Avoid in-memory libraries (adm-zip, jszip, zip-lib) when handling user-uploaded or large files.
  • Don’t use yazl or zip-stream directly unless you’re replacing archiver for a specific reason (e.g., bundle size or custom logic).

Choose based on your environment (Node vs browser), data size (small vs large), and whether you need to read, write, or both.

How to Choose: adm-zip vs archiver vs jszip vs yazl vs zip-lib vs zip-stream

  • adm-zip:

    Choose adm-zip if you're working in a Node.js environment and need a straightforward, synchronous API for both reading and writing small ZIP files entirely in memory. Avoid it for large archives or streaming scenarios due to its memory footprint.

  • archiver:

    Choose archiver when you need to generate ZIP files dynamically in Node.js with streaming supportβ€”ideal for web servers that must pipe ZIPs directly to HTTP responses without buffering everything in memory. Note that it cannot extract or read existing ZIPs.

  • jszip:

    Choose jszip for browser-based applications where users need to upload, inspect, or download ZIP files entirely client-side. It also works in Node.js but requires manual file I/O and isn't suitable for large files due to its in-memory model.

  • yazl:

    Choose yazl only if you require fine-grained, low-level control over ZIP creation in Node.js with streaming output and want to avoid higher-level abstractions. It’s a good fit for custom tooling but overkill for typical use cases already covered by archiver.

  • zip-lib:

    Choose zip-lib for simple command-line or scripting tasks in Node.js where you need a clean promise-based API to compress folders or extract archives quickly. It’s not suitable for streaming, large files, or browser environments.

  • zip-stream:

    Choose zip-stream only if you're building your own archiving pipeline and need the raw streaming ZIP engine that powers archiver. For almost all practical purposes, archiver is a more complete and user-friendly alternative.

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 });
.
.
.