API reference/POST /remove-url
Remove background from URL
Same as /remove but the source image lives at a URL we fetch on your behalf. Skip the upload step when the image is already public.
POSThttps://useknockout--api.modal.run/remove-url
Parameters
Send as multipart/form-data unless noted otherwise.
FieldTypeDefaultDescription
urlrequiredstring–Public URL of the source image. HTTPS required. ≤10 MB after fetch.
formatstringpngOutput format: png (with alpha) or webp.
qualityint 1-10092JPEG/WebP quality. Ignored for PNG.
edgestringsoftEdge style: soft (default) or hard. Same behavior as /remove.
detectstringstandardSubject detection mode: standard (default) or high_recall. high_recall runs a second model pass on a contrast-boosted copy and unions the two masks, recovering product regions the single pass misses on low-contrast shots (a pale product on a pale surface). It only ever adds to the mask; it never removes included background (that's decontaminate). Runs double inference, so latency roughly doubles and it requires a paid plan: free-tier requests get a 402.
decontaminatebooleanfalseRe-classify pixels near the mask edge using per-image color models of subject vs background, removing background the model kept: base-paper strips under products, lightbox rig fragments at the boundary. Trade-off: it helps least on a white product on a white background (no color evidence to work with), and it can trim the dark underside edge of stacked or thick products, which is partly real product. Available on every tier.
enginestring(default engine)Set to product-v1 to run the alternate cutout engine built for flat product photography: packaging film, paper, sheet goods and lightbox flat-lays, where the default engine can leave a faint light edge where the background met the product. Opt-in per request, so calls that omit it are unchanged. It runs a second refinement pass at full resolution, which costs roughly 25 seconds per image instead of a few, and it needs a paid plan. Choose it for flat, opaque products; leave it off for plants, hair, and translucent or pale organic subjects, where it performs worse than the default.
max_dimint–Resize so the longest side is ≤ this many px (aspect preserved).
widthint–Exact output width. Alone preserves aspect; with height sets an exact box.
heightint–Exact output height. Alone preserves aspect; with width sets an exact box.
despillfloat–Knockout Plus. Edge color decontamination strength 0–100. Paid tiers only; free-tier requests including it get a 402.
watermarkstring–Knockout Plus. Text watermark, bottom-right. Paid tiers only.
watermark_opacityfloat0.5Watermark opacity 0.0–1.0.
presetstring–Knockout Plus. Apply a saved preset by name. Paid tiers only.
Request
curl -X POST "https://useknockout--api.modal.run/remove-url" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/cat.jpg","format":"png"}' \
-o out.pngResponse
HTTP/1.1 200 OK
content-type: image/png
content-length: 254312
x-knockout-latency: 184
x-knockout-model: BiRefNet
x-ratelimit-limit: 60
x-ratelimit-remaining: 59Errors
FieldTypeDefaultDescription
401unauthorized–Missing or invalid token.
402payment_required–Free tier exhausted. Add a card to continue.
413payload_too_large–Image exceeds 10 MB or 4096×4096.
422no_subject_detected–Foreground could not be isolated from background.
429rate_limit_exceeded–Slow down. Retry-After header tells you when.
500internal_error–Something broke on our side. Include request_id when reporting.
424fetch_failed–We couldn't fetch the source URL. Check it's public and HTTPS.
Every error response also includes a
request_id in the JSON body. Quote it when reporting issues.Notes
- All params go in the JSON body (this endpoint is JSON, not multipart).
- We fetch via HTTP GET with a 10s timeout, no redirects beyond the first.
- Invalid edge or detect values return a 400 before we fetch the URL, so a typo costs nothing.
- Fetched bytes count against your quota same as direct uploads.
- despill, watermark, preset, and detect=high_recall require a paid tier here too: free-tier requests that include them get a 402 rather than silently ignoring them.