Bulk File & Image Downloader: Links, Pages, ZIP
Pricing
from $1.00 / 1,000 file downloadeds
Bulk File & Image Downloader: Links, Pages, ZIP
Download files from a list of links, or the images and linked PDFs, CSVs or ZIPs on web pages, into Apify storage. One row per file with a download link, type, size, SHA-256 and image size. Optional ZIP. Failed files are free.
Pricing
from $1.00 / 1,000 file downloadeds
Rating
0.0
(0)
Developer
Public Data Tools
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Security
Limited permissionsShare
Download files in bulk from a list of links, or every image on a web page and the PDFs, CSVs, spreadsheets or ZIPs it links to. Each file is saved in your Apify storage with a download link that works, and you get one row per file with its type, size, SHA-256 and, for images, width and height. Turn on one ZIP of everything if you want a single download.
- 📥 Two ways in, one run: paste direct file links (images, PDFs, CSVs, Excel, ZIPs, audio, video, anything), or pages to collect files from.
- 🖼️ Images from pages:
<img>with srcset and lazy-load attributes,<picture>sources and the og:image; the largest version by default. - 📎 Linked files by extension:
pdf,csv,xlsx,zip,docx,mp3… from links, embeds and media sources on the page. - 🧾 A row per file: download link, file name, content type, size in bytes, SHA-256, image width and height, the page it was on, its alt text.
- 🧹 Filters and limits: file types and extensions, minimum and maximum size, minimum image size, duplicates by link and by content, a file count and a total size the run never passes.
- 🤖 Polite: robots.txt for pages and the files found on them, 2 connections and 25 Mbit/s per site by default, Retry-After honoured, an honest user agent.
- 💸 $1 per 1,000 files up to 2 MB each; larger files add $0.0002 per MB. Skipped, duplicate and failed files are free.
Try it: the input comes pre-filled with the Wikipedia article on The Starry Night, at most 10 files and 5 MB, and images of at least 200 × 200 pixels. Click Start: in a few seconds you get ten images of the painting and related works, with their sizes and hashes, for $0.01.
What you get
One row per file, in the Files table (with a preview of each image) and as JSON, CSV or Excel:
| Data | What's in it |
|---|---|
| Status | downloaded (stored and charged) or, free: duplicate, skipped, not downloaded, disallowed, blocked, refused, failed, with the reason in plain words |
| The file | key in the run's key-value store, downloadUrl (opens the file, also from outside Apify), fileName from the server or the link, contentType, fileType (image, pdf, document, spreadsheet, archive, audio, video, other), extension, sizeBytes, sha256 |
| Images | width and height in pixels, read from the file's header (JPEG, PNG, GIF, WebP, AVIF, HEIC, BMP, TIFF, ICO, SVG) |
| Where it came from | sourceUrl, finalUrl after redirects, httpStatus, pageUrl and how it was found (img, srcset, picture, og:image, link, embed, media, or input for your own links), the image's altText or the link's text |
| Duplicates | duplicateOf: the key of the stored file with the same SHA-256 |
| Billing | extraMegabytes: started MB above the first 2 MB |
| When | fetchedAt |
The files themselves are in the run's key-value store (the Storage tab, or the "Downloaded files" link in the output), named by your pattern: 00001-Mona_Lisa.jpg by default. With the ZIP on, files.zip holds them all.
The RUN_SUMMARY record has counts per status, every page with what was found on it, each host's requests and limits, the robots.txt answers, and the files found on pages that weren't tried because a limit was reached.
Who it's for
- E-commerce and marketplace teams: pull product photos from your own or your suppliers' pages, or from a scraper's image links, into one place with sizes and hashes.
- Researchers and data teams: collect image or document sets from listed pages, de-duplicated by content, with the page, alt text and fetch time for each.
- Site migrations and backups: save every image and PDF your old pages show before you move them.
- Developers and automations: turn a column of file links from another Actor, a sheet or an API into stored files with stable links, then pass them on.
- Archivists and compliance teams: keep copies of published PDFs and spreadsheets with a SHA-256 for each.
How much does it cost?
You pay per file stored, plus Apify's standard run start fee (a fraction of a cent):
| Event | Price |
|---|---|
| File stored, first 2 MB included | $0.001 |
| Each started MB of a file above its first 2 MB | $0.0002 |
| ZIP of all files (only when on), per started MB of the ZIP | $0.0001 |
| Example | Cost |
|---|---|
| The pre-filled example: 10 images | $0.01 |
| 1,000 product photos under 2 MB | $1 |
| One 20 MB file | $0.0046 ($0.001 + 18 × $0.0002) |
| 200 PDFs of 5 MB | $0.32 |
| The same 200 PDFs with a ZIP (1 GB) | $0.42 |
Free: skipped files (filters, size limits), duplicates, files a robots.txt disallows, blocked and failed downloads, files not tried because a limit was reached, pages, and runs that fail.
Why a price per MB? Apify bills this Actor for every megabyte it writes to your storage and for the time each download takes, and the ZIP is a second copy, so big files cost more to deliver. Files up to 2 MB, most images and PDFs, pay only the file price. Set a maximum cost per run in the run options; the run stops cleanly at that amount.
How to use it
- Add file links, one per line, under File links, or pages under Pages to collect files from, or both.
- For pages, choose what to collect: images (on by default; the largest version, or as shown), the og:image, and linked files by extension (for example
pdf,csv,xlsx). - Filter (optional): file types, extensions, minimum and maximum file size, minimum image width and height.
- Set the limits: the most files and the most megabytes per run, and whether to skip duplicates by link and by content.
- Name the files (optional): a pattern such as
{index}-{name},{host}-{name}or{hash}; turn on the ZIP if you want one archive. - Click Start. The Files table shows each file with a preview, size and download link. Export it as JSON, CSV or Excel.
Only the pages you list are read; links from them to other pages aren't followed. Images a page adds with JavaScript, or sets in CSS, aren't in its HTML, so they aren't found.
Example input
Product photos and a price list from your own links:
{"fileUrls": ["https://example.com/images/sku-1001.jpg","https://example.com/images/sku-1002.png","https://example.com/downloads/price-list.xlsx"],"fileNamePattern": "{name}"}
Every image and PDF on two pages, at least 300 px wide, in one ZIP:
{"pageUrls": ["https://example.com/products/chairs", "https://example.com/catalogue"],"linkExtensions": ["pdf"],"minImageWidth": 300,"zip": true}
Only the PDFs and spreadsheets a page links to, no images:
{"pageUrls": ["https://example.org/reports"],"collectImages": false,"linkExtensions": ["pdf", "csv", "xlsx"],"maxFiles": 200,"maxTotalMb": 500}
Example output
A row from the pre-filled example (a thumbnail of a public-domain painting on Wikimedia Commons), shortened:
{"rowType": "file","status": "downloaded","index": 9,"sourceUrl": "https://thumb.wikimedia.org/wikipedia/commons/thumb/e/e7/Vincent_van_Gogh_-_Green_Field_-_Google_Art_Project.jpg/330px-Vincent_van_Gogh_-_Green_Field_-_Google_Art_Project.jpg?utm_source=en.wikipedia.org&utm_campaign=parser&utm_content=thumbnail","pageUrl": "https://en.wikipedia.org/wiki/The_Starry_Night","foundIn": "srcset","fileName": "Vincent_van_Gogh_-_Green_Field_-_Google_Art_Project.jpg","key": "00009-Vincent_van_Gogh_-_Green_Field_-_Google_Art_Project.jpg","downloadUrl": "https://api.apify.com/v2/key-value-stores/…/records/00009-Vincent_van_Gogh_-_Green_Field_-_Google_Art_Project.jpg?signature=…","contentType": "image/jpeg","fileType": "image","extension": "jpg","sizeBytes": 43977,"sha256": "…","width": 330,"height": 271,"duplicateOf": null,"extraMegabytes": 0,"fetchedAt": "2026-11-04T…Z","error": null}
And a free one:
{"status": "disallowed","sourceUrl": "https://en.wikipedia.org/w/resources/assets/poweredby_mediawiki.svg","pageUrl": "https://en.wikipedia.org/wiki/The_Starry_Night","error": "Not downloaded: robots.txt of en.wikipedia.org disallows it. Not charged."}
Good to know
- Download links:
downloadUrlis the stored record's address. When your Apify storage is private (the default for new accounts), the link carries a signature so it opens without an Apify token; anyone with the link can open that file. The files stay for your plan's data retention period, like any run's storage. - Names: keys may only use letters, digits and
! - _ . ' ( ), so other characters become-(accents are dropped:Café.jpg→Cafe.jpg). A repeated key gets-2,-3. The original name is infileName. - File types come from the file's first bytes where they say (images, PDF, ZIP and other archives, audio, video), else from the server's file name, the link or the Content-Type. A Word, Excel or PowerPoint file keeps its own extension.
- Limits: a file over the per-file size isn't downloaded when the server says its size, and is stopped as soon as it passes the limit when it doesn't. The total size is checked before each file is stored, so the run never stores more than you set. Each file passes through the run's disk on its way to storage (about 8 GB free at the default 1 GB of memory in tests); large files are never held whole in memory.
- Duplicates: with Skip duplicate files on, a file with the same content as one already stored is listed with
duplicateOfand not stored or charged again. - Web pages given as file links are skipped with a hint to put them under Pages, unless you add
htmlto Only these extensions. - Bigger runs: up to 10,000 files and 20 GB per run, and 1,000 pages; 10 downloads at a time by default (up to 20).
Integrations
-
Apify API: start a run and get the rows back as JSON in one call:
curl -X POST "https://api.apify.com/v2/acts/subtleasianmerch~bulk-file-downloader/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{"fileUrls": ["https://example.com/a.pdf", "https://example.com/b.jpg"]}'Replace
YOUR_TOKENwith your Apify API token. Each row'sdownloadUrlgives you the file. -
After another Actor: feed it the image or file links another scraper found, with a webhook or an Apify integration that starts this Actor when the first one finishes.
-
Make, Zapier and n8n: send the stored files' links to Google Drive, Dropbox, S3, Slack or a database with Apify's apps for these tools.
-
Schedules: run it daily or weekly in Apify Console to keep copies of files that change.
FAQ
Is it legal to use?
The files belong to their owners. You are responsible for having the right to download the files you choose and to use them the way you plan to: your own files, files under an open licence (and following its terms, such as credit), or files you have permission for. Each row keeps the source address, the page and the fetch time, so you can credit and check sources; this Actor doesn't decide or record licences. It respects robots.txt for the pages you give and for every file it finds on them, sends an honest user agent, keeps to a few connections per site, and doesn't get past blocks: a site that refuses, asks it to wait for long, or shows a bot check gets a free row and is left alone. Direct links you give are fetched as given. This isn't legal advice.
Does it follow robots.txt?
Yes, for crawling: before reading a page, and before downloading each file found on a page, it reads that host's robots.txt (rules for bulk-file-downloader, else for *) and skips what it disallows, listed as disallowed and free. A robots.txt that can't be read (a server error) counts as "disallow everything". A Crawl-delay of up to 60 seconds is kept, with one connection to that host. Links you list yourself under File links aren't crawled, so robots.txt isn't consulted for them, as with any download you start yourself.
Why was an image skipped or missing?
The row says why: too small (bytes or pixels), the wrong type or extension, a duplicate, disallowed by robots.txt, or a server that refused. If an image you see in your browser isn't listed at all, the page adds it with JavaScript or shows it as a CSS background; this Actor reads the HTML the server sends, without a browser. Give the image's own link under File links instead.
Can it download from sites that need a login?
No. It fetches public links only, without cookies or passwords. Links that already carry their own access, such as signed S3 or Google Cloud links, work; credentials in links are hidden in the rows and logs.
Can it reach my private network?
No. Addresses on private, local and cloud metadata networks are refused, including when a link redirects to one or when a name resolves to one.
How do I get all files at once?
Turn on Also save one ZIP of all files: files.zip appears in the key-value store and in the output's "ZIP of all files" link. Or download the records from the Storage tab, or use each row's downloadUrl.
What happens with HTTP 429 (too many requests)?
The Actor pauses that host for as long as the server asks (Retry-After, up to 120 seconds) and tries again, up to three times. A server that asks for a longer pause, or keeps answering 429, gets its remaining files listed as blocked, free; the Actor doesn't switch addresses or proxies to get around it.
Related Actors
More Actors from the same developer that work well with this one:
| Actor | Use it to |
|---|---|
| Website Screenshot API | capture the pages themselves as images or PDFs |
| Bluesky Scraper | collect posts with their image links, then download the images here |
Questions, bugs or ideas? Open an issue on this Actor's Issues tab.