Skip to content
LogoLogo

Transform parameters

imgx uses a /image/<OPTIONS>/<SOURCE-IMAGE> URL convention: a fixed image/ prefix, then an OPTIONS segment, then the source image path. imgx treats the segment immediately after the prefix as the options segment when it contains =. Separate multiple parameters with commas.

GET /image/<options>/<image-path>
GET /image/w=400,h=300,f=webp,q=85/photos/hero.jpg

The source-image segment is normally a relative path, resolved against IMGX_ORIGIN_BASE_URL. It may instead be an absolute http:///https:// URL, fetched directly instead of from the configured origin — but only when the operator has set IMGX_ALLOW_REMOTE_SOURCES=true (default false); otherwise such a request returns 403 Forbidden before any network call. See IMGX_ALLOW_REMOTE_SOURCES in Configuration for the security guards this enables and the risk it accepts.

GET /image/w=400/https://example.com/photos/hero.jpg

Dimensions

w / width

Output width in pixels, resized according to the current fit mode.

  • Range: 1–8192
  • Default: original width
/image/w=400/photo.jpg
/image/width=400/photo.jpg

h / height

Output height in pixels.

  • Range: 1–8192
  • Default: original height
/image/h=300/photo.jpg
/image/w=400,h=300/photo.jpg

When you specify only one dimension, imgx derives the other from the source aspect ratio.

dpr

Device pixel ratio. Multiplies w and h for retina and HiDPI displays. The effective dimensions are clamped to 8192.

  • Range: 1.0–5.0
  • Default: 1.0
# 400px at 2x = 800px actual output
/image/w=400,dpr=2/photo.jpg

Quality

q / quality

Compression quality for lossy formats (JPEG, WebP, AVIF). Higher values produce larger files with fewer artifacts. Has no effect on PNG.

  • Range: 1–100, or a perceptual quality string: high, medium-high, medium-low, low
  • Default: 80
/image/q=90/photo.jpg
/image/w=400,q=60/photo.jpg
/image/quality=high/photo.jpg

scq / slow-connection-quality

Overrides quality when the request's client-hint headers (rtt, save-data, ect, downlink) indicate a slow connection: rtt over 150ms, save-data: on, ect in slow-2g/2g/3g, or downlink under 5Mbps.

  • Range: same as quality — 1–100, or a perceptual quality string
  • Default: unset (no override)
/image/q=80,scq=40/photo.jpg

compression

Prioritizes encoding speed over output quality/size. Accepts fast, which biases format selection away from AVIF/WebP (the slowest encoders) toward JPEG — this applies even when an explicit format=avif/format=webp is requested.

  • Values: fast
  • Default: unset
/image/compression=fast/photo.jpg

Format

f / fmt / format

Output format. When set to auto or omitted, imgx negotiates the format from the client's Accept header.

  • Values: jpeg, jpg, png, webp, avif, gif, baseline-jpeg, json, auto
  • Default: auto
/image/f=webp/photo.jpg
/image/format=avif/photo.jpg
/image/fmt=png/photo.jpg
/image/f=gif/animation.gif
/image/f=baseline-jpeg/photo.jpg
/image/w=200,format=json/photo.jpg

baseline-jpeg produces non-progressive (baseline sequential) JPEG — the same encode path as jpeg today (libvips defaults to baseline unless progressive encoding is explicitly requested).

format=json returns a metadata-only JSON response instead of image bytes:

{
  "original": { "width": 2000, "height": 1500, "file_size": 123456 },
  "transformed": { "width": 200, "height": 150, "format": "webp", "file_size": 4821 }
}

transformed.format/transformed.file_size are computed by actually negotiating and encoding a real codec — real numbers, not placeholders. See docs/CLOUDFLARE_PARITY.md gap 5 for the schema's provenance (spec-derived — Cloudflare doesn't publish an exact field-by-field schema).

Fit mode

fit

Controls how the image fits the target dimensions.

ValueAliasesBehavior
containscale-downScale down to fit within the dimensions. Preserves aspect ratio. Never upscales. (default)
coverScale and crop to fill the exact dimensions. Uses gravity to pick the crop anchor. Upscales if needed.
fillsqueezeStretch to exactly fill the dimensions. Ignores aspect ratio.
insideSame as contain.
outsidescale-upScale up to cover the dimensions. Preserves aspect ratio. Never downscales.
padResize like contain, then letterbox onto the target canvas using the background color.
cropFill the target area like cover, but never upscales — behaves like contain when the source is smaller than the target.
aspect-cropCrop to the target aspect ratio. Downscales (never upscales) when the source is large enough to cover the target; otherwise crops the original-size image directly to the target ratio.
/image/w=400,h=400,fit=cover/photo.jpg
/image/w=400,h=300,fit=fill/photo.jpg
/image/w=400,h=400,fit=crop/photo.jpg
/image/w=400,h=200,fit=aspect-crop/photo.jpg

With fit=pad, set both w and h to force a fixed output canvas. The padding color comes from bg/background and defaults to white. For animated output, fit=pad currently behaves like contain.

scale-down, squeeze, and scale-up are Cloudflare Images' names for pixel-dimension-equivalent behavior imgx already had under contain, fill, and outside respectively — see docs/CLOUDFLARE_PARITY.md gap 3 for the equivalence proof. imgx's own default (contain) is unchanged.

Gravity

g / gravity

When fit=cover crops the image, this controls which region to keep.

ValueAliasesBehavior
centercentreCrop from center (default)
northn, topKeep the top edge
souths, bottomKeep the bottom edge
easte, rightKeep the right edge
westw, leftKeep the left edge
northeastneKeep the top-right corner
northwestnwKeep the top-left corner
southeastseKeep the bottom-right corner
southwestswKeep the bottom-left corner
smartautoEntropy-based detection (keeps high-detail areas)
attentionattAttention-based detection (keeps visually interesting areas)
/image/w=400,h=400,fit=cover,g=smart/photo.jpg
/image/w=400,h=400,fit=cover,g=north/photo.jpg
/image/w=400,h=400,fit=cover,g=auto/photo.jpg
/image/w=400,h=400,fit=cover,g=top/photo.jpg

top/bottom/left/right and auto are Cloudflare Images' own gravity vocabulary — aliased onto imgx's existing compass words and smart respectively (same meaning, verified against Cloudflare's docs). Cloudflare's face (face-detection-based gravity) and XxY relative-coordinate focal points are not implemented — see docs/CLOUDFLARE_PARITY.md gap 12.

Effects

sharpen

Unsharp mask with the given sigma value.

  • Range: 0.0–10.0
/image/sharpen=1.5/photo.jpg
/image/w=400,sharpen=2.0/photo.jpg

blur

Gaussian blur with the given sigma value.

  • Range: 0.1–250.0
/image/blur=3.0/photo.jpg
/image/w=400,blur=10.0/photo.jpg

brightness

  • Range: 0.0–2.0 (1.0 is normal)
/image/brightness=1.2/photo.jpg

contrast

  • Range: 0.0–2.0 (1.0 is normal)
/image/contrast=1.3/photo.jpg

saturation

  • Range: 0.0–2.0 (1.0 is normal)
/image/saturation=0.0/photo.jpg

gamma

Gamma correction.

  • Range: 0.1–10.0
/image/gamma=2.2/photo.jpg

rotate

  • Values: 0, 90, 180, 270
/image/rotate=90/photo.jpg

flip

  • Values: h (horizontal), v (vertical), hv (both)
/image/flip=h/photo.jpg

bg / background

Hex RGB color used for fit=pad canvas fill and alpha flattening before encoding. Useful when converting transparent PNGs to JPEG.

  • Format: 6-character hex, no # prefix
/image/f=jpeg,bg=ffffff/photo.png

border / border.color / border.top / border.right / border.bottom / border.left

Draws a solid-color border around the image, applied after resizing. Border widths scale with dpr.

  • border: uniform width in pixels on all four sides
  • border.color: 6-character hex, no # prefix (default: 000000)
  • border.top/.right/.bottom/.left: per-side width, overriding border for that side
/image/border=10/photo.jpg
/image/border=4,border.color=ff0000/photo.jpg
/image/border.top=2,border.left=8/photo.jpg

trim

Detect and crop uniform borders around the image (border-color-aware).

  • Range: 1.0–100.0 (threshold)
/image/trim=10/photo.jpg

trim.top / trim.right / trim.bottom / trim.left

Crop a fixed amount from one or more edges independently — NOT border-color aware (unlike trim above), and may be combined with each other or with trim.

  • Values: an integer pixel count, or a decimal 0.01.0 fraction of that side's dimension
/image/trim.top=100,trim.left=50/photo.jpg
/image/trim.left=0.1,trim.right=0.1/photo.jpg

See docs/CLOUDFLARE_PARITY.md gap 9 for what's implemented (per-side keys) versus not yet (the combined top;right;bottom;left syntax, trim.height/trim.width).

metadata

Controls EXIF and ICC metadata in the output.

  • Values: strip (default), keep, copyright
/image/metadata=keep/photo.jpg

Animation

anim

Controls whether animated images (GIF, animated WebP) preserve animation in the output.

ValueAliasesBehavior
autotruePreserve animation when the input is animated and the output format supports it. (default)
staticfalseStrip animation. Serve the first frame only.
animateRequest animated output. Degrade to static if the format does not support animation.
# Serve an animated GIF, resized
/image/w=64/spinner.gif
 
# Strip animation (Cloudflare-compatible syntax)
/image/anim=false/spinner.gif
 
# Strip animation (imgx syntax)
/image/anim=static/spinner.gif

When anim=auto and no explicit format is set, imgx negotiates an animated-capable format from the Accept header: WebP > GIF. If the client accepts neither, the output degrades to a static first frame in the best available format.

frame

Extract a specific 0-indexed frame from an animated image and serve it as a static image.

  • Range: 0–999
  • Default: none (all frames preserved)
/image/frame=0,f=png/spinner.gif
/image/frame=2/spinner.gif

If the index exceeds the number of frames, imgx returns the last frame.

Animation safety limits

LimitDefaultEnvironment variable
Max frames100IMGX_TRANSFORM_MAX_FRAMES
Max total pixels (width x height x frames)50,000,000IMGX_TRANSFORM_MAX_ANIMATED_PIXELS

When the pixel budget is exceeded, the output falls back to a static first frame. When the frame count exceeds max_frames, only that many frames load.


Content negotiation

When the output format is auto (the default), imgx picks the best format from the client's Accept header.

Static images: AVIF > WebP > JPEG > PNG

Animated images: WebP > GIF

The negotiation follows these rules:

  1. Explicit format wins. If you set f=webp, imgx always outputs WebP regardless of Accept.
  2. Animation preservation. For animated sources, imgx prefers animated-capable formats (WebP, GIF).
  3. Alpha channel handling. When the source has transparency, JPEG is deprioritized because it cannot represent alpha.
  4. Client support. Only formats the client advertises in Accept are considered.
  5. Fallback. If no acceptable format matches, JPEG is the universal fallback.

The response includes a Vary: Accept header so CDNs cache different format variants correctly.


Caching behavior

imgx caches transform results using a deterministic key built from the image path, transform parameters, and resolved output format.

Key format: <image-path>|<transform-string>|<format>

Example: photos/hero.jpg|w=400,h=300|webp

Parameter order does not matter. w=400,h=300 and h=300,w=400 produce the same cache key.


Error responses

Invalid transforms return structured JSON errors:

ConditionStatusExample
Unknown parameter400banana=42
Empty value400w=
Invalid format400f=bmp
Out of range422w=0, w=9000, q=101
{"error":{"status":400,"message":"Bad Request","detail":"invalid transform parameters"}}

onerror

Opt-in per-request behavior when the transform pipeline itself fails (a corrupt/unsupported source, an unavailable codec, etc). By default (no onerror), imgx falls back to serving the raw origin bytes as-is. Setting onerror=redirect instead returns a 302 redirect to the origin image URL — only for HTTP origins (not R2, which has no public URL to redirect to).

  • Values: redirect
  • Default: unset (raw-bytes fallback)
/image/w=400,onerror=redirect/photo.jpg

draw (overlays) — opt-in, off by default

draw.<N>.url, draw.<N>.width/.height, .top/.left/.bottom/.right, .opacity, .repeat, .background, .rotate, .fit, .gravity parse and validate (an array of overlays, indexed by <N> starting at 0). By default (IMGX_ALLOW_DRAW_OVERLAYS=false), every request naming a draw overlay returns 403 Forbidden before any network call. Set IMGX_ALLOW_DRAW_OVERLAYS=true to enable fetching draw[].url overlay images through imgx's SSRF-safe remote fetcher (see IMGX_ALLOW_REMOTE_SOURCES in Configuration — this is a separate flag, so an operator can enable overlays without enabling arbitrary remote main-image sources). See docs/CLOUDFLARE_PARITY.md gap 11 for the full status.

/image/draw.0.url=https://example.com/logo.png,draw.0.opacity=0.5/photo.jpg
→ 403 Forbidden by default; composites the overlay onto the base image when IMGX_ALLOW_DRAW_OVERLAYS=true

Full example

GET /image/w=800,h=600,fit=cover,g=attention,f=auto,q=85,dpr=2,sharpen=0.5/products/shoe-red.png

This request:

  1. Fetches products/shoe-red.png from the origin
  2. Resizes to 1600x1200 effective pixels (800x600 at dpr 2)
  3. Crops to fill using attention-based gravity
  4. Negotiates the output format from the client's Accept header
  5. Encodes at quality 85
  6. Applies a light sharpen (sigma 0.5)
  7. Caches the result for subsequent requests