Bulk Image Downloader - Resize, Convert, ZIP, Dedupe
Pricing
from $4.50 / 1,000 image downloadeds
Bulk Image Downloader - Resize, Convert, ZIP, Dedupe
Download images in bulk from image links, web pages or an Apify dataset. Each file gets a public link, optional single ZIP, resize and convert to WebP, JPG or PNG, custom file names, SHA-256 dedupe and minimum size filter. Width, height, bytes and hash per image. Failed images are free.
Pricing
from $4.50 / 1,000 image downloadeds
Rating
0.0
(0)
Developer
Scrapewise Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
2
Monthly active users
8 days ago
Last modified
Categories
Share
Bulk Image Downloader
Bulk Image Downloader saves every image from a list of image links, from web pages or from an Apify dataset as real files: each one gets a public download link, and the whole run can come as one ZIP. On the way it can resize, convert to WebP, JPG or PNG, rename files by a pattern, skip duplicates by SHA-256 and drop images below a minimum size. Every row tells you the width, height, bytes, format and hash of the saved file. No login, no API key, no proxy setup.
You pay only for images that were saved. Failed downloads, duplicates, filtered-out images and web pages are free.
At a glance
- Three sources in one run: direct image links, web pages (all images in the HTML), and any Apify dataset with image links
- Files, not just links: each image in the key-value store with a public link, and optionally one
images.zipwith ametadata.csv - Resize and convert: maximum width and height, WebP / JPG / PNG, quality setting
- Clean output: file name pattern, SHA-256 dedupe, minimum width, height and file size, format filter
- Reads the real file: format and dimensions come from the bytes, not from the link (JPG, PNG, WebP, GIF, AVIF, HEIC, BMP, TIFF, ICO, SVG)
- Safe by default: size limit per file, private and local network addresses are refused
- Error rows: free, with an
errorCode
One real row
Default input, the second link (collected on 2026-10-03):
{"url": "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png","status": "downloaded","pageUrl": null,"fileUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/000002-PNG_transparency_demonstration_1.png?signature=<signature>","key": "000002-PNG_transparency_demonstration_1.png","fileName": "000002-PNG_transparency_demonstration_1.png","zipFile": null,"format": "png","contentType": "image/png","width": 800,"height": 600,"bytes": 224566,"hash": "c4e870d358d64ce677e958c156d0e3fba466993d8e915fc81c5dc64937a9b696","converted": false,"scrapedAt": "2026-10-03T13:20:17Z"}
An image found on a web page also carries pageUrl, the alt text and where it was found (foundIn: img, meta, background, poster, link).
Measured runs
Cloud runs on 2026-10-03, default memory (1 GB):
| Run | Result | Time |
|---|---|---|
| 240 image links, files + one ZIP | 230 saved (26 MB), 10 dead links listed as NOT_FOUND, free | 24 s |
| Dataset of a social media scraper (150 items, image field detected automatically), convert to JPG at 1,200 px, ZIP | 150 saved | 27 s |
Dataset of a product scraper, field images, minimum width 300 px, ZIP only | 300 saved, 17 duplicates skipped | 26 s |
| 2 web pages, minimum width 100 px, ZIP | 47 saved, 16 small images filtered out | 10 s |
| 5 large photos (5 to 660 MB) with the default 25 MB limit | 4 saved (41 MB), the 660 MB file refused in under a second | 11 s |
What you can do with it
- AI and computer-vision datasets: turn a list of links into same-format, same-size files with a hash per file and no duplicates.
- Product catalogs: point it at the dataset of your e-commerce scraper and get every product photo as WebP at 1,200 px, named your way.
- Website migration and backup: save every image of a list of pages before a redesign, with the page each one came from.
- Content and SEO audits: find oversized or broken images: the row has bytes, dimensions, format and an error code when the link is dead.
Input
| Field | What it does |
|---|---|
urls | Image links and web page links, mixed. A page is opened and all images in its HTML are downloaded |
datasetId | An Apify dataset of your account (pick it in the form or paste its ID); image links are taken from every item |
datasetFields | Fields that hold the links (images, product.imageUrl). Empty = detect automatically |
maxImages | Stop after this many saved images |
maxImagesPerPage | Image links taken from each page (default 500) |
createZip | One images.zip with all files and a metadata.csv |
saveToKeyValueStore | Each image as its own file with a public link (default on) |
fileNamePattern | {index}, {name}, {hash}, {host}, {page}, {width}, {height}, {ext}. Default {index}-{name}.{ext} |
convertTo | original, jpg, png or webp |
resizeMaxWidth, resizeMaxHeight | Shrink larger images, keeping the aspect ratio. Never enlarges |
quality | JPG / WebP quality, default 85 |
minWidth, minHeight, minFileSizeKB | Skip small images (icons, tracking pixels). Free |
maxFileSizeMB | Larger files are not downloaded (default 25, up to 200) |
formats | Keep only these real formats, e.g. jpg, png, webp |
dedupeByHash | Same file from different links is saved once (default on) |
urlMustMatch, urlMustNotMatch | Regex filters for image links found on pages or in the dataset |
includeMetaImages, includeBackgroundImages, includeLinkedImages | What counts as an image on a page: social preview, CSS background in style, full-size files linked from thumbnails |
maxConcurrency, downloadTimeoutSecs, proxyConfiguration | Advanced |
Download a list of image links as WebP thumbnails
{"urls": ["https://picsum.photos/id/237/1200/800","https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png","https://images.unsplash.com/photo-1506744038136-46273834b3fb?w=1600"],"convertTo": "webp","resizeMaxWidth": 512,"resizeMaxHeight": 512,"fileNamePattern": "{hash}.{ext}"}
Download all images from a web page to a ZIP
{"urls": ["https://books.toscrape.com/"],"createZip": true,"minWidth": 100,"fileNamePattern": "{page}-{index}.{ext}"}
Download the images of a dataset
{"datasetId": "<dataset ID of a finished run>","datasetFields": ["images"],"convertTo": "jpg","resizeMaxWidth": 1200,"createZip": true}
Output
One row per image link that was tried.
| Field | Description |
|---|---|
url | The source link |
status | downloaded, duplicate, filtered or failed |
fileUrl | Public link of the saved file in the key-value store |
fileName, key | Name of the file (also its key in the key-value store and its name inside the ZIP) |
zipFile | ZIP part that holds the file (images.zip, images-part-2.zip...) |
format, contentType | Real format of the saved file |
width, height, bytes | Of the saved file (after resize or conversion) |
hash | SHA-256 of the source file |
converted, originalFormat, originalWidth, originalHeight, originalBytes | When the file was resized or converted |
pageUrl, alt, foundIn | For images found on a web page |
sourceField | For images that came from a dataset |
finalUrl | When the link redirected |
animated, warning, extraMegabytes | Animated file; why a conversion was skipped; MB above the first 5 |
errorCode, error | Why the image was not saved (never charged) |
Where the files are: the Output tab has the links to the files and to images.zip; the Storage > Key-value store tab lists every file. The record SUMMARY has the totals of the run.
Error codes (never charged)
| errorCode | Meaning |
|---|---|
NOT_FOUND | The server answered 404 or 410 |
FORBIDDEN | The site refused the download even with a referer and a proxy |
HTTP_ERROR, TIMEOUT, DOWNLOAD_FAILED | The server failed or did not answer after retries |
NOT_AN_IMAGE, EMPTY_FILE | The link returned something that is not an image |
TOO_LARGE | Above maxFileSizeMB, or more than 160 megapixels |
TOO_SMALL, FORMAT_FILTERED | Removed by your filters (status: filtered) |
DUPLICATE | Same content as an image already saved in this run |
NO_IMAGES_FOUND | A page or dataset without image links |
INVALID_URL, HOST_NOT_FOUND, BLOCKED_HOST | Not an http(s) link, unknown host, or a private / local network address |
DATASET_NOT_FOUND | The dataset ID does not exist in your account |
NOT_REACHED | The run timeout or your maximum charge arrived; the list of pending links is in the record NOT_PROCESSED |
Pricing
Pay per event, no monthly fee, no start fee, and no Apify compute bill on top.
| Event | Free plan | Bronze | Silver | Gold and above |
|---|---|---|---|---|
| Image downloaded (per 1,000) | US$ 45 | US$ 6.50 | US$ 5.50 | US$ 4.50 |
| Extra MB of a large image | US$ 0.001 | US$ 0.001 | US$ 0.001 | US$ 0.001 |
- Resize, conversion, public link and ZIP are included in the image price.
- The image price covers source files up to 5 MB, which is almost every image on the web. Only larger files pay the extra MB: a 7.2 MB photo is 3 extra MB (US$ 0.003).
- Failed downloads, duplicates, filtered-out images, web pages and links that are not images are free.
- On the Apify Free plan a run saves up to 100 images.
How to use it from code, on a schedule and in integrations
- API:
POST https://api.apify.com/v2/acts/scrapewise~bulk-image-downloader/run-sync-get-dataset-items?token=<YOUR_TOKEN>with the input JSON returns the rows when the run ends. EachfileUrlis a direct download link. - After another Actor: add this Actor as an integration of your scraper and pass
{{resource.defaultDatasetId}}asdatasetId: every finished scrape gets its images downloaded. The Actor runs with limited permissions: it can read only the dataset you give it. - Schedule: save the input as a task and schedule it in the Apify Console.
- n8n, Make, Zapier: use the Apify app, run this Actor and read the dataset items.
FAQ
How do I download all images at once? Turn on createZip and open the ZIP link in the Output tab (also shown in the status message of the run).
How long are the files kept? As long as the run's storage is kept by your Apify plan (7 days for unnamed storages on most plans). Download the ZIP or copy the files before that.
Does it open pages with a browser? No. It reads the HTML the server sends, including lazy-load attributes, srcset (the largest version), social preview tags and inline CSS backgrounds. Images that only appear after JavaScript runs are not seen.
Which image is taken from srcset? The largest one.
Are my files public? The link works for anyone who has it, as with every Apify key-value store record. Nobody can list your store without your token.
Can it keep the folder structure? File names are flat. Use {page} or {host} in fileNamePattern to group files by source.
Limitations
- No JavaScript rendering and no crawling: only the pages you list are read, one level.
- Animated GIF/WebP and SVG are saved as they are (no resize or conversion). Images above 80 megapixels are saved without conversion.
- Files above 4 MB are downloaded one at a time to keep memory low. For files above 50 MB, raise
maxFileSizeMBand give the run 2 GB of memory or more. - Resized or converted files lose EXIF metadata (the orientation is applied first).
- Sites that block datacenter servers may answer
FORBIDDEN; choose a proxy inproxyConfigurationfor those. - Only download images you have the right to use. You are responsible for the copyright and the terms of the sources. This Actor reads public links only.
- Something broke? Open an issue on the Issues tab with the run ID; it is answered within hours.
Changelog
- 2026-10-03, 0.1: first release. Image links, web pages and datasets; key-value store files with public links; ZIP with metadata.csv; resize; WebP/JPG/PNG conversion; file name pattern; SHA-256 dedupe; size and format filters; free error rows.