Documentation menu

Upscale an image

POSTupscalr.app/api/v1/upscale

Creates an upscale job. Send the file as multipart form data, or JSON with a publicly reachable image URL. Returns immediately with a queued job.

Request: multipart form data

ParameterTypeDescription
imagefile, requiredThe image bytes. JPEG, PNG, WebP or AVIF, up to 10 MB.
targetstringOutput size: 2k, 3k or 4k. Defaults to 2k.
formatstringOutput format: png, jpeg, webp or avif. Defaults to png.
curl -X POST https://upscalr.app/api/v1/upscale \
  -H "Authorization: Bearer $UPSCALR_API_KEY" \
  -F image=@photo.png \
  -F target=4k

Request: JSON with a URL

If the image already lives at a public HTTPS URL, skip the upload and point us at it. The same size and format checks apply after we fetch it.

ParameterTypeDescription
image_urlstring, requiredPublicly reachable HTTPS URL of the image.
targetstringOutput size: 2k–4k. Defaults to 2k.
formatstringOutput format: png, jpeg, webp or avif. Defaults to png.
filenamestringOptional display name for the job.
curl -X POST https://upscalr.app/api/v1/upscale \
  -H "Authorization: Bearer $UPSCALR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"image_url": "https://example.com/photo.png", "target": "4k"}'

Output format

The engine itself always produces PNG. This app decodes and re-encodes it into whatever format you asked for before the result is stored. That re-encode also strips whatever metadata the engine left behind (EXIF, ICC, XMP), so GPS coordinates, camera serial numbers and capture timestamps from the source never reach the output. jpeg drops transparency; png, webp and avif keep it.

ParameterTypeDescription
pnglosslessLargest files. Keeps transparency.
jpeglossySmaller. No transparency.
webplossySmall, and keeps transparency.
aviflossySmallest. Slower to encode.

Scope

Requires the jobs:write scope. A key without it gets 403 forbidden. See API key setup.

Idempotency

Send an Idempotency-Key header (any unique string, a UUID is ideal) and retries become safe: repeating a request with the same key returns the original job with 200 instead of creating and charging for a second one. Use it on every submission that might be retried by your infrastructure.

Response

Response · 202 Accepted

{
  "id": "cmrw0iqm8000bdcs3um6ii7fa",
  "object": "job",
  "status": "queued",
  "target": "4k",
  "filename": "photo.png",
  "credits": 3,
  "source": {
    "bytes": 2148393,
    "content_type": "image/png"
  },
  "created_at": "2026-07-25T09:30:00Z"
}
StatusMeaning
200Idempotent replay: the original job.
202Job accepted.
400Invalid request.
401Missing or invalid API key.
402Not enough credits.
413Image too large.
415Unsupported image format.
429Rate limit exceeded.

Error bodies follow the shape described in Errors.