Turn Pixels into Perfection
Drop a photo in, or call the API. A cleaner version comes back in seconds.
upscalr.app/api/v1/upscalecurl -X POST https://upscalr.app/api/v1/upscale \
-H "Authorization: Bearer $UPSCALR_API_KEY" \
-F image=@photo.png \
-F target=4ktargetaccepts2k3k4k
{
"id": "cmrw0iqm8000bdcs3um6ii7fa",
"object": "job",
"status": "queued",
"target": "4k",
"filename": "photo.png",
"credits": 3,
"created_at": "2026-07-25T09:30:00Z"
}- 2× – 4×on each dimension
- PNG · JPEG · WebP · AVIFin and out
- No accountfor the free tier
- REST APIwith webhooks
Detail that was never in the original
Every pair below is genuine output from the same engine the uploader uses. The source was uploaded, upscaled and downloaded like any other job.

UpscaledOriginalFur, fabric weave and eyelashes all collapse at 360px and come back strand by strand.
360 × 240 → 1440 × 960

UpscaledOriginalIndividual hairs, lash separation and skin texture survive the enlargement instead of smearing into one tone.
735 × 919 → 2940 × 3676

UpscaledOriginalA thumbnail-sized listing image, usable on a product page: edges hold and the surface keeps its grain.
300 × 300 → 1200 × 1200

UpscaledOriginalLetterforms come back sharp enough to read rather than guess — the case where softness costs you the content itself.
389 × 280 → 1556 × 1120

UpscaledOriginalA scan of a print: grain stays grain, and the detail already in the emulsion is resolved rather than invented.
1086 × 1448 → 4344 × 5792

UpscaledOriginalDiffusion output at native size, taken to print resolution without the plastic smoothing an upscale usually adds.
760 × 1012 → 3040 × 4048

UpscaledOriginalFlat colour and hard edges — the case that exposes ringing and halos. The curves stay clean at four times the size.
378 × 450 → 1512 × 1800

UpscaledOriginalThe hardest source here, a 114px thumbnail: straight lines stay straight and the window grid survives.
114 × 113 → 456 × 452

UpscaledOriginalFine repeating texture is where an upscale usually turns to mush: here the feather barbs and the catchlight hold.
399 × 501 → 1596 × 2004
Inspect it at actual pixel size
Step the multiplier, then move the lens. The frame is the original stretched; the circle is the result at 1:1.
Original, enlargedMove to inspect. Lens shows the upscale at 1:1This is the real 4× output at 1440 × 960, straight from the engine. The lens shows it at 1:1; the surround is the 360px original stretched to match.
2× to 4× on each dimension. 4× is 16× the pixels.
What happens to your image
The same four states the API reports and the webhook fires on, not a diagram drawn for this page.
Uploaded straight to storage with a presigned URL, so the image never passes through an application server that could become the bottleneck.
Reserved, not charged. The reservation is a guarded database write, so two concurrent jobs cannot both spend the last credit, and a failure releases it automatically.
Picked up by the worker loop and sent to the upscale engine. If the engine rejects the requested size for that image, the job retries at the largest size it will accept rather than failing.
Stored, converted to the format you asked for, and available over a signed download URL. The same moment fires your webhook, if you have one.
Built for the images you already have
Not for generating new ones. For rescuing the ones that are already too small.
Product photography
Marketplace listings and supplier images arrive at whatever size the supplier had. Bring them up to what your own storefront expects, without a reshoot.
Old photographs
Scans and phone snaps of prints lose the grain, the fabric and the eyelashes first. Those are exactly the details worth getting back.
Documents and screenshots
Small type is where softness shows first. A larger, cleaner source is a better input to whatever reads it next.
A web-sized image is fine on a screen and soft at 300 DPI. Upscaling before layout is cheaper than reshooting after proof.
Game and concept art
Line work and flat colour survive enlargement badly. Clean edges matter more here than invented texture.
One POST, then a webhook
No SDK required, no polling if you don't want it, and a retried request never charges twice.
upscalr.app/api/v1/upscalecurl -X POST https://upscalr.app/api/v1/upscale \
-H "Authorization: Bearer $UPSCALR_API_KEY" \
-F image=@photo.png \
-F target=4k- queuedAccepted
- processingIn the engine
- succeededresult stored · webhook sent
{ "object": "job", "status": "succeeded" }Job status succeededEverything starts with one image
Drop one in and see what comes back. No account, no card, no install.