remove.bg API migration: what actually changes
remove.bg moves its API to Leonardo.Ai on 1 December 2026. The field-by-field diff, three production traps, and our measured prices and latency.
If you call api.remove.bg, you have a deadline: 1 December 2026. remove.bg's own API page now says it plainly — "Starting December 1, 2026, background removal moves to Leonardo." — and links to a migration guide on Leonardo's docs, tagged utm_source=RBG_website. Leonardo.Ai is part of Canva (Canva's own newsroom welcomed it in 2024), and Canva's public API does not expose background removal at all: we searched its published Connect specification — 52 paths — and found zero matches.
So the question is not whether you migrate, but where to, and what breaks when you do. Below is the field-by-field diff we assembled while doing this work ourselves, the three traps that only show up in production, and the numbers we measured on our own API rather than quoting someone else's brochure.
Where remove.bg actually sends you
The pointer is not a rumour. remove.bg's API page carries a "Leonardo API Migration" link, and its documentation link is tagged utm_source=RBG_website&utm_medium=removebg, which tells you the vendor considers this a hand-off rather than a suggestion.
The interesting part is what is not on that path: Canva's public API. Canva owns the destination, but its Connect API — the one a developer can actually call — has no background-removal endpoint at all. If your integration needs an API, the only route remove.bg offers you is Leonardo's.
Field by field
Leonardo publishes its own comparison, and it is unusually honest. Here it is with the parts that matter to a migration, plus what to watch for:
POST https://api.remove.bg/v1.0/removebg
- What it becomes (Leonardo)
POST https://cloud.leonardo.ai/api/rest/v2/generationssync- What to watch for
- New host, new path version
X-Api-Key: <key>
- What it becomes (Leonardo)
Authorization: Bearer <LEONARDO_API_KEY>- What to watch for
- Different header — your secret store and your gateway rules both change
multipart/form-data or JSON
- What it becomes (Leonardo)
JSON only (application/json)- What to watch for
- Form uploads stop working
image_file / image_url / image_file_b64
- What it becomes (Leonardo)
one image object inside parameters.guidances.image_reference- What to watch for
- Your image reference moves two levels deep
Implicit model
- What it becomes (Leonardo)
explicit "model": "remove-bg"- What to watch for
- Cheap to get right, easy to forget
Raw image bytes by default (JSON optional)
- What it becomes (Leonardo)
always JSON: results[0].url, or dataB64 when you ask for base64- What to watch for
- You now need a second fetch or a decode before you have the picture
Nothing kept
- What it becomes (Leonardo)
kept in your Leonardo library unless ephemeral: true- What to watch for
- A storage decision your privacy policy may care about
png, jpg, webp, zip, auto
- What it becomes (Leonardo)
png, jpg, webp (no zip, no auto)- What to watch for
- Batch zips and format=auto need rework
X-Credits-Charged header
- What it becomes (Leonardo)
cost object in the response body- What to watch for
- Your cost accounting reads a different place
If you want the same comparison with a second column for us, our API reference keeps it updated — including the rows where we are worse.
The three traps
1. The response is not an image any more
The single most common bug we saw described while reading other migration write-ups: the code that used to stream a PNG now receives JSON. You either fetch the URL or decode the base64 — and each has a size limit. Leonardo's own guide notes that dataB64 only works for results under roughly 7.45 MB of pixels, and that the sync request itself can take up to about 27 seconds before it times out.
# Before: the response was the image
curl -s -X POST https://api.remove.bg/v1.0/removebg \
-H "X-Api-Key: $REMOVE_BG_KEY" \
-F image_file=@photo.jpg -o no-bg.png
# After: JSON in, decode on your side
curl -s -X POST https://cloud.leonardo.ai/api/rest/v2/generationssync \
-H "authorization: Bearer $LEONARDO_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"remove-bg","public":false,"ephemeral":true,
"parameters":{"size":"auto","type":"auto","format":"png",
"guidances":{"image_reference":[{"image":{"id":"https://example.com/photo.jpg","type":"URL"}}]}}}' \
| jq -r '.results[0].dataB64' | base64 --decode > no-bg.png
2. Results are stored unless you say otherwise
By default Leonardo keeps the result in your account library. That is a feature if you want an asset history and a liability if you process other people's photos: "we never store your images" and "your images sit in a vendor library until you delete them" are different sentences in a privacy policy. ephemeral: true gets you a 30-minute URL instead, which matches what remove.bg did (it kept nothing).
3. The price is public now
remove.bg's API page published rate limits, not a per-image price. Leonardo publishes one: $0.1047 per image, returned in every response as a cost object.
Our own top-ups are $10 for 300, $29 for 1,000, $99 for 4,000 and $299 for 15,000 — $0.033 down to $0.020 per image. That is the comparison we can defend, because both columns are published by the vendor that charges them. What it is not is the whole decision: price per image matters less than whether the integration fits your pipeline.
The question nobody asks: what happens to large images
Background removal APIs are usually benchmarked on flattering inputs. The failure mode that costs you a customer is a print-resolution photo from a phone or a product shoot. Here is the part most comparisons skip, because it is about the server rather than the model: if the service decodes your result to inspect or resize the pixels, every megapixel costs 4 bytes of memory per pixel, and serverless runtimes cap that hard.
We hit this wall ourselves and it is why our API has a number in its contract instead of a promise: 50 megapixels (8000×6250), the same ceiling remove.bg used to publish for JPG and ZIP results. To get there we stopped decoding results above 6 megapixels for API and paid callers — the no-subject check now uses the output's file size as a proxy instead of a pixel scan, which is a heuristic and is documented as one. Below that threshold nothing changed.
The practical advice: before you migrate, run your worst image through the new API, not your average one. The script below does exactly that.
Latency, measured
These are single runs against our own live API, from this workstation, on 21 September 2026 — not averages, and the model dominates, which is why the numbers are not a clean curve:
Read that as "large inputs work and cost you a longer wait", not as a benchmark against Leonardo: we have not run a controlled side-by-side, and we are not going to publish a number we did not measure.
Verify all of this yourself in five minutes
Do not trust a migration guide, including this one. Three commands settle it:
# 1. The deadline, from remove.bg's own page
curl -s https://www.remove.bg/api | grep -o 'Starting December 1, 2026[^<]*'
# 2. Canva's public API really has no background removal (52 paths, zero hits)
curl -s https://www.canva.dev/sources/connect/api/latest/api.yml | grep -ci 'remove.background'
# 3. Your own worst image through both APIs: wall time, output bytes, price
curl -s -o /dev/null -w 'ours: %{time_total}s %{size_download} bytes\n' \
-X POST https://backgone.com/api/v1/remove \
-H "Authorization: Bearer $BACKGONE_KEY" -F image_file=@your-worst-photo.jpg
Sources and method
- The deadline and the destination — remove.bg's API page and its migration guide link, read 21 September 2026.
- The ownership — Canva's newsroom announcement welcoming Leonardo.Ai, 2024.
- The negative finding — Canva's published Connect API specification (
canva.dev), searched 21 September 2026: 52 paths, zero matches for background removal. - Leonardo's contract — its own "Migrate from the remove.bg API" guide, which is where the $0.1047 figure, the JSON-only body and response, the storage default and the format list come from.
- Our latency and output sizes — single calls to
backgone.com/api/v1/removeon 21 September 2026, one per input size, uploaded from this workstation; output sizes were recorded for the smallest and largest only. - The memory chart — bytes are arithmetic (4 bytes per pixel for RGBA); the pass/fail boundary is measured on production: 6 MP and 9 MP return 200, 12 MP returns Cloudflare error 1102 on the path that still decodes.
FAQ
Can I keep calling the remove.bg API after 1 December 2026? Its own page says background removal moves to Leonardo on that date. Plan as if the endpoint is gone; do not plan around a grace period that nobody has documented.
Is Leonardo the only option? No — it is the destination remove.bg chose to point at. The two things worth comparing are the contract (request shape, response shape, storage) and the price per image, and both are published by every serious vendor.
How much code has to change? If you follow remove.bg's pointer: the auth header, the body shape, the image reference, the response handling and your cost accounting. If you keep a multipart-in, image-out shape, less.
Do I have to worry about image size? Yes, and it is the least documented part of any of these APIs. Test your largest real input before you commit, and check what the API does when it is too big: a clear error with the megapixels it measured is worth more than a mysterious 500.
Written by the BackGone team, which runs the background-removal API linked above. Every number here comes from our own production measurement or from a first-party document named next to it; where we measured once rather than many times, the text says so. If you spot an error, tell us and we will fix it and say that we did.