Bulk File Downloader - URLs to Files and ZIP avatar

Bulk File Downloader - URLs to Files and ZIP

Pricing

from $0.70 / 1,000 files

Go to Apify Store
Bulk File Downloader - URLs to Files and ZIP

Bulk File Downloader - URLs to Files and ZIP

Download files from a list of URLs, web pages or another Actor's dataset: images, PDFs, video, audio. Fast and resumable, with SHA-256, image size, duplicates removed and optional ZIP. You pay only for files stored.

Pricing

from $0.70 / 1,000 files

Rating

0.0

(0)

Developer

Shivam Prajapati

Shivam Prajapati

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

16 hours ago

Last modified

Security

Limited permissions

Share

Download files in bulk from a list of URLs, from web pages, or from the dataset of another Actor. Images, PDFs, videos, audio and archives are streamed to disk, stored in your key-value store (and packed into ZIP parts on request), and reported in one table with size, content type, SHA-256, image width and height, redirects and tries. Same content is stored once, broken downloads continue where they stopped, and you pay only for files that were stored: failed and skipped addresses are free. No proxy, no login, no browser.

Actively maintained. Last update: 2026-11-07. Every release passes 100+ automated tests, and Apify test-runs it every day.

What can you use it for?

  • Turn scraper output into files. Another scraper gave you 5,000 image or PDF links. Give this Actor the dataset id and get the files.
  • Back up media. Download all images, videos and documents from a list of pages in one run, with a ZIP at the end.
  • Product image libraries. Name every image by a template such as {host}_{filename} and keep one ZIP per run.
  • Archive and prove. Every file comes with its SHA-256, size and server headers (etag, lastModified), ready for audits and deduplication.
  • Feed AI and data pipelines. Hand the stored file links and image sizes to the next step.

What data do you get?

One row per stored file. Failed addresses are not rows: they are in the FAILED_URLS record, with the reason.

FieldWhat it is
url, finalUrlThe address you gave, and where it led after redirects
statusdownloaded, or duplicate when an earlier file in the run has the same content
fileName, key, storageUrlThe file's name, its record key and the link to the stored file
contentType, fileType, extensionServer content type, image, document, video, audio, archive or other, and the extension
bytes, sha256Size and SHA-256 of the content
width, heightImage size in pixels (PNG, JPEG, GIF, WebP, BMP)
duplicateOfFor a duplicate: the key of the file with the same content
httpStatus, lastModified, etagServer answer and headers
sourcePageThe page the file was found on (page scans)
zipPartThe ZIP part the file is in, e.g. files-part-001.zip
redirects, attempts, downloadMsRedirects followed, tries needed and time taken
fetchedAtWhen the file was downloaded (UTC)

Example result

{
"url": "https://upload.wikimedia.org/wikipedia/commons/a/a9/Example.jpg",
"finalUrl": null,
"status": "downloaded",
"fileName": "Example.jpg",
"key": "6a1f0c3e-Example.jpg",
"storageUrl": "https://api.apify.com/v2/key-value-stores/xxxx/records/6a1f0c3e-Example.jpg",
"contentType": "image/jpeg",
"fileType": "image",
"extension": "jpg",
"bytes": 12345,
"sha256": "3b1c...",
"width": 275,
"height": 297,
"duplicateOf": null,
"httpStatus": 200,
"sourcePage": null,
"zipPart": null,
"redirects": 0,
"attempts": 1,
"downloadMs": 180,
"fetchedAt": "2026-11-07T12:00:00Z"
}

How to use it

  1. Paste file links into File URLs, or list pages in Or web pages to scan for files, or give a dataset id.
  2. Pick the kinds of files you want, a ZIP option and a file name template if you like.
  3. Set Maximum files and press Start. Files appear in the key-value store as they arrive.

Input options

InputWhat it does
urlsFile links to download: one by one, pasted (one per line) or from a text file. Objects with url and fileName work through the API
pageUrlsWeb pages to scan for images, video, audio, documents and archives (each page is read once)
datasetId, urlFieldsDownload every file link in the rows of another Actor's dataset; name the fields or let the Actor find them
fileTypesKeep only some kinds of files; others are skipped for free
sameHostOnly, maxFilesPerPagePage scans: stay on the page's site, and cap the files taken from each page
saveFiles, zip, zipPartMbStore each file, pack ZIP parts (none, single, byHost), and the part size
fileNameTemplate, uniqueFileNamesThe record key: {filename} {name} {ext} {host} {urlhash} {sha} {type} {index}, with a short address code in front
maxFileSizeMb, maxRetries, timeoutSecondsSize limit, retries and the wait for the server's next bytes
maxPerHost, maxConcurrencyDownloads at once from one site and in total
headers, userAgent, refererExtra request headers, for files you are allowed to download
acceptHtmlSave an address that returns a web page as a file instead of a failure
keyValueStoreNameSave into a named key-value store that does not expire
onlyNewSkip addresses that earlier runs of this same input already returned
maxItemsStop after this many stored files

How much does it cost?

You pay per stored file, nothing else. Failed downloads, skipped files, wrong kinds and too-large files are free and do not count toward the maximum. The first Apify plan includes free monthly credit to try it.

PlanPrice per 1,000 files
Free$1.00
Bronze$0.90
Silver$0.80
Gold$0.70

Use it via API, on a schedule, or with your tools

from apify_client import ApifyClient
client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("pshivam/bulk-file-downloader-scraper").call(run_input={
"datasetId": "<DATASET_ID_OF_ANOTHER_RUN>",
"fileTypes": ["image"],
"zip": "single",
"maxItems": 1000,
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
print(row["fileName"], row["bytes"], row["width"], row["height"], row["storageUrl"])

Schedule it in the Apify Console (Schedules) and turn on Only new files to download only what earlier runs did not. Connect the result to Google Sheets, Make, Zapier, n8n or your own app with Apify's integrations.

Good to know

  • Files are streamed to disk and uploaded in parallel. Memory stays flat, so a 100 MB video and a 5,000-image list run on the same 256 MB.
  • Interrupted downloads continue. When a connection drops and the server supports byte ranges, the download resumes from the last byte.
  • Same content is stored once. A second file with the same SHA-256 gets a duplicate row that points to the first.
  • Private networks are refused. Addresses that lead to internal or private IP addresses fail with blocked_address.
  • Web pages are read once. Page scans do not crawl further and do not run JavaScript. Images that a page loads with JavaScript need a browser scraper first.
  • Some links expire. Links from social media and CDNs often stop working after hours. Run the download soon after the scrape.
  • Streaming sites are not file links. An address that returns a web page (a YouTube watch page, for example) is a failure html_instead_of_file, not a saved page.
  • Files are kept as your run's records. Run records expire after your plan's retention time. Use keyValueStoreName for a store that stays.

FAQ

How do I download many files from a list of URLs?

Paste the links into File URLs (one per line) or load a text file, set Maximum files, and press Start. Each stored file is a record in the key-value store and a row in the results table.

Can it download all images from a web page?

Yes. Put the page in Or web pages to scan for files and pick the image kind. It finds img tags (the sharpest srcset size), picture sources, video posters, icons and og:image links.

Can I download the files of another Actor's results?

Yes. Give the dataset id of the other run. Fields such as imageUrl, images, pdf and video are found on their own, or name them in Dataset fields with the links.

Can I get everything as a ZIP?

Yes. Choose One ZIP (in parts). Parts close at the size you set and appear as files-part-001.zip and so on. Turn off Store each file to get only the ZIP.

What happens to failed downloads?

They are not charged and not counted toward the maximum. The FAILED_URLS record lists each address with the reason (not_found, forbidden, timeout, html_instead_of_file, too_large and more).

Does it work with login-protected files?

It sends the headers you give in Extra request headers, for example an Authorization header or a Cookie, for files you are allowed to download. It does not log in and does not bypass blocks.

The Actor fetches the addresses you give, like a download manager. You are responsible for having the right to download and keep the files and for following the terms of the sites you download from.

How do I download only new files every day?

Turn on Only new files and schedule the Actor. It remembers what it returned in your key-value store.