If you have ever imported products from a supplier, you know the problem: half of the images are 400 pixels wide. Marketplaces want 1,000+ px, zoom features want more, and nobody wants to open 300 files one by one in an upscaling web app.
This n8n workflow does it from a Google Sheet. You paste image URLs into a column, click Execute workflow, and every image is upscaled 4x with Real-ESRGAN, saved to Google Drive, and the Drive link, new size and status are written back into the same row. Run it again later and it only processes the new rows.
Disclosure: the upscaling runs on the AI Image Upscaler Actor on Apify, which I built. Prices are below.
How it looks
Your sheet has a tab Images with four columns (illustrative rows):
| image_url | upscaled_url | size | status |
|---|---|---|---|
| https://…/sku-1001.jpg | https://drive.google.com/file/d/…/view | 3200x3200 | done |
| https://…/sku-1002.jpg | failed: HTTPStatusError: Client error '404 Not Found' … | ||
| https://…/sku-1003.jpg |
You fill image_url; the workflow fills the rest. In my test run a 179x179 px JPG came back as a 716x716 px file (92 kB) after about a second of processing, and a broken link was written back as failed, free of charge.
The workflow
Manual Trigger
→ Google Sheets: read "Images"
→ Filter: has image_url, no upscaled_url
→ Code: batch URLs (5 per batch)
→ HTTP Request: AI Image Upscaler
→ IF status = ok
├ yes → HTTP Request: download → Google Drive: upload → Set row → Google Sheets: update
└ no → Set row (failed + reason) ──────────────────────────────→ Google Sheets: update
Batching
Apify's synchronous endpoint (run-sync-get-dataset-items) is the simplest way to call an Actor from n8n: one request in, results out. It waits at most 300 seconds, though. Instead of sending 300 images in one run, a Code node groups the URLs into batches of five:
const BATCH_SIZE = 5;
const urls = [...new Set($input.all().map(i => String(i.json.image_url || '').trim()).filter(Boolean))];
const batches = [];
for (let i = 0; i < urls.length; i += BATCH_SIZE) batches.push({ json: { imageUrls: urls.slice(i, i + BATCH_SIZE) } });
return batches;
The HTTP Request node runs once per incoming item, so each batch becomes one Actor run, and the body is built from the item:
={{ JSON.stringify({ imageUrls: $json.imageUrls, scale: '4', outputFormat: 'jpg', quality: 92 }) }}
The Actor returns one result per image with status, outputUrl, outputWidth, outputHeight, or an error for images it could not process.
Why copy to Google Drive?
The upscaled files live in the Apify run's key-value store. The links work right away, but unnamed Apify storage is deleted after your plan's retention period (7 days on the free plan at the time of writing). For product images you want something permanent, so the workflow downloads each file (same Apify credential) and uploads it to a Drive folder. Swap that node for S3, Cloudinary or your shop's media upload if you prefer.
Writing back to the right row
The Google Sheets Update operation matches on the image_url column. That only works if the URL that comes back is exactly the one in the sheet, which is why the batching code trims whitespace and the Actor echoes the original URL as sourceUrl. The Drive file name is derived from it too: sku-1001.jpg becomes sku-1001-4x.jpg.
Quality and limits
- Real-ESRGAN (general x4 v3) is good at sharpening edges, text and product shapes. It does not invent detail that isn't there; a blurry face stays a slightly cleaner blurry face.
- Inputs are capped at 1 megapixel by default (larger images are scaled down first), so a 4x result is up to about 16 MP. That's plenty for shops and print catalogues and keeps processing fast.
-
"scale": "2"is often enough for web shops and gives smaller files. - PNG output keeps transparency for cut-out product shots and logos.
Cost
$0.015 per upscaled image, $15 per 1,000. Failed images are free. 100 product photos = $1.50. Apify's free plan includes $5 per month, roughly 330 images.
Get it
- Workflow JSON and setup guide: https://github.com/ichkifokkus/data-recipes/tree/main/5-bulk-image-upscale
- Actor: https://apify.com/fast_data_asap/ai-image-upscaler
Setup takes about ten minutes: one Apify credential, Google Sheets and Google Drive. Start with two or three rows to check the output before you throw your whole catalogue at it.
Only upscale images you have the rights to use. The model is BSD-licensed; the images are not.
Top comments (0)