Bulk Image Downloader - Download and Store Images · Apify
Bulk Image Downloader avatar

Bulk Image Downloader

Pricing

from $0.60 / 1,000 images

Go to Apify Store
Bulk Image Downloader

Bulk Image Downloader

Download images from URLs and store them in the key-value store with metadata including dimensions, file size, and SHA256 hash. Supports bulk input from URLs or from another Actor's dataset.

Pricing

from $0.60 / 1,000 images

Rating

0.0

(0)

Developer

Murat Uzun

Murat Uzun

Maintained by Community

Actor stats

0

Bookmarked

11

Total users

10

Monthly active users

19 hours ago

Last modified

Features

Limited permissions

Share

Bulk Image Downloader

Download images in bulk and store them in Apify's key-value store with metadata including dimensions, file size, and SHA256 hash. Paste direct image URLs, web page URLs (the Actor finds the images on the page), or read URLs from another Actor's dataset.

What is the Bulk Image Downloader?

The Bulk Image Downloader fetches images from a list of URLs (or from another Actor's dataset) and stores them in Apify's key-value store for persistent access. Each URL can be:

  • a direct image URL (.jpg, .png, .webp, …) — the image is downloaded as is;
  • a web page URL — the Actor reads the page and downloads the images on it: <img src>, the largest srcset candidate, lazy-loaded images (data-src, data-lazy-src, data-lazy, data-original), <picture><source srcset> and og:image. Relative URLs are resolved against the page, and each image URL is downloaded once.

For each downloaded image, the Actor stores:

  • Final URL after redirects
  • MIME type (content type)
  • File size in bytes
  • Image dimensions (width/height, parsed from PNG/JPEG/GIF/WebP headers)
  • SHA256 hash for deduplication or integrity checking
  • Public access URL
  • The page the image was found on

The Actor also optionally creates a ZIP file containing all downloaded images.

What data does the Bulk Image Downloader extract?

The Actor returns one dataset row per successfully downloaded image, with the following fields:

FieldTypeDescription
sourceUrlstringThe image URL: as given, or as found on the page
finalUrlstringThe final URL after following redirects
keystringThe key under which the image is stored in the key-value store
storedUrlstringPublic URL to access the stored image
contentTypestringMIME type of the image (e.g., image/jpeg, image/png)
bytesintegerFile size in bytes
widthintegerImage width in pixels (parsed from file header)
heightintegerImage height in pixels (parsed from file header)
sha256stringSHA256 hash of the image file
scrapedAtstringTimestamp of the download (ISO 8601 UTC)
sourcePagestring or nullThe web page the image was found on; null when you gave the image URL directly

Every run also writes an OUTPUT record to the key-value store: the number of images downloaded, pages scanned, and every skipped URL with its error code and reason. Skipped URLs are also in the ERRORS record. When no image could be downloaded, the run still succeeds, is not charged per image, and its status message says why (for example 2 URL(s) skipped: 1 HTTP 400, 1 not an image).

How to use the Bulk Image Downloader

Option 1: Download from image or page URLs

  1. Provide URLs: Enter one or more image or web page URLs, one per line (or separated by semicolons), e.g.:

    https://upload.wikimedia.org/wikipedia/commons/a/a9/Example.jpg
    https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png
    https://en.wikipedia.org/wiki/Cat
  2. Set the maximum number of images: Specify how many images to download (default: 50). The same limit applies to the images taken from any one page.

  3. Optionally create a ZIP: Enable createZip to also store all images as a single ZIP file.

Option 2: Download from another Actor's dataset

  1. Provide the dataset ID: Enter the ID of the dataset from a previous Actor run.

  2. Specify the URL field name: Enter the name of the field containing the image (or page) URLs (default: url).

  3. Configure download settings: Set max images, file size limit, and ZIP option as desired.

Example input

{
"imageUrls": [
"https://upload.wikimedia.org/wikipedia/commons/a/a9/Example.jpg",
"https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png",
"https://upload.wikimedia.org/wikipedia/commons/3/3a/Cat03.jpg"
],
"maxImages": 50,
"maxFileSizeMb": 20,
"timeoutSecs": 30,
"createZip": true
}

An empty input runs the same three Wikimedia images as a demo.

Example output

[
{
"sourceUrl": "https://upload.wikimedia.org/wikipedia/commons/a/a9/Example.jpg",
"finalUrl": "https://upload.wikimedia.org/wikipedia/commons/a/a9/Example.jpg",
"key": "a3f2b8c1d4e5f6a7.jpg",
"storedUrl": "https://api.apify.com/v2/key-value-stores/<store-id>/records/a3f2b8c1d4e5f6a7.jpg",
"contentType": "image/jpeg",
"bytes": 9022,
"width": 275,
"height": 297,
"sha256": "a3f2b8c1d4e5f6a7…",
"scrapedAt": "2026-11-12T14:30:00.000Z",
"sourcePage": null
}
]

For an image found on a web page, sourceUrl is the absolute image URL and sourcePage is the page URL you gave.

Example OUTPUT record when nothing could be downloaded:

{
"images": 0,
"pagesScanned": 1,
"rejectedCount": 2,
"reasons": { "HTTP 400": 1, "page without images": 1 },
"rejected": [
{ "sourceUrl": "https://site.example/photo.jpg", "sourcePage": null, "errorCode": "HTTP_ERROR", "httpStatus": 400, "error": "HTTP 400" },
{ "sourceUrl": "https://site.example/about", "sourcePage": null, "errorCode": "NO_IMAGES_ON_PAGE", "error": "The page has no <img>, srcset, lazy-load or og:image images" }
],
"stoppedEarly": false
}

Input parameters

  • imageUrls (array of strings, optional): Image or web page URLs, one per line (semicolons also work). Aliases: urls, url, startUrls. If you set it but no entry is an http(s):// URL (and there is no datasetId), the run fails with a clear message.
  • datasetId (string, optional): ID of another Actor's dataset to read URLs from. Use this instead of imageUrls.
  • urlField (string, default: url): When using datasetId, the name of the field containing the URL or URL list.
  • maxImages (integer, default: 50, max: 100000): Maximum number of images to download, in total and from any one page.
  • maxFileSizeMb (integer, default: 20, max: 1000): Skip images (and pages) larger than this size in megabytes.
  • timeoutSecs (integer, default: 30, range: 5–300): Timeout for each download in seconds.
  • createZip (boolean, default: false): Also create a ZIP file containing all downloaded images.

Error codes

Each skipped URL in the OUTPUT and ERRORS records has an errorCode and a readable error. Skipped URLs are never charged.

errorCodeMeaning
HTTP_ERRORThe server answered with a status other than 200 (httpStatus holds it, e.g. 400, 403, 404).
NOT_AN_IMAGEThe response was neither an image nor an HTML page (e.g. PDF, JSON), or an image URL found on a page returned something else.
NO_IMAGES_ON_PAGEThe URL is a web page, but it has no img, srcset, lazy-load or og:image image.
FILE_TOO_LARGEThe image or page is larger than maxFileSizeMb.
TIMEOUTThe download took longer than timeoutSecs.
NETWORK_ERRORDNS, TLS or connection failure.
STORE_FAILEDThe image could not be written to the key-value store.
PUSH_FAILEDThe dataset row could not be written (no charge).
DATASET_READ_FAILEDThe datasetId dataset could not be read.

Pricing

The Bulk Image Downloader costs $0.001 per image downloaded. A run with 50 images costs approximately $0.05.

Limitations

  • Charging: You pay only for images that are downloaded and saved as a dataset row. Pages, skipped URLs and failed saves are not charged.
  • File size filtering: Images larger than the maxFileSizeMb limit are skipped and not charged.
  • Timeout enforcement: Downloads exceeding the timeoutSecs limit are aborted. Near the run's own timeout the Actor stops downloading and still writes the ZIP, OUTPUT and ERRORS records.
  • Dimension parsing: Image width/height are parsed from the file header. For some rare image formats, dimensions may be unavailable (width/height will be null).
  • ZIP file size: The created ZIP file is stored in the key-value store under a single record. There is no practical size limit, but very large ZIPs may take time to generate.
  • Redirect handling: The Actor follows HTTP redirects (up to 20). Final URL reflects the ultimate source after all redirects.
  • Content-type validation: Only responses with MIME types starting with image/ are saved. An HTML response is scanned as a page; other content is skipped with NOT_AN_IMAGE.
  • Page mode: Pages are read without a browser, one level deep. Images added only by JavaScript after load and CSS background images are not found; links to other pages are not followed.

Using with AI agents and MCP

This Actor works with AI agents through the Apify MCP server. Agents can call it like:

{
"imageUrls": ["https://upload.wikimedia.org/wikipedia/commons/3/3a/Cat03.jpg", "https://en.wikipedia.org/wiki/Cat"],
"maxImages": 50,
"createZip": true
}

The Actor returns a dataset of stored images with public URLs ready for processing, analysis, or further download by other tools.

FAQ

Q: Can I download images from password-protected URLs? A: No, the Actor makes unauthenticated requests. It cannot access URLs behind login walls or authentication pages.

Q: What happens if an image URL returns a redirect? A: The Actor automatically follows redirects (up to 20 hops). The finalUrl field shows the ultimate source URL after all redirects.

Q: Can I download images from a different Actor's dataset? A: Yes. Provide the dataset ID and specify the field name containing image URLs. The Actor will read URLs from all items in that dataset.

Q: How are images deduplicated? A: Each image URL is downloaded once per run, even if it appears on several pages or twice in your list. The same file under different URLs is not merged, but the SHA256 hash in the output lets you identify such duplicates downstream.

Q: I pasted a web page URL. What happens? A: The Actor reads the page and downloads the images on it (img src, largest srcset, lazy-load attributes, og:image), up to maxImages. Each row's sourcePage shows the page. A page with no images is listed in the OUTPUT record with NO_IMAGES_ON_PAGE and is not charged.

Q: Why can't I download from Instagram or Facebook? A: These sites use bot-detection and require authenticated sessions. The Actor makes simple, unauthenticated requests and will not bypass bot checks.

Q: Is the ZIP file immediately available? A: Yes, the ZIP is created in the key-value store while the run finishes. You can access it via the key shown in the log output.

Q: What image formats are supported? A: The Actor downloads any image MIME type (JPEG, PNG, GIF, WebP, BMP, TIFF, SVG, etc.). Dimension parsing works for PNG, JPEG, GIF, and WebP.

Part of the webdatatools web-intelligence suite — every Actor is pay-per-event, reads public data without a login, and returns one clean row per entity:

Browse the whole suite at webdatatools, or call ten of these Actors straight from Claude, Cursor or Cline with the webdatatools MCP server.

Website & domain intelligence

Content for AI, LLMs and RAG

Search, video and social

Leads, jobs and company data

Developer, app and research data

Support

For issues, feature requests, or questions, visit the Actor's GitHub issues or community forums.