extract-zip, unzip, and unzipit are npm packages that handle decompression of ZIP archives, but they target different environments and use cases. extract-zip is a Node.js-specific utility that writes extracted files directly to the filesystem. unzip is an older, stream-based Node.js library for parsing ZIP files, but it has known stability and maintenance issues. unzipit is a modern, browser-compatible library that operates entirely in memory using Web APIs like Response and File, making it suitable for frontend applications without filesystem access.
When your app needs to unpack ZIP files, the right library depends heavily on where your code runs and what you do with the data. These three packages — extract-zip, unzip, and unzipit — solve similar problems but with fundamentally different assumptions about environment, safety, and output. Let’s break down their real-world trade-offs.
unzipFirst, the bad news: unzip is deprecated and should not be used in new projects. Its npm page explicitly states it’s no longer maintained, and the GitHub repository shows no meaningful activity since 2018. It’s known to crash on certain ZIP structures and lacks support for modern Node.js versions. If you see it in a legacy codebase, plan to migrate.
⚠️ Do not use
unzipfor new development. It’s unstable, unmaintained, and superseded by safer alternatives.
That leaves us with two viable options: extract-zip for Node.js filesystem workflows, and unzipit for in-memory, cross-environment use.
extract-zip (Node.js Only)extract-zip is purpose-built for one job: take a ZIP file path or buffer and dump its contents into a directory on disk. It uses Node.js streams under the hood but hides the complexity behind a simple promise-based API.
// extract-zip: Extract to filesystem
import extract from 'extract-zip';
await extract('archive.zip', { dir: './output' });
// All files from archive.zip now exist in ./output/
Key traits:
fs, path, and stream modules.This makes it perfect for backend tasks like processing user uploads, deploying packaged assets, or automating builds — anywhere you control the server environment and want files on disk.
unzipit (Browser + Node.js)unzipit takes a completely different approach. Instead of writing to disk, it lets you inspect and read ZIP entries as streams or arrays in memory. It works identically in browsers, Node.js, Deno, and edge runtimes because it relies only on standard Web APIs like Uint8Array and ReadableStream.
// unzipit: Read entries in memory
import { unzip } from 'unzipit';
const { entries } = await unzip(new Uint8Array(zipBuffer));
// List filenames
console.log(Object.keys(entries)); // ['file1.txt', 'image.png', ...]
// Read a specific file as text
const text = await entries['file1.txt'].text();
// Or as an ArrayBuffer
const bytes = await entries['image.png'].arrayBuffer();
You can also feed it a Response object directly from fetch():
// unzipit with fetch (browser or Node.js with fetch)
const res = await fetch('/download/archive.zip');
const { entries } = await unzip(res);
const content = await entries['readme.md'].text();
Key advantages:
Use this when you’re in the browser, working with serverless functions, or simply don’t want to touch the filesystem.
| Feature | extract-zip | unzip (deprecated) | unzipit |
|---|---|---|---|
| Environment | Node.js only | Node.js only | Browser, Node.js, Deno, etc. |
| Output destination | Filesystem | Streams (to filesystem) | In-memory (Uint8Array, strings) |
| Async API | Promise-based | Stream-based (callback-heavy) | Promise + async/await |
| Partial extraction | ❌ (extracts all) | ✅ (via stream filtering) | ✅ (access entries by name) |
| Malformed ZIP handling | Robust (uses yauzl) | ❌ Crashes easily | Robust |
| Maintenance status | Actively maintained | Deprecated / abandoned | Actively maintained |
You run an Express server that accepts ZIP uploads and saves contents to disk.
extract-zip// Express route using extract-zip
app.post('/upload', async (req, res) => {
const zipPath = req.files.archive.tempFilePath;
await extract(zipPath, { dir: `/uploads/${userId}/` });
res.json({ status: 'success' });
});
Users drag a ZIP file into your React app, and you show a list of files with previews.
unzipit// React handler using unzipit
const handleDrop = async (file) => {
const arrayBuf = await file.arrayBuffer();
const { entries } = await unzip(new Uint8Array(arrayBuf));
const filenames = Object.keys(entries);
setFileList(filenames);
// Preview first text file
if (filenames[0].endsWith('.txt')) {
const content = await entries[filenames[0]].text();
setPreview(content);
}
};
A Cloudflare Worker fetches a ZIP config bundle and reads a manifest.json inside.
unzipitunzipit works with fetch() natively.// Cloudflare Worker
export default {
async fetch(request) {
const zipRes = await fetch('https://cdn/configs/latest.zip');
const { entries } = await unzip(zipRes);
const manifest = await entries['manifest.json'].json();
return new Response(JSON.stringify(manifest));
}
};
Error resilience matters when dealing with user-provided archives.
extract-zip fails fast on invalid ZIPs:
try {
await extract('corrupt.zip', { dir: './out' });
} catch (err) {
console.error('Extraction failed:', err.message);
}
unzipit also throws on malformed headers but allows safe inspection before reading:
try {
const { entries } = await unzip(buffer);
// Safe to check entry names first
if ('important.txt' in entries) {
const data = await entries['important.txt'].text();
}
} catch (err) {
console.error('Invalid ZIP:', err.message);
}
In contrast, unzip often crashes the Node.js process on corrupt input due to unhandled stream errors — another reason to avoid it.
extract-zip.unzipit.unzip? → Don’t. Migrate existing usage to extract-zip (for disk) or unzipit (for memory).These tools aren’t interchangeable — they solve different problems. Pick based on your runtime environment and whether you need filesystem access. When in doubt, unzipit’s portability makes it the safer default for modern web apps.
Choose extract-zip if you're working in a Node.js environment and need to extract ZIP contents directly to disk with minimal setup. It’s ideal for CLI tools, build scripts, or backend services where filesystem I/O is acceptable and expected. Avoid it in browser contexts—it won’t work there.
Choose unzipit when you need ZIP extraction in the browser or in environments without filesystem access (e.g., Cloudflare Workers, Deno, or serverless functions). It works entirely in memory, supports async iteration over entries, and integrates cleanly with modern Web APIs like fetch() and File. It’s the only option here that runs reliably outside Node.js.
Avoid unzip in new projects. It is deprecated, unmaintained, and prone to crashes with malformed archives. While it once provided streaming ZIP parsing in Node.js, its instability and lack of updates make it a liability. Use extract-zip for simple extraction or consider lower-level alternatives like yauzl if you need streaming control.
Unzip written in pure JavaScript. Extracts a zip into a directory. Available as a library or a command line program.
Uses the yauzl ZIP parser.
Make sure you have Node 10 or greater installed.
Get the library:
npm install extract-zip --save
Install the command line program:
npm install extract-zip -g
const extract = require('extract-zip')
async function main () {
try {
await extract(source, { dir: target })
console.log('Extraction complete')
} catch (err) {
// handle any errors
}
}
dir (required) - the path to the directory where the extracted files are writtendefaultDirMode - integer - Directory Mode (permissions), defaults to 0o755defaultFileMode - integer - File Mode (permissions), defaults to 0o644onEntry - function - if present, will be called with (entry, zipfile), entry is every entry from the zip file forwarded from the entry event from yauzl. zipfile is the yauzl instanceDefault modes are only used if no permissions are set in the zip file.
extract-zip foo.zip <targetDirectory>
If not specified, targetDirectory will default to process.cwd().