# Bulk Image Format Converter (`automation-lab/bulk-image-format-converter`) Actor

Convert batches of public or uploaded images to JPEG, PNG, WebP, or AVIF and export converted files with dimensions, MIME types, byte sizes, and per-item status.

- **URL**: https://apify.com/automation-lab/bulk-image-format-converter.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 image converteds

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?

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 Format Converter

Bulk Image Format Converter is an **image format converter** for repeatable batches. Give it public direct image URLs, one file-picker upload, or binary files in an Apify key-value store; choose JPEG, PNG, WebP, or AVIF; and receive converted files plus a typed status record for every attempted image.

It runs the conversion inside your Actor run. No third-party conversion API receives the image bytes. Successful files are stored in the run's default key-value store, while the default dataset reports source/output MIME types, dimensions, byte sizes, settings, file links, errors, and timestamps.

### What can this image format converter do?

- Convert JPEG, PNG, WebP, and AVIF raster inputs.
- Produce JPEG/JPG, PNG, WebP, or AVIF output.
- Process mixed input formats in one ordered batch.
- Accept anonymous direct URLs and private key-value store files.
- Flatten transparency onto white when JPEG is requested.
- Preserve compatible metadata on request, or strip it by default.
- Continue after an individual download or conversion failure.
- Charge the per-image event only after a successful conversion.

This Actor changes formats; it does not discover images on webpages. Use [Web Image Downloader](https://apify.com/automation-lab/web-image-downloader) first when you need to find and download page assets. Use [Bulk Image Compressor](https://apify.com/automation-lab/bulk-image-compressor) when the primary job is resizing or targeting a smaller file size rather than choosing a delivery format.

### Who is it for?

**Developers** can call one conversion endpoint from scripts, CI jobs, or backend workflows without operating an image service.

**Content and ecommerce teams** can normalize product photos, article assets, thumbnails, and campaign files before upload to a CMS or CDN.

**Data pipeline operators** can schedule recurring batches, retain one metadata row per attempted input, and route successes and failures separately.

**Automation builders** can connect Actor output to Make, Zapier, n8n, webhooks, or another Actor.

### Why use it instead of a browser image format changer?

A browser tool is convenient for one manual file. This Actor is designed for automation:

1. Inputs and settings are JSON and can be versioned.
2. A run can process up to 500 supplied images.
3. Converted files remain available through Apify storage.
4. Every attempted input receives a machine-readable status record.
5. Failed images are reported without cancelling successful items in the same batch.
6. Runs can be scheduled, monitored, called by API, or composed into larger workflows.

The Actor does not claim to be a free external conversion website. Apify platform use and pay-per-event charges apply, but small test runs remain inexpensive.

### Getting started

1. Open the Actor input page.
2. Add one or more direct image URLs under **Image URLs**, or choose another source route.
3. Select **JPEG**, **PNG**, **WebP**, or **AVIF** under **Output format**.
4. Set quality for JPEG, WebP, or AVIF. PNG is lossless and ignores quality.
5. Keep **Preserve metadata** disabled unless your workflow needs compatible EXIF or ICC data.
6. Set **Maximum images** to bound the batch.
7. Start the run.
8. Download converted files from **Converted files** and inspect item metadata in **Conversion records**.

A minimal input is:

```json
{
  "imageUrls": [
    "https://raw.githubusercontent.com/lovell/sharp/main/test/fixtures/320x240.jpg"
  ],
  "outputFormat": "webp",
  "quality": 85,
  "maxItems": 1
}
```

### Input parameters

| Field | Type | Default | Purpose |
| --- | --- | --- | --- |
| `imageUrls` | string\[] | `[]` | Public direct HTTP(S) JPEG, PNG, WebP, or AVIF URLs. |
| `uploadedImage` | string | — | One image selected with Apify's file picker. |
| `sourceKeyValueStoreId` | string | default store | Store ID or name containing private binary source files. |
| `sourceKeys` | string\[] | `[]` | Exact binary record keys to read from the selected store. |
| `outputFormat` | enum | `webp` | `jpeg`, `png`, `webp`, or `avif`. |
| `quality` | integer | `85` | Quality from 1–100 for JPEG, WebP, and AVIF. |
| `preserveMetadata` | boolean | `false` | Preserve compatible metadata when possible. |
| `maxItems` | integer | `20` | Process at most 1–500 sources, in input order. |

At least one of `imageUrls`, `uploadedImage`, or `sourceKeys` is required. When several routes are supplied, the file-picker item is processed first, then URL items, then key-value store keys. `maxItems` applies across the combined list.

### Convert private or uploaded image files

For one file, use `uploadedImage` through the file-picker input editor.

For repeatable private batches:

1. Put each binary image in an Apify key-value store.
2. Pass the store ID or name as `sourceKeyValueStoreId`.
3. Pass the exact record keys as `sourceKeys`.
4. Ensure the Actor run has permission to read that store.

```json
{
  "sourceKeyValueStoreId": "my-private-image-store",
  "sourceKeys": ["catalog/front-photo", "catalog/back-photo"],
  "outputFormat": "avif",
  "quality": 75,
  "maxItems": 2
}
```

Do not place API tokens in image URLs. Query strings are retained in the dataset's `source` field and could expose secrets to anyone who can read the run dataset.

### Output fields

The default dataset contains one row for each attempted image, including failures.

| Field group | Fields |
| --- | --- |
| Source identity | `sourceType`, `source`, `sourceKey`, `sourceFileName` |
| Per-item result | `status`, `error`, `processedAt` |
| Source metadata | `sourceFormat`, `sourceMimeType`, `sourceWidth`, `sourceHeight`, `sourceBytes` |
| Output metadata | `outputFileName`, `outputFormat`, `outputMimeType`, `outputWidth`, `outputHeight`, `outputBytes` |
| Settings | `quality`, `metadataPreserved` |
| Stored file | `storedFileKey`, `storedFileUrl` |

A successful local JPG-to-WebP conversion produced:

```json
{
  "sourceType": "url",
  "source": "https://raw.githubusercontent.com/lovell/sharp/main/test/fixtures/320x240.jpg",
  "sourceKey": null,
  "status": "succeeded",
  "error": null,
  "sourceFileName": "320x240.jpg",
  "sourceFormat": "jpeg",
  "sourceMimeType": "image/jpeg",
  "sourceWidth": 320,
  "sourceHeight": 240,
  "sourceBytes": 81198,
  "outputFileName": "320x240-5190df4a3d.webp",
  "outputFormat": "webp",
  "outputMimeType": "image/webp",
  "outputWidth": 320,
  "outputHeight": 240,
  "outputBytes": 19868,
  "quality": 85,
  "metadataPreserved": false,
  "storedFileKey": "converted-001-320x240-5190df4a3d.webp",
  "storedFileUrl": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/converted-001-320x240-5190df4a3d.webp",
  "processedAt": "2026-01-15T12:00:00.000Z"
}
```

### How are converted files named and stored?

Each success is stored in the run's default key-value store with a key like:

```text
converted-001-original-name-5190df4a3d.webp
```

The index preserves processing order. The short digest comes from the source bytes and reduces name collisions. `storedFileUrl` points to the Apify API record. Private stores require normal Apify authentication when downloaded outside Console.

Failed items have null file fields and no converted binary record.

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

The Actor uses pay per event:

- one `start` event per run: **$0.00005**;
- one `item` event per successful conversion;
- no `item` charge for a failed image.

The current BRONZE item rate is **$0.004008 per successfully converted image**. Tier prices decrease for higher Apify account tiers.

At the BRONZE rate:

| Successful images | Estimated Actor charge |
| ---: | ---: |
| 1 | $0.004058 |
| 10 | $0.04013 |
| 100 | $0.40085 |

Examples include the one-time start event and exclude ordinary Apify compute/storage charges. The exact charge is visible on each run because failed inputs and account tier can change the total.

### Reliability, retries, and failure behavior

Downloads use a 30-second request timeout, at most five redirects, and up to three attempts for network errors, HTTP 429, and temporary server errors. Redirect destinations receive the same public-network safety checks as initial URLs.

The Actor does not blindly retry deterministic errors such as HTTP 400, 403, or 404. Those inputs receive `status: "failed"` and an `error` message. Per-image billing is not applied to them, and remaining batch inputs continue.

Invalid top-level input—such as no source, an unsupported output format, or an out-of-range limit—fails the run with a non-zero status instead of returning an ambiguous empty dataset.

### Limits and supported formats

- Input formats: JPEG, PNG, WebP, and AVIF raster images.
- Output formats: JPEG, PNG, WebP, and AVIF.
- Maximum file size: 25 MB per source.
- Maximum decoded dimensions: 40 million pixels per source.
- Maximum batch size: 500 supplied sources per run.
- Animated inputs are processed as a single image, not an animation.
- SVG, GIF, TIFF, HEIC/HEIF, PDF, video, and RAW camera formats are not supported.
- Output dimensions follow the source after orientation is applied; this Actor does not expose resizing.
- Converting to JPEG removes transparency by flattening onto white.
- Metadata preservation depends on compatibility between source data and target encoder.

For resize, target-size, or compression-specific controls, use [Bulk Image Compressor](https://apify.com/automation-lab/bulk-image-compressor).

### API usage

Use the synchronous dataset endpoint for small jobs that need metadata immediately, or the standard Actor run endpoint for asynchronous batches. Binary outputs remain in the run's key-value store rather than being embedded in dataset JSON.

#### Use from cURL

Set `APIFY_TOKEN` in your shell, then start a run and wait for completion:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~bulk-image-format-converter/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "imageUrls": [
      "https://raw.githubusercontent.com/lovell/sharp/main/test/fixtures/320x240.jpg"
    ],
    "outputFormat": "webp",
    "quality": 85,
    "maxItems": 1
  }'
```

The synchronous dataset endpoint returns metadata rows. Download binary files through each row's `storedFileUrl` with authentication when required.

#### Use from JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/bulk-image-format-converter').call({
  imageUrls: [
    'https://raw.githubusercontent.com/lovell/sharp/main/test/fixtures/320x240.jpg',
  ],
  outputFormat: 'avif',
  quality: 75,
  maxItems: 1,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].status, items[0].storedFileUrl);
```

#### Use from Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("automation-lab/bulk-image-format-converter").call(run_input={
    "imageUrls": [
        "https://raw.githubusercontent.com/github/explore/main/topics/nodejs/nodejs.png"
    ],
    "outputFormat": "jpeg",
    "quality": 90,
    "maxItems": 1,
})

items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items[0]["status"], items[0]["storedFileUrl"])
```

### Use with MCP and AI agents

Add this Actor to Claude Code through Apify MCP:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/bulk-image-format-converter"
```

**Claude Desktop**, **Cursor**, and **VS Code** MCP-capable extensions can use this equivalent JSON configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/bulk-image-format-converter"
    }
  }
}
```

- Claude Desktop: add the `apify` entry to the desktop MCP configuration.
- Cursor: add the same server URL in Cursor MCP settings.
- VS Code: add it through the MCP configuration used by your installed AI extension.

Example prompts:

- “Convert these three public product image URLs to WebP at quality 82 and return the output file links.”
- “Convert the binary records `hero`, `thumbnail`, and `social-card` in my image store to AVIF.”
- “Run the image converter and list only failed source URLs with their error reasons.”

### Integration patterns

**CMS preparation:** schedule a Task with new source URLs, convert assets to WebP, and pass successful `storedFileUrl` values to a publishing workflow.

**Dataset enrichment:** map image URLs from another Actor's dataset into `imageUrls`, then join conversion metadata back by `source`.

**Private asset pipeline:** write authorized files to a private key-value store, convert by key, and copy outputs to long-term storage before the run store expires.

**Quality assurance:** compare `sourceBytes` and `outputBytes`, verify MIME types, and reject unexpected failures before deployment.

**Webhook automation:** configure a run-finished webhook, fetch dataset rows, and continue only when expected items have `status: "succeeded"`.

### Legality

Use the Actor as a file-processing utility, not as a way to obtain protected media. Copyright, license, privacy, and contractual obligations remain with the user.

### Responsible use and security

Process only images you own or are authorized to transform. Respect copyright, source terms, retention requirements, and privacy obligations.

The direct URL route rejects localhost, private IPv4 ranges, link-local addresses, private IPv6 ranges, and redirect destinations that resolve to those networks. This limits server-side request forgery risk; it does not turn the Actor into an authorization bypass.

Metadata is stripped by default because EXIF can contain device, time, and location information. Enable preservation only when the workflow requires it and recipients are allowed to receive it.

Use key-value store inputs for private files. Avoid bearer tokens or signed credentials in source URLs because dataset rows retain source strings.

### Troubleshooting

**The URL returned “not an image.”** Use a direct binary image URL, not an HTML gallery or viewer page. Confirm its response has an image content type.

**The item failed with HTTP 403.** The source forbids automated or anonymous download. Put an authorized copy in an Apify key-value store and use `sourceKeys`; this Actor does not bypass access controls.

**A key-value store record was not found.** Verify the store ID/name, exact key, Actor permissions, and record retention. Keys are case-sensitive.

**The run failed before producing rows.** Check that at least one source was supplied and that `outputFormat`, `quality`, and `maxItems` satisfy the input schema.

**The PNG is larger than the source.** Format conversion does not guarantee compression. PNG is lossless and can be larger than JPEG, WebP, or AVIF for photographic content.

**The output has a white background.** JPEG cannot preserve transparency, so transparent pixels are flattened onto white. Choose PNG, WebP, or AVIF when transparency is required.

### Frequently asked questions

#### Does it resize images?

No. It preserves oriented dimensions. Use Bulk Image Compressor for resize and target-size controls.

#### Can it convert HEIC to JPG?

No. HEIC/HEIF is deliberately excluded from the supported input contract. Convert HEIC before this Actor or provide JPEG, PNG, WebP, or AVIF.

#### Are failed images charged?

The one-time start event still applies, but the per-image `item` event is charged only after a successful converted file is stored.

#### Can different items request different output formats?

Not in one run. `outputFormat` applies to the whole batch. Start separate runs for separate target formats.

#### How long are converted files kept?

They follow the retention and access rules of the run's default Apify key-value store. Copy files to your durable destination when long-term retention is required.

#### Is there a proxy option?

No. The Actor downloads anonymous public URLs directly and has a private key-value store fallback. It does not silently add residential proxy cost.

### Related Automation Lab Actors

- [Bulk Image Compressor](https://apify.com/automation-lab/bulk-image-compressor) — resize, compress, or target file sizes for supplied images.
- [Web Image Downloader](https://apify.com/automation-lab/web-image-downloader) — discover or download images from public webpages before conversion.
- [Website Image Extractor](https://apify.com/automation-lab/website-image-extractor) — extract structured image asset metadata from websites.

These tools can be composed: discover or download assets, convert them into the required delivery format, then compress or publish them in a downstream workflow.

# Actor input Schema

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

Publicly reachable direct HTTP(S) URLs of JPEG, PNG, WebP, or AVIF files. Each file may be up to 25 MB and 40 megapixels.

## `uploadedImage` (type: `string`):

Upload one image with Apify's file picker. For batches of private files, use a key-value store and sourceKeys.

## `sourceKeyValueStoreId` (type: `string`):

Optional Apify key-value store ID or name containing private input images. Leave empty to read sourceKeys from the run's default store.

## `sourceKeys` (type: `array`):

Binary image record keys in the selected key-value store. This is the private bulk-file route.

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

Requested format for every successfully converted file.

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

Encoder quality from 1 to 100 for JPEG, WebP, and AVIF. PNG uses lossless compression and ignores this value.

## `preserveMetadata` (type: `boolean`):

Keep compatible EXIF, ICC, and other metadata when possible. Disabled by default to avoid carrying private camera or location details.

## `maxItems` (type: `integer`):

Maximum number of supplied image sources processed in this run, in input order.

## Actor input object example

```json
{
  "imageUrls": [
    "https://raw.githubusercontent.com/lovell/sharp/main/test/fixtures/320x240.jpg"
  ],
  "sourceKeys": [],
  "outputFormat": "webp",
  "quality": 85,
  "preserveMetadata": false,
  "maxItems": 20
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing status and metadata for every attempted image.

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

Key-value store containing successfully converted image files.

# 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://raw.githubusercontent.com/lovell/sharp/main/test/fixtures/320x240.jpg"
    ],
    "outputFormat": "webp"
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/bulk-image-format-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://raw.githubusercontent.com/lovell/sharp/main/test/fixtures/320x240.jpg"],
    "outputFormat": "webp",
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/bulk-image-format-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://raw.githubusercontent.com/lovell/sharp/main/test/fixtures/320x240.jpg"
  ],
  "outputFormat": "webp"
}' |
apify call automation-lab/bulk-image-format-converter --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/bulk-image-format-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/RSQsf9AliNTtcR34X/builds/ApsqN1GulBcr3P4es/openapi.json
