# Image Batch Processor - Resize, Convert & Compress (`ntriqpro/image-batch-optimizer`) Actor

Process hundreds of images in one run: resize, compress and convert to WebP or AVIF automatically. Returns CDN-ready URLs and per-file size savings — a TinyPNG alternative for high-volume web and e-commerce pipelines.

- **URL**: https://apify.com/ntriqpro/image-batch-optimizer.md
- **Developed by:** [Daniel Carter](https://apify.com/ntriqpro) (community)
- **Categories:** Automation, Developer tools, AI
- **Features:** Limited permissions
- **Stats:** 8 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.20 / 1,000 image optimizeds

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

## Image Batch Optimizer

Optimize up to 50 images per run: convert formats (WebP/JPEG/PNG), resize, and compress.

| | Free plan (preview) | Paid Apify plan (Starter and up) |
|---|---|---|
| Images optimized per run | 5 (the first five URLs) | up to 50 |
| The other images | counted in a `free-plan-preview` row: how many were not processed, and an estimate (BRONZE price) of a paid run of the same input | optimized |
| Price | same events | same events, with plan discounts: BRONZE 20% off, SILVER 35% off, GOLD and up 48% off |

A free run ends as SUCCEEDED with a status message that says how many images were left out. Run the same input again on a paid plan for all of them.

### Features

- **Batch Processing**: Handle up to 50 images per run
- **Format Conversion**: Convert to WebP (recommended), JPEG, PNG, or keep original format
- **Resizing**: Resize images with customizable fit modes (inside, cover, contain, fill, outside)
- **Compression**: Adjust quality (1-100) for optimal file size vs visual quality tradeoff
- **Detailed Output**: Get original/optimized sizes, compression ratio, and final dimensions
- **Reliable**: A URL that fails gets its own row with the reason (`errorSide: "target"` with `reason` and `httpStatus` when the URL's side caused it, or `"service"` for our side), and the run continues with the remaining images
- **Pay Per Use**: $0.01 per optimized image; $0.002 for a URL whose host refuses it or that is not an image (see Pricing)

### Input

| Property | Type | Description | Example |
|----------|------|-------------|---------|
| `imageUrls` | Array\[String] | List of image URLs to optimize (max 50) | `["https://example.com/photo.png"]` |
| `outputFormat` | String | Target format: `webp`, `jpeg`, `png`, `original` | `"webp"` |
| `quality` | Integer | Compression quality (1-100) | `80` |
| `maxWidth` | Integer | Maximum width in pixels (0 = no resize) | `800` |
| `maxHeight` | Integer | Maximum height in pixels (0 = no resize) | `600` |
| `fit` | String | Resize fit mode: `inside`, `cover`, `contain`, `fill`, `outside` | `"inside"` |

### Output

Dataset contains one record per processed image:

```json
{
  "originalUrl": "https://example.com/photo.png",
  "outputUrl": "https://api.apify.com/v2/key-value-stores/.../photo.webp",
  "originalSize": 245600,
  "outputSize": 102340,
  "compressionRatio": "58.3%",
  "width": 800,
  "height": 600,
  "outputFormat": "webp",
  "disclaimer": "This tool optimizes images..."
}
```

### Pricing

| Event | Price (FREE tier list price) | When it is charged |
|---|---|---|
| `image-optimized` | $0.01 | once per optimized image row |
| `image-checked` | $0.002 | once per URL that was checked and failed on its own side: the host answered with an HTTP error, or the body is not an image Sharp can read (`rowType: "image-checked"`, `errorSide: "target"`, `reason`, `httpStatus`), or the URL given is not an http(s) address (`errorSide: "input"`, `reason: "invalid-url"`, not downloaded). Charged only once this event is on the live price list |

**Who is behind a failed URL.** When the URL's own host answers 401, 403, 404 or 410, the check is done and the answer is the host's: `errorSide: "target"` with `reason` (`login-required`, `forbidden`, `not-found`, `gone`) and `httpStatus`, charged as `image-checked`. When it answers 429, 503 or another temporary code, the Actor waits briefly and asks once more; the same kind of answer again is the host's own state: `reason: "temporarily-unavailable"` with the HTTP code, charged the same way. Our side is never charged: our time limit, a host that never answered, errors in our own processing (Sharp encode, storage) (`errorSide: "service"`).

If the platform restarts a run, the new run life reads the run's own dataset and the platform's charge counts: inputs already answered are not processed, delivered or charged again. If the dataset cannot be read back, the run stops without processing or charging anything more.

Not charged: rows with `errorSide: "service"` (network errors, our encode or storage errors), notice rows. Plan discounts: BRONZE 20%, SILVER 35%, GOLD and up 48%.

The run stops when its maximum charge is reached: no further image is processed, a `charge-limit-reached` notice row says how many were not processed, and the run ends as SUCCEEDED.

### Example

Input:

```json
{
  "imageUrls": ["https://images.unsplash.com/photo-1518791841217-8f162f1e1131?w=400"],
  "outputFormat": "webp",
  "quality": 80,
  "maxWidth": 600,
  "maxHeight": 600,
  "fit": "inside"
}
```

Result: PNG (280px, ~10KB) → WebP (280×280px, ~3KB), 70% compression, $0.01 charge.

### Disclaimer

This tool optimizes images using the open source Sharp library (Apache 2.0 license). Output quality depends on input image format and content. Original files are not modified. Processed images are stored temporarily in Apify Key-Value Store and may expire. Always verify output before use in production.

### Data Source

- **Image Processing**: Sharp (Apache 2.0) — https://sharp.pixelplumbing.com/

***

### 🔗 Related Actors by ntriqpro

Build your data pipeline with the ntriqpro Actor suite:

- [**alt-text-batch**](https://apify.com/ntriqpro/alt-text-batch) — Bulk Alt-Text Generator — SEO + WCAG
- [**image-upscale-mcp**](https://apify.com/ntriqpro/image-upscale-mcp) — AI Image Upscaler 2x/4x
- [**pdf-to-markdown**](https://apify.com/ntriqpro/pdf-to-markdown) — Office to Markdown — Document Extractor

### ⭐ Love it? Leave a Review

Your rating helps professionals discover this actor. [Rate it here](https://apify.com/ntriqpro/image-batch-optimizer/reviews).

# Actor input Schema

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

List of image URLs to optimize (max 50). Free plan: the first 5 images are optimized and the rest are counted in a free-plan-preview row; paid Apify plans process up to 50. Billing: image-optimized per optimized image, image-checked per URL that fails on its own side (the host answers 401/403/404/410, or 429/503 again after one retry, or the body is not an image). Our side (no answer from the host, our processing errors) is not charged.

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

Target image format

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

Compression quality. Higher = better quality, larger file.

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

Maximum output width in pixels. 0 keeps original.

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

Maximum output height in pixels. 0 keeps original.

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

How to fit the image within max dimensions

## Actor input object example

```json
{
  "imageUrls": [
    "https://images.unsplash.com/photo-1518791841217-8f162f1e1131?w=400"
  ],
  "outputFormat": "webp",
  "quality": 80,
  "maxWidth": 0,
  "maxHeight": 0,
  "fit": "inside"
}
```

# Actor output Schema

## `results` (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://images.unsplash.com/photo-1518791841217-8f162f1e1131?w=400"
    ],
    "outputFormat": "webp",
    "quality": 80,
    "maxWidth": 0,
    "maxHeight": 0,
    "fit": "inside"
};

// Run the Actor and wait for it to finish
const run = await client.actor("ntriqpro/image-batch-optimizer").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://images.unsplash.com/photo-1518791841217-8f162f1e1131?w=400"],
    "outputFormat": "webp",
    "quality": 80,
    "maxWidth": 0,
    "maxHeight": 0,
    "fit": "inside",
}

# Run the Actor and wait for it to finish
run = client.actor("ntriqpro/image-batch-optimizer").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://images.unsplash.com/photo-1518791841217-8f162f1e1131?w=400"
  ],
  "outputFormat": "webp",
  "quality": 80,
  "maxWidth": 0,
  "maxHeight": 0,
  "fit": "inside"
}' |
apify call ntriqpro/image-batch-optimizer --silent --output-dataset

```

## MCP server setup

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

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/5pFe4Taao91WnLpVr/builds/t05WdlRJ7NawV0uM2/openapi.json
