← Back to the tool

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.bgBGNinja
URLhttps://api.remove.bg/v1.0/removebghttps://bgninja.com/api/remove
Image fieldimage_filefile
Background colourbg_colorbg (6-digit hex, no #; colour names such as white are ignored and give transparency)
AuthX-Api-Key headernone. Drop the header
Output sizesize (credits per size)always your full resolution, up to 30 MP
ResponsePNG bytesPNG 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

MethodPOST
URLhttps://bgninja.com/api/remove
Bodymultipart/form-data
AuthNone

Parameters

NameRequiredWhat it does
fileyesThe image. PNG, JPG, WEBP or HEIC.
bgnoHex colour without the #, for example ffffff. Composites the cutout onto that flat colour instead of leaving it transparent. Leave it out for transparency.
srcnoA 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 size99 MB
Maximum resolution30 megapixels
Running at once2 per IP address
Requests per day10 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.

StatusMeaning
400The file is not an image we can read. Wrong format, or the bytes are damaged.
402The 10 free requests for today are used up. The count resets at midnight.
413Too big. Either over 99 MB, or more than 30 megapixels.
422No file field in the request at all. This one comes back under a detail key instead of error.
429You 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/remove

What 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:

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.

ShinobiTools · KvK 42147182 · info@shinobitools.com