adm-zip, jszip, node-zip, and zip-stream are libraries used to create, read, and extract ZIP archives in JavaScript. jszip is universal, working in both browsers and Node.js with an async API. adm-zip is designed for Node.js only and uses a synchronous approach for direct file system access. zip-stream provides a streaming interface for Node.js, ideal for large files or piping data. node-zip is a legacy package that is no longer maintained and should be avoided in new projects.
Creating and extracting ZIP files is a common need in web development, whether for downloading multiple assets, backing up data, or processing uploads. The JavaScript ecosystem offers several tools for this, but they differ significantly in where they run, how they handle data, and their current maintenance status. Let's compare how they tackle common problems.
jszip works everywhere.
// jszip: Universal support
const JSZip = require("jszip");
const zip = new JSZip();
// Works in browser console or Node.js script
adm-zip is Node.js only.
// adm-zip: Node.js only
const AdmZip = require("adm-zip");
const zip = new AdmZip();
// Will fail in a browser environment
zip-stream is Node.js only.
// zip-stream: Node.js only
const ZipStream = require("zip-stream");
const output = fs.createWriteStream("archive.zip");
// Requires Node.js stream APIs
node-zip was Node.js only.
// node-zip: Legacy Node.js
const zip = require("node-zip");
// Deprecated and unsupported in modern environments
adm-zip is synchronous.
// adm-zip: Synchronous
zip.addFile("test.txt", Buffer.from("hello"));
zip.writeZip("output.zip"); // Blocks execution here
jszip is asynchronous.
// jszip: Asynchronous
zip.file("test.txt", "hello");
const content = await zip.generateAsync({ type: "blob" }); // Non-blocking
zip-stream is streaming.
// zip-stream: Streaming
const archive = new ZipStream();
archive.pipe(output);
archive.entry("test.txt", { name: "test.txt" });
archive.finalize(); // Ends the stream
node-zip used callbacks.
// node-zip: Callback-based
zip.load(data, function(err, result) {
// Handle result or error in callback
});
The way you add files and save the archive varies greatly between these libraries.
adm-zip uses direct file paths or buffers.
// adm-zip: Add and write
const zip = new AdmZip();
zip.addFile("file.txt", Buffer.from("content"));
zip.writeZip("./archive.zip");
jszip chains file additions and generates asynchronously.
// jszip: Chain and generate
const zip = new JSZip();
zip.file("file.txt", "content");
zip.generateAsync({ type: "nodebuffer" }).then((content) => {
fs.writeFile("archive.zip", content);
});
zip-stream pipes entries into a stream.
// zip-stream: Pipe entries
const archive = new ZipStream();
archive.pipe(fs.createWriteStream("archive.zip"));
archive.entry(fs.createReadStream("file.txt"), { name: "file.txt" });
archive.finalize();
node-zip required loading data first.
// node-zip: Load and modify
const zip = new Zip();
zip.load(binaryData, function(err) {
zip.files["file.txt"] = "content";
});
Extraction logic also differs based on the execution model.
adm-zip extracts directly to the file system.
// adm-zip: Extract to folder
const zip = new AdmZip("archive.zip");
zip.extractAllTo("./output", true);
jszip returns files as objects or blobs.
// jszip: Read content
JSZip.loadAsync(data).then((zip) => {
zip.file("file.txt").async("string").then((text) => {
console.log(text);
});
});
zip-stream is primarily for creation.
unzip-stream instead.// zip-stream: Creation only
// No extraction API available in this package
// Developers must use a separate library for unpacking
node-zip allowed reading via callbacks.
// node-zip: Read entries
zip.files.forEach(function(entry) {
// Process entry data manually
});
jszip is actively maintained.
adm-zip is actively maintained.
zip-stream is maintained but low-level.
archiver ecosystem.node-zip is deprecated.
| Feature | adm-zip | jszip | zip-stream | node-zip |
|---|---|---|---|---|
| Environment | Node.js | Browser + Node | Node.js | Node.js (Legacy) |
| Model | Synchronous | Asynchronous | Streaming | Callback |
| Extraction | β Yes | β Yes | β No | β Yes |
| Status | β Active | β Active | β Active | β Deprecated |
| Best For | CLI Tools | Web Apps | Large Files | None |
jszip is like a universal adapter π β great for teams that need one library to work across frontend and backend. Ideal for web apps, user downloads, and moderate-sized data processing.
adm-zip is like a heavy-duty tool π οΈ β perfect for Node.js scripts that need quick, synchronous access to the file system. Shines in CLI tools and backend automation where simplicity matters.
zip-stream is like a conveyor belt π β best for servers handling large files where memory usage is a concern. Use this when you need to pipe data directly without buffering everything.
node-zip is like an old machine ποΈ β it used to work, but parts are no longer available. Do not use it. Migrate to jszip or adm-zip to keep your stack secure.
Final Thought: Despite their differences, all these libraries aim to handle compression standards. Choose based on your environment and data size. For most modern web work, jszip is the safest bet. For Node-only heavy lifting, adm-zip or zip-stream will serve you better.
Choose adm-zip if you are building a Node.js CLI tool or backend script that needs to synchronously read or write ZIP files to the local disk. It is straightforward for simple tasks where blocking the event loop is acceptable. Avoid it for browser applications or high-concurrency servers where async operations are required.
Choose jszip if you need to handle ZIP files in the browser or require a non-blocking async API in Node.js. It is the best choice for web apps that let users download or upload archives without server involvement. It handles in-memory operations well, making it suitable for moderate-sized files.
Do not choose node-zip for any new project. It is officially deprecated and no longer receives security updates or bug fixes. Existing projects using this library should plan a migration to jszip or adm-zip to ensure long-term stability and security.
Choose zip-stream if you are working in Node.js and need to stream large ZIP archives directly to a response or file without loading everything into memory. It is often used under the hood by higher-level tools like archiver. It is best for high-performance server tasks involving large data sets.
ADM-ZIP is a pure JavaScript implementation for zip data compression for NodeJS.
With npm do:
$ npm install adm-zip
Electron file system support described below.
The library allows you to:
There are no other nodeJS libraries that ADM-ZIP is dependent of
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.
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 });
.
.
.