# Bulk Image Resizer, Converter & Compressor (WebP, AVIF) (`oqen/image-resize-convert-compress`) Actor

Resize, convert and compress images in bulk from URLs: WebP, AVIF, JPEG (mozjpeg), PNG (quantised), GIF, TIFF. Responsive srcset sizes, smart crop, EXIF auto-rotate and GPS stripping, transparency kept, animated GIF to WebP, one ZIP download.

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

## Pricing

from $2.00 / 1,000 image outputs

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 Resizer, Converter & Compressor (WebP, AVIF)

Give it a list of image URLs; get back resized, converted and compressed files plus a table of before/after sizes. Built on **sharp / libvips**, the fastest open-source image library, with **mozjpeg**, **libwebp**, **libaom AVIF** and **libimagequant** PNG quantisation.

### Typical jobs

- Convert a product catalogue or a blog's images to **WebP or AVIF** (often 60–90% smaller)
- Generate **responsive `srcset` sizes** (320 / 640 / 1280 px) in one run
- Make square thumbnails with **smart crop** (`fit: cover`, which keeps the most interesting part of the image in frame)
- Strip **EXIF / GPS location** before publishing user-submitted photos
- Turn HEIC phone photos, TIFF scans or SVG logos into web formats
- Shrink animated GIFs by converting them to animated WebP

### What it gets right

- **EXIF orientation** is applied to the pixels, so photos never come out sideways, then the metadata is removed. The colour profile is kept so colours don't shift. Set `keepMetadata` if you need EXIF.
- **Transparency** is preserved for WebP, AVIF and PNG. For JPEG it is flattened onto your `background` colour, not black.
- **Never upscales** by default. In srcset mode, widths larger than the original are skipped instead of producing duplicates.
- Animated GIF/WebP stay animated when the output format supports it.
- Corrupt, truncated, non-image and over-limit files (50 MB, 100 megapixels) come back as clear `error` rows and **are not charged**.
- `largerThanOriginal` warns you when a conversion didn't pay off, e.g. an already tiny AVIF converted to WebP.

### Input example

```json
{ "images": [{ "url": "https://example.com/photo.jpg" }], "format": "avif", "widths": [320, 640, 1280], "quality": 75, "createZip": true }
```

### Output example

```json
{ "sourceUrl": "https://example.com/photo.jpg", "status": "ok", "outputKey": "0001-photo-640w.avif",
  "outputUrl": "https://api.apify.com/v2/key-value-stores/.../records/0001-photo-640w.avif",
  "format": "avif", "width": 640, "height": 427, "bytes": 9642, "originalFormat": "jpeg",
  "originalWidth": 1280, "originalHeight": 853, "originalBytes": 109586, "savedPercent": 91.2, "largerThanOriginal": false }
```

Download the files one by one from `outputUrl`, all at once from `images.zip`, or have your pipeline pull them from the key-value store via the API.

### Pricing

Pay per event: one `image-output` per output file. One image converted to three srcset widths is three events. Failed downloads and invalid images are free. Use `maxImages` and *Max cost per run* to cap spend.

# Actor input Schema

## `images` (type: `array`):

Direct links to JPEG, PNG, WebP, AVIF, HEIC, GIF, TIFF or SVG files (max 50 MB / 100 megapixels each).

## `imagesText` (type: `string`):

Whitespace- or newline-separated image URLs.

## `format` (type: `string`):

Target format. JPEG has no transparency, so transparent images are flattened onto the background colour.

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

Target width. Leave empty to keep the original or to scale by height only.

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

Target height. Leave empty to keep the aspect ratio from width.

## `widths` (type: `array`):

Optional, e.g. 320, 640, 1280. Produces one file per width (overrides width/height). Widths larger than the original are skipped unless enlargement is allowed.

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

How to fit when both width and height are set. Cover uses attention-based smart cropping.

## `withoutEnlargement` (type: `boolean`):

Keeps small images at their original size instead of blowing them up.

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

80 is visually lossless for most photos. AVIF quality is mapped so it looks like the same JPEG quality.

## `lossless` (type: `boolean`):

Lossless WebP/AVIF, and PNG without palette quantisation.

## `keepMetadata` (type: `boolean`):

Off by default: EXIF (including GPS location and camera serials) is removed, the colour profile is kept, and orientation is applied to the pixels.

## `background` (type: `string`):

Used when flattening transparency to JPEG and for 'contain' letterboxing.

## `stripAnimation` (type: `boolean`):

Animated GIF/WebP are kept animated when the output is WebP or GIF. Turn on to export only the first frame.

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

Bundles all outputs into images.zip in the key-value store.

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

Images processed at the same time.

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

Safety cap.

## `downloadTimeoutSecs` (type: `integer`):

Per image.

## Actor input object example

```json
{
  "images": [
    {
      "url": "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png"
    }
  ],
  "format": "webp",
  "fit": "inside",
  "withoutEnlargement": true,
  "quality": 80,
  "lossless": false,
  "keepMetadata": false,
  "background": "#ffffff",
  "stripAnimation": false,
  "createZip": false,
  "maxConcurrency": 4,
  "maxImages": 1000,
  "downloadTimeoutSecs": 60
}
```

# Actor output Schema

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

One item per output file: outputUrl, format, size, bytes, savings vs original; failed images have status=error.

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

All converted images (and images.zip if requested) in the key-value store.

# 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 = {
    "images": [
        {
            "url": "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("oqen/image-resize-convert-compress").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 = { "images": [{ "url": "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png" }] }

# Run the Actor and wait for it to finish
run = client.actor("oqen/image-resize-convert-compress").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 '{
  "images": [
    {
      "url": "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png"
    }
  ]
}' |
apify call oqen/image-resize-convert-compress --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,oqen/image-resize-convert-compress"
        }
    }
}
```

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/5eyM4NAIzCANTVKHR/builds/B0RbnVVhqr2QfrBhD/openapi.json
