Bulk Image Downloader
Pricing
Pay per usage
Bulk Image Downloader
Download every image from a list of public web pages or direct image URLs, with size and type filters, optional ZIP output and per-image links in the dataset.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Cole Cassel
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Give it a list of web pages, or direct image links, and it finds and downloads every image. Each one gets a direct download link, and you also get a single ZIP file of everything. It looks well beyond <img> tags:
- responsive
srcsetand<picture>sources (it keeps the largest version); - lazy-load attributes such as
data-src; - Open Graph and Twitter preview images;
- CSS background images.
Duplicates, tiny icons and unwanted formats are filtered out automatically.
You pay $0.003 per page plus $0.0005 per saved image. That comes to $0.013 for a page with 20 images, compared with $0.07 per page for the most-used alternative.
What it does
- Fetches each start URL. If the URL is an HTML page, it extracts image URLs from:
<img src>, lazy attributes (data-src,data-lazy-src,data-original, …),srcsetand<picture><source>;og:image,twitter:imageandapple-touch-icontags;- inline
style="background-image:…"and<style>blocks; - optionally,
<a href>links that point at image files.
- If the URL is itself an image, it simply downloads it.
- Checks the file's real type from its bytes, not the file name:
- JPEG, PNG, GIF, WebP, AVIF, SVG, BMP or ICO;
- measures width and height;
- drops files smaller than
minWidth×minHeight; - drops exact duplicates by SHA-1.
- Stores every image in the run's key-value store and adds it to
images.zip. - Returns one dataset row per image (
type: "image") and one summary row per page (type: "page"), plus anOUTPUTrecord with totals and the ZIP link. - Is polite by default:
- respects
robots.txt; - waits between requests to the same host;
- identifies itself (
BulkImageDownloaderBot/1.0); - refuses private or internal network addresses.
- respects
Use cases
- Collecting product or catalog photos from your own or a partner's public site.
- Downloading open-licensed media, for example from Wikimedia Commons, for research and datasets.
- Website migrations and backups: grab every image from a list of pages.
- Building image datasets for AI or vision projects from public sources you are allowed to use.
- Auditing a site's images: formats, sizes, missing alt text.
Input
{"startUrls": [{ "url": "https://commons.wikimedia.org/wiki/Commons:Featured_pictures/Animals/Birds" },{ "url": "https://en.wikipedia.org/wiki/Bald_eagle" },{ "url": "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png" }],"maxImagesPerPage": 20,"maxTotalImages": 60,"minWidth": 100,"minHeight": 100,"createZip": true}
| Field | Default | Notes |
|---|---|---|
maxImagesPerPage / maxTotalImages | 100 / 1000 | Hard caps, which also cap your cost |
minWidth / minHeight | 50 px | Removes icons and tracking pixels; SVGs have no pixel size and are kept |
maxImageMb | 25 | Larger files are skipped |
imageTypes | all | Choose any of jpeg, png, gif, webp, avif, svg, bmp, ico |
includeSrcset, includeBackgroundImages, includeMetaImages | true | Turn sources off to get fewer, more focused images |
includeLinksToImages | false | Also follow <a href="….jpg"> links |
sameDomainOnly | false | Keep only images hosted on the page's own site |
urlIncludeRegex / urlExcludeRegex | — | Case-insensitive filters on image URLs |
createZip / maxZipMb | true / 100 | The ZIP stops growing at the cap; images stay in the store either way |
respectRobotsTxt | true | |
maxConcurrency / minDelayBetweenRequestsSecs | 5 / 0.25 s | |
requestTimeoutSecs / maxRetries | 30 s / 2 | Retries with exponential backoff on timeouts and on 429/5xx |
Output
Real rows from a test run on 2026-10-18. On Apify, fileUrl and zipUrl are public links.
An image row:
{"type": "image","url": "https://thumb.wikimedia.org/wikipedia/commons/thumb/d/db/Bald_eagle_about_to_fly_in_Alaska_%282016%29.jpg/500px-Bald_eagle_about_to_fly_in_Alaska_%282016%29.jpg?utm_source=en.wikipedia.org&utm_campaign=parser&utm_content=thumbnail","ok": true,"pageUrl": "https://en.wikipedia.org/wiki/Bald_eagle","foundIn": "srcset","alt": "","imageType": "jpeg","width": 500,"height": 400,"bytes": 41607,"sha1": "cbc23b0ff7a6e3c7bbcc7e7504f8dc5416771b81","fileKey": "500px-Bald_eagle_about_to_fly_in_Alaska_(2016)-6ed4a69395.jpg","fileUrl": "https://api.apify.com/v2/key-value-stores/<store-id>/records/500px-Bald_eagle_about_to_fly_in_Alaska_(2016)-6ed4a69395.jpg","attempts": 1,"processedAt": "2026-10-18T19:09:38Z"}
A page summary row. This page had 1,232 candidate images; 20 were saved because of maxImagesPerPage:
{"type": "page","url": "https://commons.wikimedia.org/wiki/Commons:Featured_pictures/Animals/Birds","ok": true,"finalUrl": "https://commons.wikimedia.org/wiki/Commons:Featured_pictures/Animals/Birds","imagesFound": 1232,"imagesSaved": 20,"imagesFailed": 0,"imagesSkipped": { "max_images_per_page": 1158, "too_small": 54 },"processedAt": "2026-10-18T19:10:02Z"}
The OUTPUT record in the key-value store:
{"imagesSaved": 45,"pagesProcessed": 3,"failures": 2,"stoppedByBudget": false,"zipUrl": "https://api.apify.com/v2/key-value-stores/<store-id>/records/images.zip","zipImages": 45,"zipTruncated": false}
Failures become rows with ok: false and an error.code:
ROBOTS_DISALLOWED,HTTP_404and otherHTTP_<status>codes,TIMEOUT;NETWORK_ERROR,DNS_ERROR,PRIVATE_ADDRESS,INVALID_URL;TOO_LARGE,NOT_HTML_OR_IMAGE.
The test run handled 6 start URLs in 30 seconds:
- 45 images saved (27 JPEG, 7 PNG, 6 WebP, 5 SVG);
- a 1.6 MB ZIP;
- one robots.txt block and one 404, both recorded as free error rows.
Pricing
Pay per event:
| Event | Price |
|---|---|
| HTML page processed | $0.003 |
| Image saved | $0.0005 ($0.50 per 1,000) |
| Run start (Apify standard) | $0.00005 per GB of memory |
Skipped images, failed downloads and failed pages are free. Direct image URLs cost only the image fee. Use maxTotalImages, or a maximum cost per run, to cap spending; the actor stops cleanly when either limit is reached.
Limits
- Reads the HTML the server sends and does not run JavaScript. Images that only a script adds after load won't be found. For those pages, use a browser-based scraper first.
- External CSS files aren't fetched; only inline and
<style>backgrounds are found. - Duplicates are detected by exact file content. The same photo at two sizes, such as a 250 px and a 500 px thumbnail, counts as two images.
- No logins, cookies or CAPTCHA solving.
- You are responsible for having the right to use the images you download. Check each site's terms and the image licenses.
FAQ
Why did a page give me fewer images than I see in the browser? The likely causes:
- the images are added by JavaScript;
- they are smaller than
minWidth/minHeight; - they are duplicates;
- you hit
maxImagesPerPage.
The page row's imagesSkipped shows the counts for each reason.
Does it get the full-resolution image?
For srcset and <picture> it picks the largest candidate the page offers. It does not guess hidden original URLs.
Can I only get JPEGs from one site?
Yes. Set imageTypes: ["jpeg"] and sameDomainOnly: true, or use urlIncludeRegex.
Where is the ZIP?
The zipUrl in the OUTPUT record, which is also linked on the run's Storage tab.