# Bulk Image Downloader & Converter — ZIP, WebP, Resize (`masahishop/bulk-image-downloader`) Actor

Download images from image URLs or from web pages, convert to JPEG/PNG/WebP/AVIF, resize, skip duplicates and get one ZIP. Japanese/CJK file names stay readable. $2 per 1,000 images.

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

## Pricing

from $1.70 / 1,000 image saveds

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Bulk Image Downloader & Converter — ZIP, WebP, Resize

Download images in bulk from **image URLs** or from **web pages**, optionally **convert** them (JPEG, PNG, WebP, AVIF) and **resize** them, skip duplicates, and get everything as **one ZIP file**. **$2 per 1,000 images.**

- **Two kinds of input**: direct image URLs, or page URLs (the images on that page are found and downloaded)
- Finds **lazy-loaded images** (`data-src` and similar), picks the **largest `srcset` candidate**, and can include linked full-size images, `og:image`, CSS backgrounds and favicons
- **Convert** to JPEG / PNG / WebP / AVIF and **resize** to a maximum width/height (aspect ratio kept, never enlarged, EXIF rotation applied)
- **Filters**: minimum width/height and file size (skip icons and tracking pixels) — skipped images are **not charged**
- **Duplicates removed** by SHA-256 — duplicates are **not charged**
- **ZIP archive** of all images with the original file names. Japanese, Chinese and Korean file names stay readable (UTF-8 names, correct decoding of Shift_JIS / EUC-JP / GBK / Big5 pages)
- Each image also gets its own **download link**, plus size, dimensions, format, alt text and SHA-256

### What can it be used for?

- **Product images** from your own catalog or supplier URL lists, converted to WebP for your shop
- **Datasets** for machine learning or AI (with alt texts and hashes)
- **Website migrations and backups**: save all images of your pages in one ZIP
- **Thumbnails**: resize a list of images to a fixed maximum width
- **Image audits**: find oversized or broken images on your pages

### Input

| Field | Description |
|---|---|
| `urls` | Image URLs and/or page URLs. Only these URLs are read — links are not followed |
| `maxImages`, `maxImagesPerPage` | Caps to keep the cost predictable |
| `includeLinkedImages`, `includeMetaImages`, `includeBackgrounds`, `includeIcons` | What to take from pages |
| `minWidth`, `minHeight`, `minFileSizeKb`, `maxFileSizeMb`, `dedupe` | Filters |
| `outputFormat`, `maxWidth`, `maxHeight`, `quality` | Convert and resize |
| `createZip`, `zipMaxMb` | ZIP archive |
| `respectRobotsTxt`, `minDelayPerSiteMs`, `maxConcurrency`, `timeoutSecs` | Politeness and limits |

Example: all images on a page that are at least 300 px wide, as WebP with a maximum width of 1200 px:

```json
{
    "urls": ["https://en.wikipedia.org/wiki/Mount_Fuji"],
    "minWidth": 300,
    "outputFormat": "webp",
    "maxWidth": 1200
}
```

### Output

One dataset item per image:

```json
{
    "imageUrl": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/080103_hakkai_fuji.jpg/960px-080103_hakkai_fuji.jpg",
    "pageUrl": null,
    "alt": null,
    "foundIn": "input",
    "status": "saved",
    "fileName": "960px-080103_hakkai_fuji.webp",
    "key": "00007-960px-080103_hakkai_fuji.webp",
    "fileUrl": "https://api.apify.com/v2/key-value-stores/.../records/00007-960px-080103_hakkai_fuji.webp",
    "contentType": "image/webp",
    "format": "webp",
    "width": 800,
    "height": 536,
    "bytes": 61194,
    "originalWidth": 960,
    "originalHeight": 643,
    "originalBytes": 133195,
    "converted": true,
    "sha256": "f346558270df870c38f3b0df74ba7cfaab71113a8f56162f174d707adfa7b12f",
    "downloadedAt": "2026-10-06T11:35:25.436Z"
}
```

Images found on a page carry the page URL and the image's **alt text** (for example `"alt": "デジタル庁"` for the logo on the Japanese Digital Agency's home page).

- **images.zip** in the key-value store: all saved images in one file (Output tab → "ZIP archive")
- **SUMMARY** in the key-value store: counts of saved, duplicate, filtered, failed and robots.txt-blocked images
- Failed downloads are listed with `"status": "failed"` and the reason (e.g. `HTTP 404`) and are not charged

### Pricing

| Event | Price |
|---|---|
| Image saved | $0.002 ($2 per 1,000) |
| Web page scanned for images | $0.001 |

Only saved images are charged. Duplicates, filtered images, failed downloads and URLs disallowed by robots.txt are free. Converting, resizing and the ZIP file are included. Platform usage is included.

### Notes

- Only the URLs you provide are read. For a page URL, only the images of that page are downloaded; the Actor does not crawl other pages.
- robots.txt is respected by default and requests to the same site are spaced out.
- Download only images you are allowed to use. Most images on the web are protected by copyright; this tool does not grant any rights to them.
- Animated GIF/WebP stay animated when converted to WebP or GIF; other formats use the first frame.

# Actor input Schema

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

Direct image URLs are downloaded as they are. For a web page URL, the images on that page are found and downloaded (only that page is read; links are not followed).

## `maxImages` (type: `integer`):

The run stops after this many saved images (keeps the cost predictable).

## `maxImagesPerPage` (type: `integer`):

For page URLs: at most this many images are taken from one page.

## `includeLinkedImages` (type: `boolean`):

Also take images that the page links to (e.g. a thumbnail that links to the large photo).

## `includeMetaImages` (type: `boolean`):

The page's share image from its meta tags.

## `includeBackgrounds` (type: `boolean`):

Images set with style="background-image: url(...)".

## `includeIcons` (type: `boolean`):

Favicon and apple-touch-icon.

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

Skip smaller images (icons, spacers, tracking pixels). Skipped images are not charged.

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

Skip smaller images. Skipped images are not charged.

## `minFileSizeKb` (type: `integer`):

Skip smaller files. Skipped images are not charged.

## `maxFileSizeMb` (type: `integer`):

Larger files are not downloaded.

## `dedupe` (type: `boolean`):

Identical files (same SHA-256) are saved once. Duplicates are not charged.

## `outputFormat` (type: `string`):

Keep the original file, or convert every image to one format.

## `maxWidth` (type: `integer`):

Shrink larger images to fit (aspect ratio kept, never enlarged). 0 = no resizing.

## `maxHeight` (type: `integer`):

0 = no resizing.

## `quality` (type: `integer`):

Used only when converting or resizing.

## `createZip` (type: `boolean`):

All saved images in one images.zip (original file names, including Japanese/Chinese/Korean names). Free.

## `zipMaxMb` (type: `integer`):

Images beyond this size are still saved individually, just not added to the ZIP.

## `respectRobotsTxt` (type: `boolean`):

URLs that the site disallows for automated access are skipped (not charged).

## `minDelayPerSiteMs` (type: `integer`):

Spaces out requests to each host.

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

Downloads at the same time (across different sites).

## `timeoutSecs` (type: `integer`):

Maximum time for one download.

## Actor input object example

```json
{
  "urls": [
    "https://en.wikipedia.org/wiki/Mount_Fuji"
  ],
  "maxImages": 1000,
  "maxImagesPerPage": 200,
  "includeLinkedImages": true,
  "includeMetaImages": true,
  "includeBackgrounds": false,
  "includeIcons": false,
  "minWidth": 0,
  "minHeight": 0,
  "minFileSizeKb": 0,
  "maxFileSizeMb": 25,
  "dedupe": true,
  "outputFormat": "original",
  "maxWidth": 0,
  "maxHeight": 0,
  "quality": 82,
  "createZip": true,
  "zipMaxMb": 300,
  "respectRobotsTxt": true,
  "minDelayPerSiteMs": 250,
  "maxConcurrency": 8,
  "timeoutSecs": 30
}
```

# Actor output Schema

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

File link, size, dimensions, format and SHA-256 per image.

## `overview` (type: `string`):

Image, file name, size and status.

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

All saved images in one file (when "Create a ZIP archive" is on).

## `files` (type: `string`):

Every saved image as a record in the key-value store.

## `summary` (type: `string`):

Counts of saved, duplicate, filtered and failed images.

# 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": [
        "https://en.wikipedia.org/wiki/Mount_Fuji"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("masahishop/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": ["https://en.wikipedia.org/wiki/Mount_Fuji"] }

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

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).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": [
    "https://en.wikipedia.org/wiki/Mount_Fuji"
  ]
}' |
apify call masahishop/bulk-image-downloader --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,masahishop/bulk-image-downloader"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

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