# Bulk Image Converter & Resizer: WebP, JPG, PNG to ZIP (`chris_elder/bulk-image-converter`) Actor

Convert, resize and compress images in bulk: WebP, JPEG, PNG, AVIF. White-square product photo presets, target file size in KB, SKU file names from a CSV or dataset, one ZIP. Reads Bulk File Downloader results directly. $0.70 per 1,000 images; failed images are free.

- **URL**: https://apify.com/chris_elder/bulk-image-converter.md
- **Developed by:** [Chris Elder](https://apify.com/chris_elder) (community)
- **Categories:** E-commerce, Developer tools, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 converted images

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 Converter & Resizer: WebP, JPG, PNG to ZIP

**Bulk Image Converter & Resizer** converts, resizes and compresses hundreds of images in one run: JPG, PNG, WebP, AVIF, GIF, TIFF and SVG in; WebP, JPEG, PNG or AVIF out. Paste image links, a CSV or Google Sheet (such as a Shopify product export), or another Actor's dataset, and get every image back as a download link plus one ZIP, named by SKU if you like.

✅ **Pay per result: $0.70 per 1,000 images** · 🆓 **Failed images are never charged** · 🔑 No API key, no login, no third-party image service

[▶ Try it with one click](#how-to-use-it) · [📄 Real example output](#output-example-from-a-real-public-run) · [💲 Pricing](#how-much-does-it-cost-to-convert-images) · [🔌 API & integrations](#integrations-api-ai-agents-make-zapier) · [❓ FAQ](#faq) · [🛟 Support](#support-reliability-and-feature-requests)

### What does Bulk Image Converter & Resizer do?

- 🔄 **Convert formats**: WebP, JPEG, PNG or AVIF, or keep each image's own format and just compress it
- 📐 **Resize four ways**: fit inside a box, pad to an exact size, crop to fill, or stretch; small images are not enlarged unless you allow it
- 🛍️ **Product photo presets**: trim plain borders, centre the product with a 5% margin on a white 2048, 1600 or 1000 px square, saved as JPEG
- 🎯 **Target file size**: set a limit in KB and each image gets the highest quality that fits; every row says whether the target was met
- 🏷️ **SKU file names**: name files from a CSV column or dataset field (SKU, Handle) with a template such as `{sku}-{width}x{height}`
- 📦 **One ZIP**: every converted image in `images.zip`, plus a public link per image in the dataset
- 🔗 **Works after Bulk File Downloader**: paste its dataset ID (and key-value store ID) and the files it already saved are converted
- 🧹 **Clean output**: EXIF and GPS removed, phone photos auto-rotated, transparency put on white for JPEG

### Use cases

- **Shopify, eBay and Etsy sellers**: turn a product export into uniform white-square photos named by SKU, ready to upload
- **Web developers and SEO teams**: convert a site's images to WebP or AVIF at a set width and see the bytes saved per image
- **Agencies migrating stores**: download a catalogue with [Bulk File Downloader](https://apify.com/chris_elder/bulk-file-downloader), then resize and rename it here in one pass
- **Scraper users**: shrink the images from any scraper's dataset before storing them
- **Marketplace feeds**: keep every image under a size limit with the KB target

### How to use it

1. Click **Start**. The prefilled example converts 2 public images to WebP in a few seconds and costs about $0.0015.
2. Replace the example links with your own, or add a CSV/Google Sheet link, or a dataset ID from another run.
3. Pick a preset or set format, size, quality and target KB yourself. Anything you set overrides the preset.
4. Open the **Output** tab for a table with image previews, or download `images.zip` from the key-value store.

#### Input example

```json
{
  "imageUrls": [
    "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png",
    "https://upload.wikimedia.org/wikipedia/commons/a/a9/Example.jpg"
  ]
}
```

A Shopify export to 1600 px white squares named by handle:

```json
{
  "csvUrl": "https://api.apify.com/v2/key-value-stores/b4gAQBUYH6cUo2aUC/records/shopify-products-sample.csv",
  "nameField": "Handle",
  "preset": "square-1600-white",
  "fileNameTemplate": "{sku}"
}
```

Other options: `datasetId`, `keyValueStoreId`, `urlField`, `outputFormat`, `quality`, `targetKb`, `width`, `height`, `fit`, `allowUpscale`, `backgroundColor`, `trim`, `marginPercent`, `stripMetadata`, `autoRotate`, `createZip`, `maxImages`, `maxInputMb`, `maxConcurrency`.

#### Output example (from a real public run)

```json
{
  "index": 0,
  "sourceUrl": "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png",
  "ok": true,
  "fileName": "PNG_transparency_demonstration_1.webp",
  "key": "img-00001-PNG_transparency_demonstration_1.webp",
  "url": "https://api.apify.com/v2/key-value-stores/Dm1WMrlPZvA4r6loI/records/img-00001-PNG_transparency_demonstration_1.webp",
  "format": "webp",
  "width": 800,
  "height": 600,
  "bytes": 69056,
  "originalFormat": "png",
  "originalWidth": 800,
  "originalHeight": 600,
  "originalBytes": 224566,
  "savedPercent": 69.2,
  "quality": 80
}
```

Public example run: [dataset as JSON](https://api.apify.com/v2/datasets/IQBghztLduG8qSAMd/items?format=json\&clean=1) · [CSV](https://api.apify.com/v2/datasets/IQBghztLduG8qSAMd/items?format=csv\&clean=1) · [images.zip](https://api.apify.com/v2/key-value-stores/Dm1WMrlPZvA4r6loI/records/images.zip)

| Field | Meaning |
|---|---|
| `ok` | `true` if the image was converted (and charged), `false` for a free error row |
| `fileName`, `url` | Output file name and its public download link |
| `format`, `width`, `height`, `bytes` | The converted image |
| `originalFormat`, `originalWidth`, `originalHeight`, `originalBytes` | The source image |
| `savedPercent` | Size saved versus the original (negative when an image was enlarged) |
| `quality`, `targetKb`, `targetMet` | Encoder quality used and whether the KB target was reached |
| `sku` | Name from your CSV column or dataset field, when given |
| `error`, `errorCode` | Why an image failed (not charged) |

The run's `OUTPUT` record has totals (converted, failed, MB in and out) and the ZIP link(s).

### How much does it cost to convert images?

| Event | Price |
|---|---|
| Converted image | $0.0007 ($0.70 per 1,000) |
| Actor start | $0.00005 per GB of memory, once per run (default 1 GB) |

| Job | Arithmetic | Cost |
|---|---|---|
| One-click example (2 images) | 2 x $0.0007 + $0.00005 | about $0.0015 |
| 500 product photos to white squares | 500 x $0.0007 + $0.00005 | about $0.35 |
| 5,000 site images to WebP | 5,000 x $0.0007 + $0.00005 | about $3.50 |
| 5,000 images with a KB target and SKU names | same: options are free | about $3.50 |

Never charged: links that fail to download, files that are not images, images over the size limit, duplicates and rows without a link. Set **Max cost per run** in the run options to cap spending.

### Integrations (API, AI agents, Make, Zapier)

```bash
curl -X POST "https://api.apify.com/v2/acts/chris_elder~bulk-image-converter/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"imageUrls":["https://httpbin.org/image/jpeg"],"outputFormat":"webp","width":800}'
```

Python (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor("chris_elder/bulk-image-converter").call(run_input={
    "imageUrls": ["https://httpbin.org/image/jpeg"],
    "preset": "square-1600-white",
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(row["ok"], row.get("fileName"), row.get("url"))
zip_url = f"https://api.apify.com/v2/key-value-stores/{run['defaultKeyValueStoreId']}/records/images.zip"
```

MCP (AI agents): `https://mcp.apify.com/?tools=chris_elder/bulk-image-converter`

Make / Zapier / n8n: use the Apify **Run Actor** module with `chris_elder/bulk-image-converter`, pass image links in `imageUrls` or the previous run's dataset ID in `datasetId`, then read the dataset rows or fetch `images.zip`. Schedules and webhooks work as with any Actor.

### Limits and good to know

- Animated GIFs are converted from their first frame.
- SVG files are rendered to pixels: at their own size by default, or sharply at the width or height you set.
- Images over 30 MB are skipped for free (raise `maxInputMb` up to 100).
- Sites that block automated downloads may fail; those rows are free. Downloading with Bulk File Downloader first and passing its key-value store avoids downloading twice.
- Trim removes plain borders only; it is not background removal.
- A KB target can't always be met for very large images; the row then says `targetMet: false` and keeps the smallest version.

### Is it legal?

The Actor downloads only the public image links you give it, or reads the datasets and stores you pass in, and changes the files for you. It does not log in anywhere. You are responsible for having the right to use and modify the images. See Apify's post on [whether web scraping is legal](https://blog.apify.com/is-web-scraping-legal/).

### FAQ

**Can I convert a Shopify product export?** Yes. Pass the CSV or Google Sheet link as `csvUrl`; the `Image Src` column is found automatically. Set `nameField` to `Handle` or your SKU column for file names.

**How do I make every product photo a white square?** Choose a `square-...-white` preset. It trims plain borders, centres the product with a 5% margin and pads it to an exact square on white.

**How do I get every image under 200 KB?** Set `targetKb` to 200. Each image gets the highest quality that fits, and `targetMet` tells you if one could not.

**Does it work with the results of Bulk File Downloader?** Yes. Paste its dataset ID. Add its key-value store ID too and the saved files are used directly.

**Is PNG output lossless?** Yes, unless you set a KB target, which switches PNG to palette compression.

### Support, reliability and feature requests

- Failed images are free.
- Every release is tested on real public images; the one-click example works.
- Issues answered within 2 business days via the Actor **Issues** tab.
- Breaking input or price changes are announced in this README first.

Built by GPT Shop Ltd with AI-assisted development; every release is reviewed and tested.

### More tools from GPT Shop Ltd

[Bulk Image & File Downloader](https://apify.com/chris_elder/bulk-file-downloader) · [AI Image Upscaler](https://apify.com/chris_elder/ai-image-upscaler) · [Image to Text OCR](https://apify.com/chris_elder/image-to-text-ocr) · [Bulk Website Screenshot](https://apify.com/chris_elder/bulk-website-screenshot) · [Dataset Transformer](https://apify.com/chris_elder/dataset-transformer) · [all tools](https://apify.com/chris_elder)

### Done-for-you

Need this run for you or customised? Done-for-you data from £49: https://tools.gptshopltd.com/done-for-you-scraper/

# Actor input Schema

## `imageUrls` (type: `array`):

Links to images (JPG, PNG, WebP, AVIF, GIF, TIFF, SVG). One per line. Each converted image costs one event; failed images are free.

## `csvUrl` (type: `string`):

A public CSV/TSV/text file or a Google Sheet shared as "Anyone with the link can view". The image column is found automatically (for example a Shopify export's "Image Src"), or set it below.

## `datasetId` (type: `string`):

Convert the images from another Actor's results: paste the dataset ID from the run's Storage tab. Read-only access to this one dataset is requested. Bulk File Downloader results are recognised automatically; failed rows are skipped.

## `keyValueStoreId` (type: `string`):

With a Bulk File Downloader dataset, also paste that run's key-value store ID to convert the files it already saved instead of downloading them again. Read-only access to this one store is requested.

## `urlField` (type: `string`):

Dataset field (dotted paths like images.0 work, arrays of links are expanded) or CSV column holding the image links. Left empty, it is detected.

## `nameField` (type: `string`):

Dataset field or CSV column used to name each output file, for example SKU or Handle. Repeats get -2, -3.

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

Ready-made settings. Any option you set below overrides the preset. Square presets trim plain borders, centre the product with a 5% margin and pad it onto a white square.

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

"Same as input" keeps JPEG/PNG/WebP/AVIF and turns other formats into JPEG (or PNG when transparent). JPEG output puts transparent areas on the background colour. Default WebP (or the preset's format).

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

Encoder quality for JPEG, WebP and AVIF. Default 80 (85 on product presets). PNG is lossless unless a target size is set.

## `targetKb` (type: `integer`):

Highest quality that fits under this size is picked per image. Each row reports targetMet. No extra cost.

## `width` (type: `integer`):

Target width. Leave empty to keep the aspect ratio from the height, or keep the original size.

## `height` (type: `integer`):

Target height.

## `fit` (type: `string`):

inside: fit within the box, keep ratio. contain: fit and pad to the exact box with the background colour. cover: fill the box and crop. fill: stretch.

## `allowUpscale` (type: `boolean`):

Off: images smaller than the target are not enlarged (pad mode still pads to the exact size). Product presets turn this on.

## `backgroundColor` (type: `string`):

Hex colour for padding and for transparent areas in JPEG output. Default #ffffff.

## `trim` (type: `boolean`):

Remove plain borders around the subject before resizing. On for product presets.

## `marginPercent` (type: `integer`):

Empty space on each side in pad mode, as a percent of the canvas. Product presets use 5.

## `stripMetadata` (type: `boolean`):

Removes camera and location data and makes files smaller. Default on.

## `autoRotate` (type: `boolean`):

Rotate phone photos upright using their EXIF orientation. Default on.

## `fileNameTemplate` (type: `string`):

Tokens: {name} (original file name or the name/SKU field), {sku}, {index}, {width}, {height}. Example: {sku}-{width}x{height}. The extension is added for you.

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

Saves images.zip (split into parts for very large runs) in the key-value store. Free.

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

Stop after this many images (1 to 10,000). Use Apify's Max cost per run as a spending cap too.

## `maxInputMb` (type: `integer`):

Larger images are skipped and not charged.

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

How many images are processed at once (1 to 8).

## Actor input object example

```json
{
  "imageUrls": [
    "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png",
    "https://upload.wikimedia.org/wikipedia/commons/a/a9/Example.jpg"
  ],
  "preset": "none",
  "stripMetadata": true,
  "autoRotate": true,
  "fileNameTemplate": "{name}",
  "createZip": true,
  "maxImages": 100,
  "maxInputMb": 30,
  "maxConcurrency": 4
}
```

# Actor output Schema

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

No description

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

No description

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

No description

# 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 = {
    "imageUrls": [
        "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png",
        "https://upload.wikimedia.org/wikipedia/commons/a/a9/Example.jpg"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("chris_elder/bulk-image-converter").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 = { "imageUrls": [
        "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png",
        "https://upload.wikimedia.org/wikipedia/commons/a/a9/Example.jpg",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("chris_elder/bulk-image-converter").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 '{
  "imageUrls": [
    "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png",
    "https://upload.wikimedia.org/wikipedia/commons/a/a9/Example.jpg"
  ]
}' |
apify call chris_elder/bulk-image-converter --silent --output-dataset

```

## MCP server setup

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

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/VJ5VEb8afne4sCBZZ/builds/LhK61PhnFbjvfUh0a/openapi.json
