# AI Image Upscaler - Enlarge Photos 2x or 4x with Real-ESRGAN (`scrapewise/image-upscaler`) Actor

Batch upscale from URLs or any Apify dataset: AI (Real-ESRGAN) enlarges images 2x or 4x into sharper WebP, JPG or PNG files with download links, plus one ZIP of everything. Up to 0.5 MP per image at the base price. No GPU, no API key. Errors are free.

- **URL**: https://apify.com/scrapewise/image-upscaler.md
- **Developed by:** [Scrapewise Data](https://apify.com/scrapewise) (community)
- **Categories:** AI, E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $17.00 / 1,000 image upscaleds

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

## AI Image Upscaler: enlarge photos 2x or 4x with Real-ESRGAN, in batch

**New in 0.2: up to 0.5 MP per image at the base price, ZIP download and batch from any dataset.**

Paste image links, or pick the dataset another scraper just filled, and get **sharper images 2x or 4x larger**,
saved as WebP, JPG or PNG with a download link for each one and, if you want, one ZIP with everything. Built on the open Real-ESRGAN model, which rebuilds edges and texture instead of
just stretching pixels. Batch hundreds of images per run, from the Console, the API, a schedule or an AI agent. No
GPU, no account elsewhere, no API key.

### At a glance

- **Price per image up to 0.5 MP of input (about 707x707):** US$ 0.02 (US$ 0.017 on Gold and above)
- **Larger inputs:** plus US$ 0.065 per started megapixel above 0.5 MP. 1024x1024 costs US$ 0.085, 1600x1200 US$ 0.15
- **Fee per run:** US$ 0.01 at the default 4 GB of memory
- **Upscale factor:** 4x (default) or 2x, same price
- **Output:** WebP (default), JPG or PNG; transparency kept in WebP and PNG; optional ZIP of all files (free)
- **Input:** any public image link (JPG, PNG, WebP, GIF, BMP, TIFF), Apify key-value store links, data: URLs, or
  any Apify dataset of your account that has image links
- **Largest input:** 2 megapixels (about 1600x1200); larger images are skipped for free or, if you choose, shrunk
  to 2 MP first
- **Error rows (broken link, not an image, too large):** Free, with an `errorCode`

### What you can do with it

- **E-commerce:** enlarge small supplier or marketplace product photos to the size your store needs.
- **Print and design:** bring web images, logos and old photos up to print resolution.
- **Real estate and listings:** sharpen small listing photos before republishing.
- **Content and thumbnails:** upscale blog images, social thumbnails and video frames.
- **Data pipelines and AI agents:** chain it after any scraper that returns image URLs: pass the scraper's dataset
  as `datasetId` and every image in it is upscaled. Every row carries a direct file link.

### One real row

From a cloud test run on 2026-10-09 (the first example image, a 330x330 photo, upscaled 4x to JPG at the default
4 GB):

```json
{
  "type": "image",
  "inputUrl": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/330px-Cat03.jpg",
  "inputWidth": 330,
  "inputHeight": 330,
  "inputFormat": "jpeg",
  "inputMegapixels": 0.109,
  "resizedBeforeUpscale": false,
  "originalWidth": 330,
  "originalHeight": 330,
  "outputWidth": 1320,
  "outputHeight": 1320,
  "scale": 4,
  "outputFormat": "jpg",
  "outputKey": "0001-330px-Cat03-x4.jpg",
  "outputUrl": "https://api.apify.com/v2/key-value-stores/<store id>/records/0001-330px-Cat03-x4.jpg?signature=<signature>",
  "outputBytes": 232064,
  "hasAlpha": false,
  "model": "realesr-general-x4v3",
  "processingSeconds": 3.3,
  "inferenceSeconds": 3.08,
  "encodingSeconds": 0.01,
  "chargedMegapixels": 0.109,
  "chargedExtraMegapixels": 0,
  "processedAt": "2026-10-09T23:25:15Z"
}
```

### Input

| Field | What it does |
|---|---|
| `imageUrls` | One image link per line. Empty (and no dataset) = two small example images |
| `datasetId` | Optional. A dataset of your account (pick it from the list or paste the ID). Each item gives its link from `imageUrl`, `image` or `url`, whichever exists first |
| `datasetField` | Optional. The field with the image link when it has another name, with dots for nested fields (`product.imageUrl`). A list of links gives one image per link |
| `scale` | `4` (default) or `2`. Same price: you pay for the input size |
| `outputFormat` | `webp` (default, smallest files, keeps transparency), `jpg` (works everywhere) or `png` (lossless, keeps transparency) |
| `quality` | WebP and JPG quality, 1 to 100 (default 90) |
| `outputZip` | Off (default). On: all files are also packed into `OUTPUT.zip`, linked in the last dataset row and in the run status. No extra charge |
| `downscaleLargeImages` | Off (default): inputs above 2 MP get a free `TOO_LARGE` row. On: they are shrunk to 2 MP, then upscaled |

Example: upscale every product photo another scraper saved, 2x, and get one ZIP:

```json
{
  "datasetId": "<your dataset ID>",
  "datasetField": "imageUrl",
  "scale": 2,
  "outputZip": true
}
```

Example: 4x two photos by link, as JPG:

```json
{
  "imageUrls": [
    "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/330px-Cat03.jpg",
    "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Camponotus_flavomarginatus_ant.jpg/330px-Camponotus_flavomarginatus_ant.jpg"
  ],
  "scale": 4,
  "outputFormat": "jpg"
}
```

To run it after another Actor automatically, add an integration on that Actor ("Run an Actor" when the run
succeeds) and pass `{"datasetId": "{{resource.defaultDatasetId}}"}` as the input.

### Output

Every image gives one dataset row and one file in the run's key-value store.

| Field | Meaning |
|---|---|
| `outputUrl` | Direct link to the upscaled file (open it or download it) |
| `outputKey` | File name in the run's key-value store |
| `inputWidth`, `inputHeight`, `inputMegapixels` | Size that was processed |
| `outputWidth`, `outputHeight`, `outputBytes` | Size of the result |
| `originalWidth`, `originalHeight`, `resizedBeforeUpscale` | Original size, and whether it was shrunk to 2 MP first |
| `scale`, `outputFormat`, `hasAlpha`, `model` | What was done |
| `processingSeconds` | Time for this image (inference and encoding) |
| `chargedMegapixels`, `chargedExtraMegapixels` | Megapixels charged and how many `extra-megapixel` events this image paid |
| `zipKey` | With `outputZip`: the ZIP file that holds this image |
| `errorCode`, `error` | Only on error rows, which are free |

With `outputZip` on, the last row has `"type": "zip"` and `zipUrl` (the download link), `imagesInZip`, `zipBytes`
and `zipFiles` (one entry per part; runs with more than about 200 MB of results are split into
`OUTPUT-part-2.zip` and so on). This row is free.

The files stay in the run's key-value store for your plan's data retention period. To keep them longer, copy them
to your own storage (S3, Google Drive, Dropbox) with an Apify integration or the API.

### Error codes (never charged)

| `errorCode` | Meaning |
|---|---|
| `INVALID_INPUT` | Not an http(s) or data: link, or a bad option (scale must be 2 or 4) |
| `DOWNLOAD_FAILED` | The link answered an error (404, 403, 429) or did not answer after 3 tries |
| `UNSUPPORTED_FORMAT` | The link is not an image this Actor reads (for example an HTML page, SVG, HEIC or AVIF), or the file is damaged |
| `TOO_LARGE` | Input above 2 megapixels (turn on `downscaleLargeImages`), or a file above 40 MB |
| `TOO_SMALL` | Smaller than 8 px on a side |
| `OUTPUT_TOO_LARGE` | The result would pass every format's size limit (WebP results above 16383 px per side are saved as JPG or PNG automatically, so this is very rare) |
| `NO_IMAGES_FOUND` | The dataset has no image link in `imageUrl`, `image`, `url` or the `datasetField` you set |
| `DATASET_NOT_FOUND` | The dataset could not be read; pick one of your own account. Links in `imageUrls` still run |
| `TIMEOUT` | Not processed because the run timeout was close; raise the timeout or split the list |
| `COST_LIMIT` | Not processed because your maximum cost per run was reached |
| `UNEXPECTED` | Something we did not expect with this image; the other images go on |

### Pricing

You pay per image delivered, by the size of the input, never for errors.

| Event | Free | Bronze | Silver | Gold and above |
|---|---|---|---|---|
| Image upscaled (covers up to 0.5 MP of input) | US$ 0.02 | US$ 0.019 | US$ 0.018 | US$ 0.017 |
| Extra megapixel (per started MP above 0.5 MP) | US$ 0.065 | US$ 0.0618 | US$ 0.0585 | US$ 0.0553 |
| Run start, at the default 4 GB | US$ 0.01 | US$ 0.0095 | US$ 0.009 | US$ 0.0085 |

Examples on the Free plan: 100 images of 500x500 = US$ 2.01; 100 images of 1024x1024 = US$ 8.51; one 1600x1200
image = US$ 0.16 with the run start; 100 images of 700x700 = US$ 2.01 (US$ 8.51 before version 0.2). The
upscale factor, the output format and the ZIP do not change the price.

### Speed

At the default 4 GB of memory a 512x512 image takes about 10 seconds, a
707x707 (0.5 MP) image 10 to 14 seconds and a 1024x1024 image about 50 seconds (measured on the Apify cloud), so a
run of 100 images of 512x512 takes about 20 minutes. Runs with more memory get more cores and finish sooner; the
price per image is the same.

### Limitations

- Upscaling invents plausible detail; it does not recover detail that was never in the photo. Faces and small text
  may look painted at 4x. Try 2x for a more conservative result.
- One general model for photos and graphics. No face restoration, no denoise slider.
- Input up to 2 megapixels per image (larger ones can be shrunk first), files up to 40 MB.
- Links that need a login or a cookie do not work; the image must be reachable by a plain HTTP request.
- Animated GIF and WebP: only the first frame.

### FAQ

**How do I upload my own files?** Upload them to any public location, or to an Apify key-value store, and paste the
links. data: URLs (base64) also work for small images.

**Can I upscale the images another scraper found?** Yes. Put that run's dataset in `datasetId`. If the link is in a
field other than `imageUrl`, `image` or `url`, name it in `datasetField` (for example `images` or `product.photo`).

**How do I download everything at once?** Turn on `outputZip`. The ZIP link is in the last dataset row and in the
run status message.

**Can I use it from n8n, Make, Zapier or an AI agent?** Yes, through the Apify app or the Apify MCP server. Each row
has an `outputUrl` the next step can download.

**Which model is it?** An open model from the Real-ESRGAN project.

### License

The upscaling model is Real-ESRGAN (BSD 3-Clause); its license notice ships with this Actor in
`model/LICENSE-Real-ESRGAN.txt`. Images you process stay yours; this Actor does not keep copies outside your run's
storage.

### Changelog

- **0.2 (2026-10-16):** up to 0.5 MP per image at the base price (was 0.3 MP); `outputZip` for one ZIP of all
  files; `datasetId` and `datasetField` to upscale the images of any dataset; WebP is the default format (half the
  file size of JPG); quality default 90; WebP results too wide for WebP are saved as JPG or PNG instead of failing;
  about 8% less processing time on images of 0.5 MP and more.
- **0.1 (2026-10-10):** first version. 2x and 4x with Real-ESRGAN; JPG, PNG and WebP; transparency kept;
  price by input megapixels; free error rows; optional shrink of inputs above 2 MP.

# Actor input Schema

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

One public image link per line (JPG, PNG, WebP, GIF, BMP or TIFF), for example a product photo, a thumbnail or a scanned picture. Links to files in an Apify key-value store and data: URLs also work. Up to 2 megapixels of input per image (about 1600x1200); up to 0.5 MP (about 707x707) costs the base price. Leave empty and pick a dataset below to upscale the images another scraper found. Both empty = two small example images.

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

Optional. An Apify dataset from your account, picked from the list or pasted as an ID, for example the output of a product, real estate or social media scraper. Every item gives the image link in its imageUrl, image or url field (the first one that exists), or in the field you set below. Works together with the links above; up to 1,000 images per run.

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

Optional. The dataset field that holds the image link, with dots for nested fields, for example product.imageUrl or images. A list of links in the field gives one image per link. Empty = imageUrl, image or url, whichever exists first.

## `scale` (type: `integer`):

4 (default) or 2. 4x turns 500x500 into 2000x2000; 2x turns it into 1000x1000. The price is the same: it depends on the input size only.

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

WebP (default) gives the smallest files and keeps transparent backgrounds. JPG works in every tool. PNG is lossless and keeps transparency, with large files. Transparent images saved as JPG get a white background. WebP results above 16383 px per side are saved as PNG or JPG instead.

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

Compression quality for WebP and JPG, 1 to 100 (default 90). 95 or more also keeps full color detail in JPG. Ignored for PNG.

## `downscaleLargeImages` (type: `boolean`):

Off (default): images above 2 megapixels are skipped with a free TOO_LARGE row. On: they are first shrunk to 2 megapixels (aspect ratio kept) and then upscaled, and you pay for the 2 megapixels processed.

## `outputZip` (type: `boolean`):

On: at the end of the run all upscaled files are packed into OUTPUT.zip in the run's key-value store (very large runs are split into OUTPUT-part-2.zip and so on). The link is in the last dataset row and in the run status. No extra charge.

## Actor input object example

```json
{
  "imageUrls": [
    "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/330px-Cat03.jpg",
    "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Camponotus_flavomarginatus_ant.jpg/330px-Camponotus_flavomarginatus_ant.jpg"
  ],
  "scale": 4,
  "outputFormat": "webp",
  "quality": 90,
  "downscaleLargeImages": false,
  "outputZip": false
}
```

# Actor output Schema

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

No description

## `resultsCsv` (type: `string`):

No description

## `files` (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/thumb/3/3a/Cat03.jpg/330px-Cat03.jpg",
        "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Camponotus_flavomarginatus_ant.jpg/330px-Camponotus_flavomarginatus_ant.jpg"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapewise/image-upscaler").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/thumb/3/3a/Cat03.jpg/330px-Cat03.jpg",
        "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Camponotus_flavomarginatus_ant.jpg/330px-Camponotus_flavomarginatus_ant.jpg",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("scrapewise/image-upscaler").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/thumb/3/3a/Cat03.jpg/330px-Cat03.jpg",
    "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Camponotus_flavomarginatus_ant.jpg/330px-Camponotus_flavomarginatus_ant.jpg"
  ]
}' |
apify call scrapewise/image-upscaler --silent --output-dataset

```

## MCP server setup

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

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/H3gvv0rpGr11qP8ok/builds/qH5XQWq8Sc9l3ayPE/openapi.json
