# Bulk Image Resizer: Resize, Crop, Convert & Compress (`bossless/bulk-image-resizer`) Actor

Resize, crop, pad, convert and compress images in bulk: several sizes per image, Amazon/Shopify/Etsy/Instagram/YouTube/favicon presets, max file size in KB, JPEG/PNG/WebP/AVIF output, HEIC input, smart crop, EXIF strip. Links, Drive, Dropbox, uploads; ZIP. Pay per image.

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

## Pricing

from $1.50 / 1,000 image files

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 Resizer: Resize, Crop, Convert & Compress Images in Bulk

**Resize hundreds of images in one run:** several sizes per image (thumbnail + web + retina), ready-made sizes for
Amazon, Shopify, Etsy, eBay, Instagram, YouTube and favicons, a maximum file size in KB, and JPEG, PNG, WebP or AVIF
output. iPhone HEIC photos are read too. Paste links (or Google Drive / Dropbox share links), upload files, or chain it
after any scraper. Every file lands in the run's key-value store with a public link, plus one `images.zip`.

- 📐 **Several sizes per image:** `thumb=300x300:cover`, `web=1200`, `retina=2400`, `50%`... one file per size.
- 🛒 **Marketplace and social presets:** Amazon 2000×2000, Shopify 2048×2048, Etsy 3000×2250, eBay 1600×1600 (white padding), Instagram square / portrait / story, YouTube thumbnail, Open Graph share image, responsive web `srcset`, favicon set.
- 🗜️ **Max file size target:** quality is lowered step by step, then the picture is made smaller, until each file fits (for example under 100 KB). Each record says whether the target was met.
- ✂️ **Fit modes:** contain, cover (crop with centre, top, bottom, left, right or **smart** detail-aware position), pad with any colour (exact box), stretch. Never enlarges unless you allow it.
- 🔄 **Formats:** JPEG (progressive), PNG, WebP, AVIF out; JPEG, PNG, WebP, AVIF, **HEIC/HEIF**, GIF, TIFF, BMP in.
- 🎨 **Colour-correct:** photos are turned upright by their EXIF orientation; wide-gamut photos (iPhone Display P3) are converted to sRGB before metadata is stripped, so colours don't shift. Or keep EXIF and the colour profile.
- 📦 **Output:** public links per file, `images.zip` with everything, and one dataset row per image.

### What can you do with it?

- **E-commerce:** turn supplier photos into exact marketplace sizes on a white background (Amazon, Shopify, Etsy, eBay).
- **Websites:** make `srcset` sets (480/960/1600/2400 px WebP) or thumbnails + full-size images, and shrink them under a KB limit for page speed.
- **Social media:** crop photos to Instagram square, portrait or story, YouTube thumbnails (under 2 MB) and link previews (1200×630).
- **iPhone photos:** convert HEIC to JPEG or WebP in bulk.
- **Pipelines and AI agents:** chain after a product, Instagram or Google Maps scraper with `datasetId`, or call it from an agent through MCP.

### Which files and links does it accept?

| Input | Example | Notes |
|---|---|---|
| Direct image link | `https://example.com/photos/shoe.jpg` | JPG, PNG, WebP, AVIF, HEIC/HEIF, GIF, TIFF, BMP |
| Google Drive file | `https://drive.google.com/file/d/.../view` | shared as "Anyone with the link" |
| Dropbox file | `https://www.dropbox.com/s/.../photo.png?dl=0` | public share link |
| Uploaded file | "Or upload images" field in the Console | stored in your key-value store |
| Apify dataset | `datasetId` + `datasetField` (e.g. `images[*].url`) | chain after any scraper |

Folders and pages that need a login are not supported: link the files themselves. Animated GIF/WebP: the first frame is used. Up to 50 MB per file.

### How much does it cost?

You pay per **output image file**. One image resized to 3 sizes = 3 files. Dead links, private files and unreadable
files are never charged.

| Event | Free / Bronze | Silver | Gold / Platinum / Diamond |
|---|---|---|---|
| **Image file (`image`)** | **$0.0025** | **$0.002** | **$0.0015** |
| Actor start (`apify-actor-start`) | $0.00005 / run | $0.00005 / run | $0.00005 / run |

Examples: 1,000 product photos to one Amazon size = 1,000 files = $2.50 (down to $1.50). 100 photos × 3 web sizes =
300 files = $0.75. Set `maxImages` or a maximum cost per run to cap the spend.

### How fast is it?

Measured on Apify at the default 1 GB of memory, with 12–18 megapixel camera photos (4080×3072 and 5184×3456 JPEG):

| Job | 10 photos | Per photo |
|---|---|---|
| One 1200 px WebP each | 7.6 s run | under 1 s |
| Three sizes each (300 cover, 1200, 2400 WebP) | 20 s run | ~2 s |
| Amazon 2000×2000 JPEG on white | 6.9 s run | under 1 s |
| 1600 px WebP under 100 KB (quality search) | 12 s run | ~1 s |

Downloads run four at a time while the previous photo is processed. At the default 1 GB an image can have up to
52 megapixels (32 with transparency); a bigger one is skipped uncharged with a "run with more memory" note. Each
extra GB allows ~85 megapixels more, up to 178 megapixels. All sizes of one image together may add up to twice that.

### Presets

| Preset | Output | Fit |
|---|---|---|
| `amazon` | 2000×2000 JPEG q90 | pad, white |
| `shopify` | 2048×2048 JPEG q85 | pad, white |
| `etsy` | 3000×2250 JPEG q90 | pad, white |
| `ebay` | 1600×1600 JPEG q90 | pad, white |
| `instagram-square` | 1080×1080 JPEG q90 | cover, smart crop |
| `instagram-portrait` | 1080×1350 JPEG q90 | cover, smart crop |
| `instagram-story` | 1080×1920 JPEG q90 | cover, smart crop |
| `youtube-thumbnail` | 1280×720 JPEG q90, under 2 MB | cover, smart crop |
| `social-share` | 1200×630 JPEG q85 (Open Graph, X, LinkedIn) | cover, smart crop |
| `web-responsive` | 480, 960, 1600, 2400 px wide WebP q80 | contain, never enlarged |
| `favicon` | favicon.ico (16/32/48) + 180, 192, 512 px PNG | pad, transparent |

Marketplace and social presets enlarge small images so the box is always exact. A preset replaces the sizes, fit,
format, quality and background fields; "Strip metadata" and "ZIP" still apply.

### Input

| Field | Default | Description |
|---|---|---|
| `images` | | Image links, one per line |
| `uploads` | | Uploaded files (Console file upload) |
| `datasetId` / `datasetField` | `url` | Read links from a dataset field (`imageUrl`, `images[*].url`...) |
| `preset` | `custom` | One of the presets above |
| `sizes` | `["1200"]` | `1200` width, `x800` height, `1200x630` box, `50%` scale; optional `name=` and `:fit` (`thumb=300x300:cover`) |
| `fit` | `contain` | `contain`, `cover`, `pad`, `stretch` |
| `cropPosition` | `center` | `center`, `smart`, `top`, `bottom`, `left`, `right` |
| `backgroundColor` | `#ffffff` | padding colour and JPEG background; `transparent` for PNG/WebP/AVIF |
| `allowUpscale` | `false` | enlarge smaller images |
| `outputFormat` | `same` | `same`, `jpeg`, `png`, `webp`, `avif` (same: HEIC → JPEG; GIF, TIFF, BMP → PNG) |
| `quality` | `82` | 1–100 for JPEG, WebP, AVIF (AVIF is scaled so the same number looks like JPEG at that quality) |
| `maxFileSizeKb` | | maximum size of each output file |
| `stripMetadata` | `true` | remove EXIF/GPS (colours converted to sRGB first) |
| `createZip` | `true` | save `images.zip` with every file |
| `maxImages` | `100` | input images per run |

### Example

```json
{
  "images": [
    "https://api.apify.com/v2/key-value-stores/T5HtoeQYut1ufwkKC/records/bgremove-product.jpg",
    "https://api.apify.com/v2/key-value-stores/T5HtoeQYut1ufwkKC/records/bgremove-portrait.jpg"
  ],
  "sizes": ["thumb=300x300:cover", "web=1200", "retina=2400"],
  "outputFormat": "webp",
  "maxFileSizeKb": 300
}
```

### Output

One dataset row per input image; every file is in the key-value store (`recordUrl`-style public links) and in `images.zip`.

```json
{
  "url": "https://api.apify.com/v2/key-value-stores/T5HtoeQYut1ufwkKC/records/bgremove-product.jpg",
  "source": "direct",
  "status": "success",
  "fileName": "bgremove-product.jpg",
  "inputFormat": "jpeg",
  "inputWidth": 1280,
  "inputHeight": 1474,
  "inputBytes": 655566,
  "frames": 1,
  "previewUrl": "https://api.apify.com/v2/key-value-stores/<store>/records/0001-bgremove-product-thumb.webp",
  "outputCount": 3,
  "outputBytes": 412345,
  "outputs": [
    {"name": "thumb", "key": "0001-bgremove-product-thumb.webp", "url": "https://api.apify.com/v2/key-value-stores/<store>/records/0001-bgremove-product-thumb.webp",
     "format": "webp", "width": 300, "height": 300, "bytes": 14210, "quality": 82, "targetMet": null}
  ],
  "processedAt": "2026-11-01T12:00:00+00:00",
  "error": null
}
```

### Use the API from code

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("bossless/bulk-image-resizer").call(run_input={
    "images": ["https://example.com/shoe.jpg"],
    "preset": "amazon",
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    for f in item["outputs"] or []:
        print(f["url"], f["width"], f["height"], f["bytes"])
```

```bash
curl "https://api.apify.com/v2/acts/bossless~bulk-image-resizer/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"images": ["https://example.com/photo.heic"], "sizes": ["1600"], "outputFormat": "jpeg", "maxFileSizeKb": 400}'
```

### Use it with AI agents (MCP)

Add `https://mcp.apify.com?tools=bossless/bulk-image-resizer` to Claude, Cursor or any MCP client. The agent passes
image links and a preset or sizes, and gets back public links to the resized files.

### Ready-made tasks

- [Amazon product image resizer: 2000×2000 on white](https://apify.com/bossless/bulk-image-resizer/examples/amazon-product-image-resizer)
- [HEIC to JPG converter for iPhone photos](https://apify.com/bossless/bulk-image-resizer/examples/heic-to-jpg-converter)
- [Compress images to 100 KB (WebP / JPG)](https://apify.com/bossless/bulk-image-resizer/examples/compress-images-to-100kb)

### FAQ

**Does it enlarge small images?** Not by default: a small image keeps its own size (with `pad` it is centred on the
exact box). Turn on `allowUpscale` to enlarge. Marketplace and social presets always produce the exact box.

**What does "smart" crop do?** It keeps the part of the picture with the most detail (edges), which usually holds the
subject, instead of always cutting the centre.

**Why is my file bigger than the max size?** The quality goes down to 30 and the picture is made smaller up to four
times; a file that still doesn't fit is delivered with `targetMet: false`.

**Can it remove backgrounds or read EXIF data?** Not this actor. Use
[Background Remover](https://apify.com/bossless/background-remover) for transparent cutouts and
[EXIF Metadata Extractor](https://apify.com/bossless/exif-metadata-extractor) to read camera, GPS and dates.

**Are my images private?** They are stored in your run's key-value store under your account; the links work for
anyone who has them, like other Apify storage links.

**Is this an official Amazon, Shopify, Etsy, eBay, Instagram or YouTube tool?** No. This is an independent tool and is
not affiliated with or endorsed by Amazon, Shopify, Etsy, eBay, Meta/Instagram, Google/YouTube or Apple. The presets
follow their published image size guidelines.

# Actor input Schema

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

Links to images: JPG, PNG, WebP, AVIF, HEIC/HEIF (iPhone photos), GIF (first frame), TIFF, BMP. Direct links, or Google Drive / Dropbox file links shared as 'Anyone with the link'. One link per line. Folders and pages that need a login don't work.

## `uploads` (type: `array`):

Upload image files from your computer. Apify keeps each file in a key-value store of your account and the actor reads it from there.

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

ID of a dataset in your account (for example the output of a product, Instagram or Google Maps scraper). The links in the field below are read after the links above.

## `datasetField` (type: `string`):

Which field of each dataset item holds the image link: `imageUrl`, `displayUrl`, a nested `media.url`, or `images[*].url` for every item of a list.

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

A ready-made size and format for a marketplace or social network. A preset replaces the sizes, fit, format, quality and background below; 'Strip metadata' and 'ZIP' still apply.

## `sizes` (type: `array`):

One output file per entry, for every image. Forms: `1200` (width), `x800` (height), `1200x630` (box, see Fit), `50%` (scale). Optional name and fit: `thumb=300x300:cover`. Each output file is one billed image.

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

How a WIDTHxHEIGHT size is filled. A size's own `:fit` suffix wins over this.

## `cropPosition` (type: `string`):

Which part of the picture a cover crop keeps.

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

Fills the padding (fit 'pad') and replaces transparency in JPEG: `white`, `#ffffff`, `#f5f5f5`, or `transparent` (PNG, WebP, AVIF only).

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

Enlarge images smaller than the requested size. Off: a small image keeps its own size (pad still gives the exact box).

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

File format of every output.

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

JPEG, WebP and AVIF quality (1-100). 75-85 is the usual web range.

## `maxFileSizeKb` (type: `integer`):

Optional. Each output is made to fit: quality is lowered first (not below 30), then the picture is made smaller. PNG is reduced to 256 colours first. The record says whether the target was met.

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

Remove EXIF (camera, GPS) and colour profiles; colours are converted to sRGB first so they look the same. Off: EXIF and the colour profile are kept. Images are always turned upright by their EXIF orientation.

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

Also save every output file in one images.zip in the run's key-value store.

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

At most this many input images are processed per run (after removing duplicate links).

## Actor input object example

```json
{
  "images": [
    "https://api.apify.com/v2/key-value-stores/T5HtoeQYut1ufwkKC/records/bgremove-product.jpg",
    "https://api.apify.com/v2/key-value-stores/T5HtoeQYut1ufwkKC/records/bgremove-portrait.jpg"
  ],
  "datasetField": "url",
  "preset": "custom",
  "sizes": [
    "thumb=300x300:cover",
    "web=1200",
    "retina=2400"
  ],
  "fit": "contain",
  "cropPosition": "center",
  "backgroundColor": "#ffffff",
  "allowUpscale": false,
  "outputFormat": "webp",
  "quality": 82,
  "stripMetadata": true,
  "createZip": true,
  "maxImages": 100
}
```

# Actor output Schema

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

No description

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

No description

## `zip` (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 = {
    "images": [
        "https://api.apify.com/v2/key-value-stores/T5HtoeQYut1ufwkKC/records/bgremove-product.jpg",
        "https://api.apify.com/v2/key-value-stores/T5HtoeQYut1ufwkKC/records/bgremove-portrait.jpg"
    ],
    "sizes": [
        "thumb=300x300:cover",
        "web=1200",
        "retina=2400"
    ],
    "outputFormat": "webp"
};

// Run the Actor and wait for it to finish
const run = await client.actor("bossless/bulk-image-resizer").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": [
        "https://api.apify.com/v2/key-value-stores/T5HtoeQYut1ufwkKC/records/bgremove-product.jpg",
        "https://api.apify.com/v2/key-value-stores/T5HtoeQYut1ufwkKC/records/bgremove-portrait.jpg",
    ],
    "sizes": [
        "thumb=300x300:cover",
        "web=1200",
        "retina=2400",
    ],
    "outputFormat": "webp",
}

# Run the Actor and wait for it to finish
run = client.actor("bossless/bulk-image-resizer").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": [
    "https://api.apify.com/v2/key-value-stores/T5HtoeQYut1ufwkKC/records/bgremove-product.jpg",
    "https://api.apify.com/v2/key-value-stores/T5HtoeQYut1ufwkKC/records/bgremove-portrait.jpg"
  ],
  "sizes": [
    "thumb=300x300:cover",
    "web=1200",
    "retina=2400"
  ],
  "outputFormat": "webp"
}' |
apify call bossless/bulk-image-resizer --silent --output-dataset

```

## MCP server setup

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

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/UV3ZegXhfpbwYqo32/builds/PASE1jYFOEuNfj7uz/openapi.json
