Skip to content

Image upscaling

The imageUpscaler step type takes an image and returns a higher-resolution version. The upscaler model sets the scale factor per pass (a "4×" model like 4x-Remacri — the default — applies a 4× enlargement in one run). You can then run the same model up to 3 times in one step via numberOfRepeats for compounding scale.

Common uses:

  • Finishing step after image generation (chain imageGenimageUpscaler)
  • Rescuing low-resolution assets
  • Preparing images for print / large-format display

Prerequisites

The simplest request

Use the per-recipe endpoint when you're just upscaling one image and don't need webhooks or multi-step chaining:

http
POST https://orchestration.civitai.com/v2/consumer/recipes/imageUpscaler?wait=60
Authorization: Bearer <your-token>
Content-Type: application/json

{
  "image": "https://image.civitai.com/.../00890-23.jpeg"
}
POST/v2/consumer/recipes/imageUpscaler
Set your Civitai API token via the Token button in the navbar to enable Try It.
Request body — edit to customize (e.g. swap the image URL or prompt)
Valid JSON

That's it — the defaults run the 4x-Remacri upscaler once. The response is a full Workflow whose single step carries the upscaled blob.

Via the generic workflow endpoint

Equivalent request through SubmitWorkflow — use this path when you need webhooks, tags, or to chain with other steps:

http
POST https://orchestration.civitai.com/v2/consumer/workflows?wait=60
Authorization: Bearer <your-token>
Content-Type: application/json

{
  "steps": [{
    "$type": "imageUpscaler",
    "input": {
      "image": "https://image.civitai.com/.../00890-23.jpeg",
      "numberOfRepeats": 2
    }
  }]
}
POST/v2/consumer/workflows
Set your Civitai API token via the Token button in the navbar to enable Try It.
Request body — edit to customize (e.g. swap the image URL or prompt)
Valid JSON

Input fields

See the ImageUpscalerInput schema for the full definition.

FieldRequiredDefaultNotes
imageURL, data URL, or raw Base64 string. Civitai CDN URLs work directly.
model4x-Remacri (urn:air:other:upscaler:civitai:147759@164821)AIR URN of the upscaler model. The model's own spec determines the scale factor per pass.
numberOfRepeats113. How many times to run the model end-to-end. Total scale ≈ (model_scale) ^ numberOfRepeats.

Picking a model

Two dimensions to consider:

Content type — different upscaler families handle different content best:

  • Photographic / real-world images — general-purpose upscalers (ESRGAN derivatives like 4x-Remacri, the default).
  • Anime / illustrated art — anime-tuned upscalers produce cleaner line work.
  • Faces / portraits — face-restoration–aware upscalers reduce artifacts around features.

Scale factor — upscaler models advertise their scale in the name (2x-…, 4x-…, 8x-…). This is typically the multiplication factor per pass — a 4x model on a 1024×1024 input produces 4096×4096 output in a single run. Combined with numberOfRepeats: 2, a 4× model produces a 16× total enlargement.

Browse Civitai's upscaler catalog and pass the AIR URN you want. Leave model unset to accept 4x-Remacri.

Chaining: generate then upscale

One of the most common two-step workflows — produce at native resolution, then upscale with a single submission:

json
{
  "steps": [
    {
      "$type": "imageGen",
      "name": "hero",
      "input": {
        "engine": "flux2",
        "model": "klein",
        "operation": "createImage",
        "modelVersion": "4b",
        "prompt": "A cat astronaut floating through neon space",
        "width": 1024,
        "height": 1024
      }
    },
    {
      "$type": "imageUpscaler",
      "name": "hero-4k",
      "input": {
        "image": {
          "$ref": "hero",
          "path": "output.images[0].url"
        },
        "numberOfRepeats": 1
      }
    }
  ]
}

The { "$ref": "hero", "path": "output.images[0].url" } reference creates a dependency — hero-4k doesn't start until hero succeeds, and the upscaler's image field is filled in with the generated image's signed URL at runtime. See Workflows → Dependencies for the full reference syntax.

POST/v2/consumer/workflows
Set your Civitai API token via the Token button in the navbar to enable Try It.
Request body — edit to customize (e.g. swap the image URL or prompt)
Valid JSON

Targeting an exact resolution

Upscalers only know how to multiply (4× per pass with the default model). If you need a specific output width — say, 1920 px wide for a hero image — chain a convertImage step after the upscaler to downscale to your exact target.

json
{
  "steps": [
    {
      "$type": "imageGen",
      "name": "hero",
      "input": {
        "engine": "flux2",
        "model": "klein",
        "operation": "createImage",
        "modelVersion": "4b",
        "prompt": "A cat astronaut floating through neon space",
        "width": 1024,
        "height": 1024
      }
    },
    {
      "$type": "imageUpscaler",
      "name": "upscaled",
      "input": {
        "image": { "$ref": "hero", "path": "output.images[0].url" },
        "numberOfRepeats": 1
      }
    },
    {
      "$type": "convertImage",
      "name": "hero-1920",
      "input": {
        "image": { "$ref": "upscaled", "path": "output.blob.url" },
        "transforms": [
          { "type": "resize", "targetWidth": 1920 }
        ],
        "output": {
          "format": "webp",
          "quality": 85,
          "lossless": false,
          "hideMetadata": true
        }
      }
    }
  ]
}

What happens at runtime:

  1. hero generates a 1024×1024 image.
  2. upscaled runs 4x-Remacri once → 4096×4096 (intermediate, oversized).
  3. hero-1920 downsamples to 1920 px wide (height auto-computed from aspect ratio = 1920×1920 here) and re-encodes as WebP at quality 85.

ResizeTransform keeps aspect ratio — set only targetWidth (1–4096). For other format / quality knobs see the ConvertImageInput schema; supported format values are jpeg, png, webp, gif.

POST/v2/consumer/workflows
Set your Civitai API token via the Token button in the navbar to enable Try It.
Request body — edit to customize (e.g. swap the image URL or prompt)
Valid JSON

Reading the result

A successful imageUpscaler step emits a single upscaled image blob:

json
{
  "status": "succeeded",
  "steps": [{
    "name": "0",
    "$type": "imageUpscaler",
    "status": "succeeded",
    "output": {
      "blob": { "id": "blob_...", "url": "https://.../signed.png" }
    }
  }]
}

Note: imageUpscaler output is blob (singular), not blobs[] — the step always returns exactly one image.

Blob URLs are signed and expire — refetch the workflow or call GetBlob to get a fresh URL.

Cost

Billed in Buzz on the workflow's transactions. Use whatif=true for an exact preview; see Payments (Buzz) for currency selection.

Cost scales with input pixel area and the total scale factor applied by numberOfRepeats:

inputMegapixels = width × height / 1 000 000
scale           = 2 ^ numberOfRepeats      // default 4x-Remacri, 2 per pass
total           = max(1, ceil(inputMegapixels)) × scale
ShapeBuzz
512×512 input, numberOfRepeats: 12
1024×1024 input, numberOfRepeats: 14
2048×2048 input, numberOfRepeats: 110
1024×1024 input, numberOfRepeats: 28
1024×1024 input, numberOfRepeats: 316

Upscaling is one of the cheapest operations exposed — even aggressive stacked passes on a 2-megapixel source land under a few dozen Buzz. The practical ceiling is usually the upscaler's content-size cap, not cost.

Runtime

A single pass (numberOfRepeats: 1) with the default 4x-Remacri on a ~1-megapixel input usually completes in 5–15 s and fits inside wait=60. Multiple repeats stack both runtime and output size — numberOfRepeats: 3 with a 4× model produces a 64× enlargement, which will exceed the 100-second request timeout and is rarely what you actually want. Use wait=0 plus webhooks/polling for anything beyond one pass, and keep the total scale in mind before cranking numberOfRepeats.

Troubleshooting

SymptomLikely causeFix
400 with "image could not be loaded"URL not publicly reachable, or data URL malformedMake sure the URL is fetchable without auth; re-encode the Base64 payload.
400 with "numberOfRepeats out of range"Value outside 13Clamp client-side.
Output looks soft / painterlyDefault model mismatch for this contentSpecify a content-appropriate model AIR (anime-tuned for illustration, face-aware for portraits, etc.).
Output has halos or ringingnumberOfRepeats too aggressive for the sourceDrop to a single pass; or pre-denoise the source.
Step failed, reason = "blocked"Source image hit content moderationDon't retry the same input — see Errors & retries → Step-level failures.

Civitai Developer Documentation