# Bulk Image Downloader: Crawl and ZIP (`getascraper/bulk-image-downloader`) Actor

Bulk image downloader for direct URLs and bounded website crawls. Use Quick ZIP, Website Inventory, or ML Dataset presets with filters, metadata, hashes, provenance, and explicit per-image errors. Pay only for stored images.

- **URL**: https://apify.com/getascraper/bulk-image-downloader.md
- **Developed by:** [GetAScraper](https://apify.com/getascraper) (community)
- **Categories:** Automation, Developer tools, Other
- **Stats:** 17 total users, 6 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.67 / 1,000 images

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## 🖼️ Bulk Image Downloader: Website Crawl, ZIP and Image Dataset

Download images from webpages or direct URLs with bounded crawling, ZIP output, source provenance, dimensions, hashes, and honest per-image errors. Pay-per-event billing is based on successfully stored images; failed downloads are reported and are not represented as successful image records.

This Actor is a generic image downloader for public URLs. Choose a preset: **Quick ZIP**, **Website Inventory**, or **ML Dataset**, then override only the controls you need. It discovers `<img>`, `<picture>`, `srcset`, Open Graph, Twitter Card, and lazy attributes, and can follow a bounded set of page links. Each attempted image has source/input correlation, status, provenance, retry information, and an error code when the source cannot be downloaded.

***

### 💡 What can you do with it?

- **You are building an AI training dataset.** Pull thousands of product photos, real estate shots, or stock images for CLIP, DINOv2, or SigLIP. Auto-hash for dedup means you never train on the same image twice.
- **You are a scraper developer.** Hand the Actor a list of image URLs returned by your catalog scraper (REI, IndiaMART, eBay, Poshmark) and get back a ZIP of the binaries plus a clean metadata dataset. One Actor replaces three.
- **You are an e-commerce operator.** Mirror product image catalogs. Detect when a competitor swaps an image. Track pricing-page visual changes over time.
- **You are an archivist or newsroom tool.** Grab every image from a story page in one call. Use the per-URL ZIP mode to keep sources separated.
- **You are a research analyst.** Pull the full visual corpus of any public site for content analysis, brand tracking, or visual trend reports.
- **You are a builder integrating via webhook.** The Actor POSTs a JSON summary on completion. Pipe the dataset URL into your BigQuery, Sheets, or n8n pipeline.

#### Store search terms

`bulk image downloader`, `website image scraper`, `download images from webpage`, `image URL extractor`, `image dataset builder`.

***

### 🚀 How to use it

1. **Open the Actor** in the Apify Store and click "Try for free".
2. **Paste your URLs.** Mix webpages (the Actor parses the HTML) and direct image links (it downloads straight) in a single list.
3. **Pick your options.** Turn on SHA-256 dedup, EXIF strip, format conversion, or ZIP output as needed.
4. **Click Start.** The Actor fetches each URL, discovers or downloads the images, and pushes metadata to the dataset and binaries to the key-value store.
5. **Download your results.** Pull the dataset as JSON, CSV, or Excel. Grab the image binaries from the key-value store (links in the dataset's `kv_url` column). Or use the single-click ZIP download.

***

### 📥 Input

| Field | Type | Required | Description |
| --- | --- | :---: | --- |
| `urls` | array | **Yes** | List of URLs. Each can be a webpage (HTML is parsed for images) or a direct image link. Mix freely. |
| `preset` | enum | No | `quickZip`, `websiteInventory`, or `mlDataset`. Explicit fields override the preset. |
| `mode` | enum | No | `auto` (recommended, detects by extension), `page` (force HTML parse), or `direct` (force image URL). |
| `includeSrcset` | boolean | No | Discover images from `srcset`, `picture>source`, and lazy `data-src`. Default `true`. |
| `includeOgTags` | boolean | No | Discover Open Graph and Twitter Card images. Default `true`. |
| `minWidth` | integer | No | Skip images narrower than this. Default 0. |
| `minHeight` | integer | No | Skip images shorter than this. Default 0. |
| `minSizeBytes` | integer | No | Skip images smaller than this. Filters tracking pixels. Default 0. |
| `maxImagesPerUrl` | integer | No | Cap images per source URL. Default 1000. |
| `maxUrls` | integer | No | Cap total URLs processed. Default 10000. |
| `crawlDepth` | integer | No | Link depth for bounded page crawling. `0` stays on supplied pages. |
| `maxPages` | integer | No | Hard page cap per supplied URL. |
| `urlGlobs` | array | No | Optional URL patterns allowed during page crawling. |
| `includeExtensions` | array | No | Optional image extension allow-list such as `jpg`, `png`, `webp`. |
| `includeMimeTypes` | array | No | Optional response MIME allow-list such as `image/jpeg`. |
| `maxSizeBytes` | integer | No | Optional upper bound for downloaded image bytes. |
| `dedupByHash` | boolean | No | Compute SHA-256 of each image body and skip duplicates. Default `true`. |
| `stripExif` | boolean | No | Re-encode JPEGs without EXIF metadata. Default `false`. |
| `convertFormat` | enum | No | `none`, `webp-to-png`, or `png-to-jpg`. Default `none`. |
| `filenamePattern` | string | No | Templated filename using `{slug}`, `{hash}`, `{ext}`, `{idx}`, `{source}`. Default `{slug}-{hash}.{ext}`. |
| `outputFormat` | array | No | `dataset` (always), `kv-store` (binaries), `zip` (single archive), `zipPerUrl` (one ZIP per source), `s3` (upload to bucket), `webhook` (POST summary on completion). |
| `s3Bucket` | string | No | Required when `outputFormat` includes `s3`. Uses standard `AWS_*` env vars for credentials. |
| `webhookUrl` | string | No | URL to receive a JSON run summary on completion. |
| `maxConcurrency` | integer | No | Max parallel image downloads. Default 10. |
| `downloadTimeoutMs` | integer | No | Per-image fetch timeout. Default 15000. |
| `imageCheckMaxRetries` | integer | No | Retries per failed image. Default 3. |
| `proxyConfiguration` | object | No | Optional proxy. Default off. Use residential if source sites are hotlink-protected. |
| `failFast` | boolean | No | Stop on first error. Default `false`. |
| `debugLogging` | boolean | No | Verbose per-image tracing. Default `false`. |

***

### 📤 Output

The Actor pushes one row to the dataset per downloaded image. Binaries are written to the default key-value store under `IMAGES/{filename}`. Use the dataset's `kv_url` column to download each binary.

```json
{
  "filename": "picsum-photos-800x600-a1b2c3d4e5f67890.jpg",
  "source_url": "https://example.com/gallery",
  "image_url": "https://picsum.photos/800/600.jpg",
  "kv_store_key": "IMG-picsum-photos-800x600-a1b2c3d4e5f67890.jpg",
  "kv_url": "https://api.apify.com/v2/key-value-stores/abc/records/IMG-picsum-photos-800x600-a1b2c3d4e5f67890.jpg",
  "content_type": "image/jpeg",
  "size_bytes": 54321,
  "width": 800,
  "height": 600,
  "format": "jpeg",
  "sha256": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
  "is_duplicate": false,
  "exif_stripped": false,
  "from_srcset": true,
  "from_picture_source": false,
  "from_og_tag": false,
  "from_twitter_tag": false,
  "from_data_attr": false,
  "from_direct_url": false,
  "downloaded_at": "2026-06-20T12:34:56.000Z",
  "duration_ms": 423,
  "http_status": 200,
  "status": "SUCCEEDED",
  "ok": true,
  "inputId": "catalog-home",
  "sourceUrl": "https://example.com/gallery",
  "retrievedAt": "2026-08-01T12:34:56.000Z",
  "crawl_depth": 0,
  "discovery_method": "srcset"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

### 🧪 Store examples

#### Quick ZIP

```json
{
  "preset": "quickZip",
  "urls": [{ "url": "https://example.com/gallery", "inputId": "gallery" }]
}
```

#### Website inventory

```json
{
  "preset": "websiteInventory",
  "urls": [{ "url": "https://example.com/catalog", "inputId": "catalog" }],
  "urlGlobs": ["https://example.com/catalog/*"],
  "includeExtensions": ["jpg", "png", "webp"]
}
```

#### Recurring ML dataset refresh

```json
{
  "preset": "mlDataset",
  "urls": [{ "url": "https://example.com/products", "inputId": "products" }],
  "crawlDepth": 1,
  "maxPages": 25,
  "dedupByHash": true
}
```

***

### 📋 Output data fields

| Field | Description |
| --- | --- |
| `filename` | Final filename (per `filenamePattern`). |
| `source_url` | The page URL the image was discovered on (or its direct URL). |
| `image_url` | Final resolved image URL (after srcset expansion, redirects). |
| `kv_store_key` | Key in the run's key-value store (`IMG-...`). |
| `kv_url` | Signed download URL for the binary (24-hour default). |
| `content_type` | MIME type (e.g. `image/jpeg`, `image/webp`). |
| `size_bytes` | Downloaded size. |
| `width` | Image width in pixels (from sharp metadata). |
| `height` | Image height in pixels (from sharp metadata). |
| `format` | Normalized format: `jpeg`, `png`, `webp`, `gif`, `svg`, `avif`, `bmp`, `ico`, `other`. |
| `sha256` | Content hash (when `dedupByHash=true`). |
| `is_duplicate` | True if hash matched a previously-seen image in this run. |
| `exif_stripped` | True if JPEG was re-encoded to remove EXIF. |
| `from_srcset` | True if discovered via `srcset` / `picture` / `data-srcset`. |
| `from_picture_source` | True if discovered via `<picture><source>`. |
| `from_og_tag` | True if discovered via `<meta og:image>`. |
| `from_twitter_tag` | True if discovered via `<meta twitter:image>`. |
| `from_data_attr` | True if discovered via lazy `data-src` / `data-srcset`. |
| `from_direct_url` | True if the URL was treated as a direct image (mode=direct/auto). |
| `downloaded_at` | ISO timestamp of the download. |
| `duration_ms` | Time to fetch + process. |
| `http_status` | HTTP response code when the image server returned one. |
| `error` | Per-image error string when the attempt failed; omitted on a successful row. |
| `status` / `ok` | Honest success state for the image attempt. Failed attempts include an `errorCode` and omit unavailable image fields. |
| `inputId` / `sourceUrl` / `retrievedAt` | Stable input correlation, canonical source page, and retrieval timestamp. |
| `finalUrl` / `retryCount` / `errorCode` | Redirect destination and retry/error evidence when available. |
| `alt` / `title` / `page_title` | Source HTML metadata when published by the page. |
| `crawl_depth` / `discovery_method` | Bounded crawl provenance. |

***

### 💰 Pricing

The local PPE configuration bills the `Stored image` event only after an image is successfully stored. Apify applies the account tier to the event price; the current Store tiers are:

| Volume | What you pay |
| :--- | :---: |
| Free tier | $0.89 per 1,000 stored images |
| Bronze | $0.82 per 1,000 stored images |
| Silver | $0.74 per 1,000 stored images |
| Gold and above | $0.67 per 1,000 stored images |

Billing is tied to the stored-image event, not to input pages or attempted links. There is no standby mode or separate scheduled-run price.

***

### ⭐ Enjoying Bulk Image Downloader?

<table width="100%">
<tr>
<td style="padding:20px 24px 14px;background:#EEF0FD;border:1px solid #EEF0FD;border-left:5px solid #4F46E5;border-radius:10px 10px 0 0">
<span style="font-size:20px;letter-spacing:4px">⭐ ⭐ ⭐ ⭐ ⭐</span><br>
<span style="font-size:17px;font-weight:800;color:#1C1917">Save hours of manually right-clicking and saving images one by one from any site.</span><br>
<span style="font-size:14px;color:#57534E">A 5-star rating takes 10 seconds and helps other AI dataset builders and e-commerce operators find it. Your feedback also tells us what to build next.</span>
</td>
</tr>
<tr>
<td style="padding:0;background:#4F46E5;border:1px solid #EEF0FD;border-top:none;border-radius:0 0 10px 10px;text-align:center">
<a href="https://apify.com/getascraper/bulk-image-downloader/reviews" style="display:block;padding:13px 16px;color:#FFFFFF;text-decoration:none;font-weight:800;font-size:15px;letter-spacing:0.3px">★&nbsp;&nbsp;Rate this Actor on Apify</a>
</td>
</tr>
</table>

***

### 🛠️ Tips and advanced options

- **Set `includeSrcset` to false** if you only want the page's primary images. This skips lazy `data-src` and responsive variants, which is faster on heavy pages.
- **Use `minSizeBytes` to filter tracking pixels.** A typical tracking pixel is under 1KB. Set `minSizeBytes: 2000` to skip them.
- **Use `minWidth` and `minHeight` to focus on useful images.** Set `minWidth: 400` to skip thumbnails and avatars.
- **Pick the right output mode.** `zip` for a single archive, `zipPerUrl` to keep source pages separated, `s3` to push directly to your training bucket.
- **Pair with a catalog scraper.** Run one of our catalog scrapers (REI, IndiaMART, eBay) first, then feed the image URLs to this Actor for a complete e-commerce dataset.
- **Schedule weekly runs** to refresh your image corpus. Most product catalogs update slowly; daily is overkill.
- **Use SHA-256 dedup within a run.** Hashes are stable for downstream reconciliation; cross-run history belongs in the dataset or an external state store.

***

### ❓ FAQ

**Is this Actor legal to use?**
The Actor downloads images that are publicly accessible. You are responsible for ensuring your use case complies with the source site's Terms of Service and applicable copyright laws. Do not use the Actor to bypass access controls, scrape private content, or violate copyright.

**Why does it work on any site?**
The Actor is generic. It fetches the URL you give it, parses the HTML for image tags, and downloads the images it finds. There is no per-site configuration.

**Does it execute JavaScript?**
No. Single-page apps that render images via React/Vue hydration will return an empty image list. If your target site is a SPA, use a Playwright-based scraper first to get the image URLs, then pass them to this Actor with `mode: 'direct'`.

**Do I need a proxy?**
No. Most public sites serve images to any client. Default `useApifyProxy: false` works perfectly. If your source site is hotlink-protected, set residential proxy as an opt-in via the `proxyConfiguration` field.

**What is the largest image it can handle?**
Sharp auto-streams, so peak memory is around 5x the size of the largest single image. A 50MB image is fine. A 500MB image may cause memory pressure on smaller container sizes.

**Does the EXIF strip work on PNG or WebP?**
No, EXIF strip is JPEG-only. PNG metadata stripping is a v2 feature.

**How is billing calculated?**
The `Stored image` PPE event is emitted only after the binary is successfully stored. Failed image attempts stay in the dataset with an error code and are not billed as successful image events.

**Can I get a single ZIP of all images?**
Yes. Set `outputFormat: ['dataset', 'kv-store', 'zip']`. The ZIP is written to `OUT-images.zip` and is also linked in the dataset summary.

**Can I push directly to S3?**
Yes. Set `outputFormat: ['dataset', 's3']`, fill in `s3Bucket`, and set `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_REGION` as Apify Secrets. Each image uploads to `s3://{bucket}/images/{filename}`.

**Can I get a webhook on completion?**
Yes. Set `outputFormat: ['dataset', 'webhook']` and fill in `webhookUrl`. The Actor POSTs a JSON summary with run stats (counts, errors, total size) to the URL when the run finishes.

***

### 🛡️ Disclaimers and support

- **Disclaimer**: This Actor retrieves publicly accessible images. Make sure your usage complies with the source site's terms of service and applicable copyright laws. The Actor is a generic utility and does not bypass authentication, paywalls, or access controls.
- **Support**: Open an issue from the [Issues tab](https://apify.com/actorstack/bulk-image-downloader/issues) for bug reports or feature requests. Custom scrapers and integration help are available on request.

### 🔗 Other actors

- [Google Lens OCR API: Sub-second Image to Text](https://apify.com/getascraper/google-lens-ocr) ↗ - extracts text from any image via Google Lens OCR.
- [Google Lens Search: Reverse Image Finder & OCR](https://apify.com/getascraper/google-lens-visual-search) ↗ - runs reverse image search and visual matches through Google Lens.
- [Loom Video Downloader: MP4, transcript and metadata in one run](https://apify.com/getascraper/loom-video-downloader) ↗ - downloads Loom videos as MP4 with transcript and metadata.
- [Streamable Video Downloader: Direct MP4 links in seconds](https://apify.com/getascraper/streamable-video-downloader) ↗ - resolves direct MP4 download links from Streamable.
- [Loom Transcript Scraper](https://apify.com/getascraper/loom-transcript-scraper) ↗ - pulls transcripts, captions, and metadata from public Loom videos.

# Actor input Schema

## `urls` (type: `array`):

List of URLs. Each can be a webpage (the Actor discovers all images on the page via HTML/srcset/og:image/twitter:image) or a direct image URL. Mixed lists allowed.

## `preset` (type: `string`):

Start with a focused configuration. Explicit fields override the preset.

## `mode` (type: `string`):

'auto' detects by URL extension, 'page' forces HTML parsing, 'direct' treats every URL as an image.

## `includeSrcset` (type: `boolean`):

Discover images from <img srcset>, <picture><source>, and lazy-loaded data-src/data-srcset attributes. Picks the highest-resolution variant by default.

## `includeOgTags` (type: `boolean`):

Discover Open Graph and Twitter Card images from page <meta> tags. Often the best cover image.

## `minWidth` (type: `integer`):

Skip images narrower than this. 0 = no minimum. Filters tracking pixels and thumbnails.

## `minHeight` (type: `integer`):

Skip images shorter than this. 0 = no minimum.

## `minSizeBytes` (type: `integer`):

Skip images smaller than this. Filters tracking pixels and 1x1 placeholders. 0 = no minimum.

## `maxImagesPerUrl` (type: `integer`):

Safety cap on images discovered per source URL. Prevents runaway runs on heavy pages.

## `maxUrls` (type: `integer`):

Cap on total URLs processed.

## `crawlDepth` (type: `integer`):

Follow page links up to this depth. 0 processes only the supplied pages.

## `maxPages` (type: `integer`):

Hard cap on fetched HTML pages per input URL.

## `urlGlobs` (type: `array`):

Optional URL patterns such as https://example.com/products/\* for bounded page crawling.

## `includeExtensions` (type: `array`):

Optional allow-list such as jpg, png, webp. Leave empty to keep all discovered image URLs.

## `includeMimeTypes` (type: `array`):

Optional allow-list such as image/jpeg or image/png. Applied after the response headers are known.

## `maxSizeBytes` (type: `integer`):

Optional upper bound for downloaded image bytes.

## `dedupByHash` (type: `boolean`):

Compute SHA-256 of each image body and skip duplicates. Reports is\_duplicate=true on the dataset.

## `stripExif` (type: `boolean`):

Re-encode JPEGs without EXIF (camera model, GPS, timestamps). Privacy-friendly. Slightly lossy.

## `convertFormat` (type: `string`):

Optional format conversion. webp-to-png is the most common (broader compatibility).

## `filenamePattern` (type: `string`):

Templated filename. Tokens: {slug} (sanitized URL slug), {hash} (SHA-256 prefix), {ext} (extension), {idx} (index), {source} (source domain).

## `outputFormat` (type: `array`):

Always emits the structured dataset. Optionally also: ZIP archive (single or per-URL), KV store binaries, S3 upload, or webhook on completion. Valid values: dataset, kv-store, zip, zipPerUrl, s3, webhook.

## `s3Bucket` (type: `string`):

Required when outputFormat includes 's3'. Use AWS\_ACCESS\_KEY\_ID, AWS\_SECRET\_ACCESS\_KEY, and AWS\_REGION env vars (set via Apify Secrets).

## `webhookUrl` (type: `string`):

POST a completion event with the run summary to this URL on run completion.

## `maxConcurrency` (type: `integer`):

Max parallel image downloads. Default 10.

## `downloadTimeoutMs` (type: `integer`):

Per-image fetch timeout in milliseconds.

## `imageCheckMaxRetries` (type: `integer`):

Retries for failed image downloads (5xx, timeouts, transient network errors).

## `proxyConfiguration` (type: `object`):

OPTIONAL. Default is no proxy. Set residential proxy if source sites are hotlink-protected or geo-fenced.

## `failFast` (type: `boolean`):

Stop the run on the first error. Default false (continue and report per-image errors).

## `debugLogging` (type: `boolean`):

Print per-image tracing tags (FETCH, PARSE, HASH, WRITE) to run logs.

## Actor input object example

```json
{
  "urls": [
    {
      "url": "https://apify.com"
    },
    {
      "url": "https://picsum.photos/800/600.jpg"
    }
  ],
  "mode": "auto",
  "includeSrcset": true,
  "includeOgTags": true,
  "minWidth": 0,
  "minHeight": 0,
  "minSizeBytes": 0,
  "maxImagesPerUrl": 1000,
  "maxUrls": 10000,
  "crawlDepth": 0,
  "maxPages": 1,
  "urlGlobs": [],
  "includeExtensions": [],
  "includeMimeTypes": [],
  "dedupByHash": true,
  "stripExif": false,
  "convertFormat": "none",
  "filenamePattern": "{slug}-{hash}.{ext}",
  "outputFormat": [
    "dataset",
    "kv-store"
  ],
  "s3Bucket": "",
  "webhookUrl": "",
  "maxConcurrency": 10,
  "downloadTimeoutMs": 15000,
  "imageCheckMaxRetries": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "failFast": false,
  "debugLogging": false
}
```

# Actor output Schema

## `results` (type: `string`):

One row per image with width, height, format, content hash, provenance (srcset/og:image/direct), and per-image error if any.

## `keyValueStore` (type: `string`):

Each image body stored under IMG-{filename}. Use kv\_url from each dataset row to download. 7-day default retention.

## `zip` (type: `string`):

All images packaged into a single ZIP. Keyed at OUT-images.zip.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        {
            "url": "https://apify.com"
        },
        {
            "url": "https://picsum.photos/800/600.jpg"
        }
    ],
    "includeSrcset": true,
    "includeOgTags": true,
    "minWidth": 0,
    "minHeight": 0,
    "minSizeBytes": 0,
    "maxImagesPerUrl": 1000,
    "maxUrls": 10000,
    "dedupByHash": true,
    "stripExif": false,
    "filenamePattern": "{slug}-{hash}.{ext}",
    "outputFormat": [
        "dataset",
        "kv-store"
    ],
    "s3Bucket": "",
    "webhookUrl": "",
    "maxConcurrency": 10,
    "downloadTimeoutMs": 15000,
    "imageCheckMaxRetries": 3,
    "proxyConfiguration": {
        "useApifyProxy": false
    },
    "failFast": false,
    "debugLogging": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("getascraper/bulk-image-downloader").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "urls": [
        { "url": "https://apify.com" },
        { "url": "https://picsum.photos/800/600.jpg" },
    ],
    "includeSrcset": True,
    "includeOgTags": True,
    "minWidth": 0,
    "minHeight": 0,
    "minSizeBytes": 0,
    "maxImagesPerUrl": 1000,
    "maxUrls": 10000,
    "dedupByHash": True,
    "stripExif": False,
    "filenamePattern": "{slug}-{hash}.{ext}",
    "outputFormat": [
        "dataset",
        "kv-store",
    ],
    "s3Bucket": "",
    "webhookUrl": "",
    "maxConcurrency": 10,
    "downloadTimeoutMs": 15000,
    "imageCheckMaxRetries": 3,
    "proxyConfiguration": { "useApifyProxy": False },
    "failFast": False,
    "debugLogging": False,
}

# Run the Actor and wait for it to finish
run = client.actor("getascraper/bulk-image-downloader").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    {
      "url": "https://apify.com"
    },
    {
      "url": "https://picsum.photos/800/600.jpg"
    }
  ],
  "includeSrcset": true,
  "includeOgTags": true,
  "minWidth": 0,
  "minHeight": 0,
  "minSizeBytes": 0,
  "maxImagesPerUrl": 1000,
  "maxUrls": 10000,
  "dedupByHash": true,
  "stripExif": false,
  "filenamePattern": "{slug}-{hash}.{ext}",
  "outputFormat": [
    "dataset",
    "kv-store"
  ],
  "s3Bucket": "",
  "webhookUrl": "",
  "maxConcurrency": 10,
  "downloadTimeoutMs": 15000,
  "imageCheckMaxRetries": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "failFast": false,
  "debugLogging": false
}' |
apify call getascraper/bulk-image-downloader --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=getascraper/bulk-image-downloader",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/qpjZ5Xslo6pNp4vMU/builds/J9UdYaBtf94FfcmZO/openapi.json
