Background removal API
Removes the background from an image and returns a transparent PNG. No API key. No account. One POST with an image is the whole call: nothing to register for and nothing to wait on. It is a free background removal API: a remove background API call that works from curl, Python, Node or anything else that can send an HTTP POST.
Last updated: 28 September 2026
This is the same engine the BGNinja website runs on, exposed directly over HTTP. It is free to call within the limits below. You do not need to ask us for access and there is no key to rotate.
Quick start
curl -s -o output.png \
-F "file=@input.jpg" \
https://bgninja.com/api/remove
That is the whole thing. output.png is your image with the background removed and an alpha channel where the background used to be.
Moving off the remove.bg API?
remove.bg's API page says that starting 1 December 2026, background removal moves to Leonardo.Ai. If you would rather not sign up somewhere new, the change to BGNinja is small:
| remove.bg | BGNinja | |
|---|---|---|
| URL | https://api.remove.bg/v1.0/removebg | https://bgninja.com/api/remove |
| Image field | image_file | file |
| Background colour | bg_color | bg (6-digit hex, no #; colour names such as white are ignored and give transparency) |
| Auth | X-Api-Key header | none. Drop the header |
| Output size | size (credits per size) | always your full resolution, up to 30 MP |
| Response | PNG bytes | PNG bytes, same handling |
Two differences: the free limit here is 10 images a day per IP address, and there is no image-URL input. Send the file itself. If you move real volume, tell us on the contact page first. For single photos in the browser, see the remove.bg alternative page and what the remove.bg shutdown means.
Endpoint
| Method | POST |
|---|---|
| URL | https://bgninja.com/api/remove |
| Body | multipart/form-data |
| Auth | None |
Parameters
| Name | Required | What it does |
|---|---|---|
file | yes | The image. PNG, JPG, WEBP or HEIC. |
bg | no | Hex colour without the #, for example ffffff. Composites the cutout onto that flat colour instead of leaving it transparent. Leave it out for transparency. |
src | no | A label identifying your app, for example my-plugin. Up to 32 characters, letters, digits and hyphens. It only helps us see which integrations are being used. Anything else is ignored. |
Response
On success you get HTTP 200 and the raw bytes of a PNG, with Content-Type: image/png. The call is synchronous: there is no job id, no queue and nothing to poll. Write the body straight to a file or hand it to your image library.
Limits
| Maximum file size | 99 MB |
|---|---|
| Maximum resolution | 30 megapixels |
| Running at once | 2 per IP address |
| Requests per day | 10 free, resets at midnight |
These are real and enforced. There is no hidden unlimited tier, and the free result is the full-resolution image rather than a shrunken preview.
Errors
An error comes back as JSON with a single error key, not as an image. Check the status code before you write the body to a file.
| Status | Meaning |
|---|---|
400 | The file is not an image we can read. Wrong format, or the bytes are damaged. |
402 | The 10 free requests for today are used up. The count resets at midnight. |
413 | Too big. Either over 99 MB, or more than 30 megapixels. |
422 | No file field in the request at all. This one comes back under a detail key instead of error. |
429 | You already have two requests running from this address. Wait for one to finish and retry. |
$ curl -s -F "file=@notes.txt" https://bgninja.com/api/remove
{"error":"can't read this file (TXT), please upload a photo (JPG, PNG, WEBP, HEIC)."}
A 429 is about how many run at once, so retry the same image shortly after. A 402 is the daily count, so retrying before midnight will not help.
Examples
Python
import requests
with open("input.jpg", "rb") as f:
r = requests.post(
"https://bgninja.com/api/remove",
files={"file": f},
data={"src": "my-app"},
timeout=120,
)
r.raise_for_status()
open("output.png", "wb").write(r.content)
Node
import { readFile, writeFile } from "node:fs/promises";
const body = new FormData();
body.append("file", new Blob([await readFile("input.jpg")]), "input.jpg");
body.append("src", "my-app");
const r = await fetch("https://bgninja.com/api/remove", { method: "POST", body });
if (!r.ok) throw new Error(`HTTP ${r.status}`);
await writeFile("output.png", Buffer.from(await r.arrayBuffer()));
A flat white background instead of transparency
curl -s -o output.png \
-F "file=@input.jpg" \
-F "bg=ffffff" \
https://bgninja.com/api/removeWhat happens to your image
It is processed in memory and streamed straight back to you. Nothing is written to disk, so there is no stored copy sitting somewhere waiting to be deleted or leaked. We keep a count of how many requests came in and how big they were, and nothing that identifies the picture itself.
Using it in your own project
You are welcome to build on this, including in something you charge for. One condition, and one request:
- Request: pass a
srclabel so we can see that an integration exists and avoid breaking it. - Condition: if you use BGNinja on a website or in an app that other people use, name us (“Background removal by BGNinja”, linking to bgninja.com) somewhere users can see it, such as the footer or a credits page. It is the whole reason we can keep this free and without a key. Using it on your own files needs no credit.
If you are about to send serious volume through it, say hello on the contact page first. We would rather hear from you than throttle you.
Questions
Is this a replacement for the remove.bg API?
Yes. remove.bg's API moves to Leonardo.Ai on 1 December 2026. Here you change the URL to https://bgninja.com/api/remove, rename image_file to file and bg_color to bg, and drop the X-Api-Key header. The free limit is 10 images a day.
Do I need an API key?
No. There is no key, no account and no sign-up. The endpoint is open.
Is it really free?
Yes, within the limits above. It is not a trial and there is no card to add. The optional pass raises the limits on the website; the API limits listed here apply to everyone.
Is there a rate limit per day?
10 requests a day on the free tier, resetting at midnight. The only other limit is two requests running at the same time per IP address.
Can I get the cutout mask instead of the image?
Not today. The endpoint returns the composited PNG. If you need the mask on its own, tell us on the contact page and we will look at it.
Will this endpoint keep working?
It is the same endpoint our own site calls, so it will not quietly disappear. If the shape of the request ever has to change, the old form keeps working alongside it.
Is the response asynchronous?
No. The call is synchronous: the HTTP response body is the finished PNG image. There is no job id and nothing to poll.
What image formats does it accept?
PNG, JPG, WEBP and HEIC go in. A PNG with an alpha channel comes out, or a flat background if you pass a hex colour in the bg parameter.
What happens to the image I send?
It is processed in memory and streamed straight back. Nothing is written to disk, so there is no stored copy to delete.
What happens if I send too many requests?
A third request running at the same time from one IP address gets HTTP 429: wait for one to finish and retry. After 10 requests in a day you get HTTP 402 until midnight.
Terms of use are on the terms page, and what we do with data is on the privacy page.