Create a ZIP File in the Browser with JavaScript
Turn browser files, blobs, and URLs into a ZIP entirely client-side — one createZip call, no server, no upload, with the options that actually matter.
Browsers can build real ZIP archives — no server round trip, no uploading the user's files anywhere. This page is the plain-JavaScript how-to: what can go into a browser-made ZIP, the one call that builds it, and the handful of options worth knowing.
The one call
import { createZip } from '@eazip/core';
const result = await createZip({
files: fileInput.files, // a FileList from <input type="file" multiple>
zipName: 'export.zip',
});
result.download();createZip() resolves when the archive is ready; result.download()
hands it to the browser's normal download flow. That's a working feature —
Eazip.js is MIT-licensed and needs no account. (Package setup and a
step-by-step first run live in
Getting Started / JavaScript.)
What can go in
One files array accepts every source, mixed freely:
| Source | Example |
|---|---|
| Picked or dropped files | File, FileList, Blob |
| Generated content | new Blob([csvText]) with a filename |
| Remote URLs | 'https://assets.example.com/report.pdf' |
| Named entries | { url, filename } or { file, filename } |
Two things to know about entries:
filenamecontrols the unzipped result, and forward slashes create folders:{ file: photo, filename: 'photos/cover.jpg' }.- Remote URLs must be fetchable from the page — same-origin, public with CORS, or signed URLs your server minted. The rules are in Inputs and sources, and the per-platform signing recipes in the storage guides (S3, R2, Supabase).
The options that matter
const result = await createZip({
files,
zipName: 'photos.zip',
compressionLevel: 0, // store-only: JPEGs and MP4s don't compress twice
maxZipSizeBytes: 1_000_000_000, // split output into ~1 GB parts
onProgress: (progress) => render(progress),
});compressionLevel: 0skips Deflate entirely — the right choice when the sources are already compressed (photos, video, existing archives). It saves real CPU time and the output is barely larger.maxZipSizeBytessplits large output into numbered parts (export_part01.zip, …); callresult.downloadAll()for every part. See Multi-ZIP splitting.onProgressreports file and byte progress for your own UI. For cancel buttons and richer state, usestartZip()instead — the shape is in Show progress, cancel, and retry.- Failed URL fetches don't destroy the archive by default: usable output ships and failures are reported — see Partial results and errors.
Where the browser stops
Honest boundaries, because they're architectural rather than fixable:
- Memory holds the archive while it builds — multi-gigabyte ZIPs in a tab are unreliable (the details).
- The tab is the runtime — navigation or reload ends the job.
- Legacy ZIP limits don't apply (output is ZIP64), but your users' ancient extraction tools might care — ZIP files over 4 GB.
When exports outgrow the tab, the same createZip call takes
strategy: 'cloud' and a public key, and the job moves to managed Eazip
without changing your UI — see Scale with Eazip.
FAQ
Does this upload my users' files anywhere?
Not on the Local path — files are read and packaged inside the page. If
you later opt into the managed path, sources are fetched by the service;
that switch is explicit (strategy: 'cloud').
Can I create a ZIP from a folder the user picks?
Yes — <input type="file" webkitdirectory> yields a FileList whose
entries carry relative paths; map them to filename values to preserve
the folder structure inside the archive.
How big a ZIP can the browser build?
Hundreds of megabytes is routine; multiple gigabytes is where tab memory makes it a gamble. ZIP large files in the browser covers the mitigation options in order.
Do I need a Web Worker?
No — bring your own if your app's main thread is busy, but the library runs fine without one for typical export sizes.
Download Supabase Storage Files as a ZIP in the Browser
Sign a whole folder with one createSignedUrls call and let @eazip/core fetch and package the files into a ZIP in the user's browser — no bucket CORS setup, no server proxying.
Download Multiple Files at Once in JavaScript
Why the loop of anchor clicks fails, what browsers actually allow, and the reliable pattern — packaging the files into one ZIP download client-side.