Remove background from image in Python with an API

Remove an image background in Python: POST the image URL with requests, poll the job, then save the transparent PNG. A full script and the price.

5 min readSume
All posts

To remove the background from an image in Python, you either run a segmentation model in your own process or call a background-removal API. With an API, the script POSTs the image's URL, waits for the job to finish, and downloads a PNG whose background is transparent.

On Sume that call is POST /v1/rmbg-1.0/remove with the requests library, at $0.0225 per image. The Sume facts come from the RMBG 1.0 schema in the Sume API reference, which the API reference docs serve, and from Jobs and results; Requests behavior comes from its Quickstart. All were read on 2026-09-29. The field-by-field curl version is in Remove background API.

What does the Python script look like?

Submit, poll, and save. image_url is the only required field, and there is no model field: Sume picks the model. The completed job's result lists PNG artifacts with alpha, each with a public url on Sume's media host, so the download needs no key.

import os, time, requests

AUTH = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
r = requests.post(
    "https://api.sume.com/v1/rmbg-1.0/remove",
    json={"image_url": "https://example.com/inputs/portrait.jpg", "mode": "async"},
    headers={**AUTH, "Idempotency-Key": "rmbg-portrait-v1"},
    timeout=30,
)
r.raise_for_status()
job = r.json()["data"]

while True:
    s = requests.get(job["status_url"], headers=AUTH, timeout=30)
    s.raise_for_status()
    status = s.json()["data"]
    if status["terminal"]:
        break
    time.sleep(status["next_poll_after_seconds"] or 2)
if status["sume_status"] != "completed":
    raise RuntimeError(f"cutout ended as {status['sume_status']}")

res = requests.get(job["result_url"], headers=AUTH, timeout=30)
res.raise_for_status()
png_url = res.json()["data"]["result"]["artifacts"][0]["url"]
with open("cutout.png", "wb") as f:
    f.write(requests.get(png_url, timeout=60).content)

How should the script wait for the cutout?

  • mode: "async" is the default and returns at once with status_url and result_url. The loop polls status_url until terminal is true, sleeping for next_poll_after_seconds, the suggested minimum delay.
  • /result answers 409 job_not_completed until result_ready is true, so read it only after the loop ends on completed. On failed or canceled, the script stops instead.
  • mode: "sync" holds the request for at most 30 seconds (wait_timeout_seconds). That bounds the HTTP wait, not the job, so keep the poll loop either way.
  • Set timeout on every Requests call. Its Quickstart says that if no timeout is specified explicitly, requests do not time out.
  • Keep the Idempotency-Key. If the POST times out and you resend the same body under the same key, you get the original job instead of a second paid one.

Can I send a local file instead of a URL?

No. image_url must be a public HTTPS image URL, and the request schema allows no other fields besides image_url, mode, webhook_url, wait_timeout_seconds, metadata, and sync_mode, so there is nowhere to put file bytes. The schema suggests a Sume media or attachment URL where you have one. For a file on your disk, host it first: how to get a public URL for an image covers the options.

Running a model locally avoids the upload and the per-image fee, but you install and run the model yourself. The API avoids that setup, costs a flat price per image, and needs the image at a public URL.

What does it cost, and what comes back?

The price is $0.0225 per image, plus a 5.5% agent fee by default, and the public catalog adds that it does not vary by image size. Response fields and the re-cutout rule are in Remove background API. For a folder of images, remove background from images in bulk covers pacing one job per image.

From the RMBG 1.0 schema in the Sume API reference and API pricing, read 2026-09-29.
QuestionAnswer
Images per jobOne: image_url is a single URL
OutputMirrored PNG artifacts with alpha
Model choiceNone: model ids are not accepted in the request
Blocking waitAt most 30 seconds with sync; poll status_url after that
Price$0.0225 per image

Sources

Related posts

More in Developers

All Developers posts

Written by Sume