Create a ZIP from remote URLs
Fetch multiple browser-readable URLs, preserve useful filenames, and download one ZIP with JavaScript.
Fetch a list of remote file URLs in the browser and download them as one ZIP. Use this workflow when the sources allow browser requests and the archive fits comfortably in one tab.
Loading live demo…
Before you start
Install the SDK for your framework and make sure each source allows the browser to fetch it:
npm install @eazip/corenpm install @eazip/reactCreate and download the ZIP
import { createZip } from '@eazip/core';
const files = [
'https://cdn.example.com/invoice-1001.pdf',
{
url: 'https://cdn.example.com/invoice-1002.pdf',
filename: 'invoices/2026/invoice-1002.pdf',
},
];
const result = await createZip({
files,
zipName: 'invoices.zip',
});
result.download();import { useEazip, EazipTray } from '@eazip/react';
const files = [
'https://cdn.example.com/invoice-1001.pdf',
{
url: 'https://cdn.example.com/invoice-1002.pdf',
filename: 'invoices/2026/invoice-1002.pdf',
},
];
export function DownloadInvoices() {
const zip = useEazip();
return (
<>
<button
onClick={() => zip.download({ files, zipName: 'invoices.zip' })}
>
Download invoices
</button>
<EazipTray />
</>
);
}URL strings infer their name from the URL path. Use { url, filename } when
you need a specific filename or folder inside the archive.
Make the URLs browser-readable
Local jobs fetch from the visitor's browser without cookies. The source must allow the application's origin through CORS, for example:
Access-Control-Allow-Origin: https://app.example.comFor private files, have your backend return short-lived signed URLs. Never send bucket credentials or a general-purpose bearer token to frontend code.
Scope custom authorization
If you pass a custom fetch, add credentials only for a trusted, exact source
origin. A mixed URL list must not receive the same authorization blindly.
Keep usable files when one URL fails
The default behavior returns a partial ZIP rather than discarding successful files:
const result = await createZip({
files: urls,
zipName: 'export.zip',
});
if (result.status === 'partial') {
console.warn(`${result.skippedCount} files were skipped`);
}
result.downloadAll();Set failOnUrlError: true only when every source is required. Use startZip()
instead of createZip() when you need custom progress or cancellation.
Move the job beyond the browser
Switch to Cloud when CORS, memory, URL count, or tab lifetime becomes a constraint:
const result = await createZip({
strategy: 'cloud',
publicKey: 'pk_ez_...',
files: urls,
zipName: 'invoices.zip',
});
result.downloadAll();const zip = useEazip();
zip.download({
strategy: 'cloud',
publicKey: 'pk_ez_...',
files: urls,
zipName: 'invoices.zip',
});The React call is fire-and-forget: <EazipTray /> shows progress and the
finished parts. Cloud URLs must be allowed by the Public App and reachable from
Eazip's servers.
Continue with When to use Eazip Cloud or Create multi-GB ZIP archives with JavaScript.