How to convert images to WebP in bulk, from a list of URLs
Short answer
For a handful, any desktop converter works. For hundreds or thousands, send the image URLs to a bulk converter: Pixkiln on Apify downloads each image, converts it to WebP (or AVIF, JPEG, PNG) at quality 80, shrinks it to your max width, strips EXIF and GPS data and returns one ZIP plus the bytes saved per image, at $0.0015 per image; failed downloads are free.
- Collect the image URLs, one per line. To grab every image from a site first, run Picpail in "list" mode and use its dataset instead.
- Pick the format: WebP for websites and stores, AVIF when you want the smallest files and your audience uses current browsers.
- Set a max width that matches where the image is shown (1600 px for page images, 1200 px for product photos, 400 px for thumbnails).
- Keep quality at 80 unless the images are photography for a portfolio (90) or small thumbnails (60-70).
- Download the ZIP, check the savedPercent column, and replace the originals on your site or CDN.
Copy-paste code
Python (pip install apify-client): image URLs in, WebP ZIP out
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
urls = [line.strip() for line in open("images.txt") if line.strip()]
run = client.actor("cybermax/image-converter").call(run_input={
"images": urls,
"format": "webp", # or "avif", "jpeg", "png", "original"
"quality": 80,
"maxWidth": 1600,
"output": "zip",
})
for r in client.dataset(run["defaultDatasetId"]).iterate_items():
print(r["status"], r.get("fileName"), r.get("inputBytes"), "->", r.get("outputBytes"), r.get("savedPercent"))
out = client.key_value_store(run["defaultKeyValueStoreId"]).get_record("OUTPUT")
print(out["value"]) # totals and the ZIP link(s)Python: every image from a website, then WebP (Picpail -> Pixkiln)
# 1) list every image on the pages (Picpail, $0.0008 per image found)
pics = client.actor("cybermax/bulk-image-downloader").call(run_input={
"urls": ["https://www.example-store.com/collections/all"],
"output": "list", "minWidth": 300,
})
# 2) convert that dataset to WebP, max 1200 px
webp = client.actor("cybermax/image-converter").call(run_input={
"datasetId": pics["defaultDatasetId"], "format": "webp", "maxWidth": 1200,
})JavaScript / Node (npm i apify-client)
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('cybermax/image-converter').call({
images: ['https://www.gstatic.com/webp/gallery/1.jpg'],
format: 'webp', quality: 80, maxWidth: 1600,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const r of items) console.log(r.fileName, r.inputBytes, '->', r.outputBytes, `${r.savedPercent}%`);No code: n8n, Make or Zapier
n8n: HTTP Request node (or the Apify node, action "Run an Actor and get dataset")
Method: POST
URL: https://api.apify.com/v2/acts/cybermax~image-converter/run-sync-get-dataset-items
Auth: Header Auth -> Authorization: Bearer <your Apify token>
Body: JSON {"images": {{ $json.imageUrls }}, "format": "webp", "maxWidth": 1600}
Output: one n8n item per result row
Make: Apify app -> "Run an Actor" (Actor: cybermax/image-converter, wait for finish = yes)
-> Apify "Get Dataset Items" (dataset = the run's defaultDatasetId) -> your next module
Zapier: Apify app -> action "Run Actor" (cybermax/image-converter, input JSON as above)
-> trigger "Finished Actor Run" -> "Fetch Dataset Items" -> your app
Runs longer than 5 minutes: start with POST /v2/acts/cybermax~image-converter/runs and read the dataset when the run finishes.
Store flow: a weekly Apify Schedule runs Picpail on your catalogue, then Pixkiln on its dataset, so a WebP copy of every product photo stays current.From an AI agent (MCP)
# Any MCP client (Claude Desktop, Claude Code, Cursor, VS Code): Apify's hosted MCP server
{
"mcpServers": {
"image-converter": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://mcp.apify.com/?tools=cybermax/image-converter",
"--header", "Authorization: Bearer ${APIFY_TOKEN}"],
"env": { "APIFY_TOKEN": "<your Apify token>" }
}
}
}
# The agent sees one tool, cybermax--image-converter, with the Actor's input schema.
# Ask: "convert these 40 product photos to WebP, max 1200 px wide".| Image | From | Size before | Size after | Saved |
|---|---|---|---|---|
| Yorkshire Dales country road (7147 px wide) | JPEG | 18.7 MB | 4.7 MB | 74.7% |
| Ani North Walls panorama (13000 px) | JPEG | 17.5 MB | 3.4 MB | 80.4% |
| Track on Fremington Edge (4608 px) | JPEG | 9.2 MB | 2.5 MB | 72.6% |
| Book cover thumbnail (100 px) | JPEG | 11.5 KB | 5.5 KB | 52.5% |
| All 150 images | 71.1 MB | 16.8 MB | 76.4% |
Source: Pixkiln (Apify Actor cybermax/image-converter) README, real Apify run on 10 Nov 2026; the same 60 large photos as AVIF at max 1200 px went from 46.9 MB to 0.9 MB
WebP or AVIF?
WebP is the safe default: every current browser shows it, and Shopify, WooCommerce and WordPress accept WebP uploads. Photos usually end up 25-35% smaller than a good JPEG at the same visual quality.
AVIF is smaller still (often half of WebP) but slower to encode and not shown by some older Safari versions. Use it for a CDN that can fall back to WebP, or when page weight matters more than reach.
Bulk image converter for Shopify, WooCommerce and Core Web Vitals
Large images are the most common reason for a slow Largest Contentful Paint. Converting product photos to WebP at the width they are actually shown at cuts page weight without a visible change, and stripping EXIF removes camera and GPS data you did not mean to publish.
Pixkiln never enlarges a small image unless you ask, applies the photo's orientation before stripping metadata (nothing comes out sideways), puts transparent PNGs onto white when you convert to JPEG and keeps every frame of an animated GIF as animated WebP.
Download every image first, then convert
Picpail finds every image on a list of pages at full size (srcset, lazy-loaded and CSS background images included). Run it in "list" mode and give its dataset ID to Pixkiln: you get one ZIP of web-ready images without handling a single file.
Good to know
Price on Apify: $0.0015 per image converted ($1.50 per 1,000), whatever the image size, no start fee. Failed downloads, unreadable files and files over your size limit are free. Apify's free plan includes $5 of usage each month (about 3,300 images).
Pixkiln only downloads public URLs and changes size, format and compression; it does not remove backgrounds or add watermarks.
Pixkiln: Bulk image converter, compressor and resizer: image URLs or a Picpail run in; WebP, AVIF, JPEG or PNG out, resized to fit, EXIF/GPS stripped, in one ZIP with bytes saved per image.
Pixkiln converts a list of image URLs (or a Picpail run) to WebP, AVIF, JPEG or PNG, resized and stripped of EXIF, in one ZIP. $0.0015 per image; failures are free.
Runs on your own Apify account, pay per result; failed results are not charged.Questions
Is there a free way to convert images to WebP in bulk?
Desktop tools such as cwebp or Squoosh are free for files you already have on disk. Pixkiln is for image URLs at scale, from an API, a schedule or an agent; Apify's monthly free credit covers about 3,300 images.
Will WebP work in every browser?
Yes, every current browser shows WebP. AVIF is shown by current Chrome, Edge, Firefox and Safari, but not by some older Safari versions.
Can it make a file bigger?
No. When a same-format re-encode would be larger, the original bytes are kept (neverLarger is on by default).
Can an AI agent use it?
Yes. Apify's MCP server exposes it as cybermax--image-converter for Claude, Cursor and other MCP clients.
Free: the Free API Starter Kit
Copy-paste calls for 4 APIs with free daily tiers (CVE priority, VIN recalls, US duty rates, email checks), then 5 short emails on KEV/EPSS, MCP and free data.