A familiar request, so the move can stay small.
If your code already sends POST /v1.0/removebg with an X-Api-Key header, it can send it here. Mostly the host changes, and purchased credits never expire.
Create a key- Create a key. Create an API key on the pricing page. A new email receives 5 test credits that do not expire.
- Send the request here. Point the client’s API host at https://remover.dev. The endpoint shape is drop-in compatible with the remove.bg API. The header is still X-Api-Key, and the image is still image_file or image_url.
- Read the bytes. A successful response is the image, not JSON. Errors are JSON with errors[].code. GET /v1.0/account returns the Ruby gem shape.
curl -H "X-Api-Key: $REMOVER_API_KEY" \ -F "image_file=@image.png" \ -F "size=auto" \ -o no-bg.png \ https://remover.dev/v1.0/removebg
import { readFile, writeFile } from "node:fs/promises";
const body = new FormData();
body.set("image_file", new Blob([await readFile("image.png")]), "image.png");
body.set("size", "auto");
const response = await fetch("https://remover.dev/v1.0/removebg", {
method: "POST",
headers: { "X-Api-Key": process.env.REMOVER_API_KEY },
body,
});
if (!response.ok) throw new Error(await response.text());
await writeFile("no-bg.png", Buffer.from(await response.arrayBuffer()));import os, requests
response = requests.post(
"https://remover.dev/v1.0/removebg",
headers={"X-Api-Key": os.environ["REMOVER_API_KEY"]},
files={"image_file": open("image.png", "rb")},
data={"size": "auto"},
)
response.raise_for_status()
open("no-bg.png", "wb").write(response.content)connection = RemoveBg::HttpConnection.build("https://remover.dev")
client = RemoveBg::ApiClient.new(connection: connection)
client.remove_from_file(
"image.png",
RemoveBg::RequestOptions.new(api_key: ENV["REMOVER_API_KEY"], size: "auto")
).save("no-bg.png")$request = curl_init("https://remover.dev/v1.0/removebg");
curl_setopt_array($request, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["X-Api-Key: " . getenv("REMOVER_API_KEY")],
CURLOPT_POSTFIELDS => ["image_file" => new CURLFile("image.png"), "size" => "auto"],
]);
file_put_contents("no-bg.png", curl_exec($request));// The official remove.bg plugin always calls api.remove.bg.
// If your own plugin or theme posts the image, this is the endpoint:
$endpoint = "https://remover.dev/v1.0/removebg";
$request = wp_remote_post($endpoint, [
"headers" => ["X-Api-Key" => getenv("REMOVER_API_KEY")],
"body" => ["image_url" => $product_image_url, "size" => "auto"],
]);# The remove.bg Shopify app cannot point at another host. # Call the HTTP API from a custom app with the same POST body. curl -H "X-Api-Key: $REMOVER_API_KEY" \ -F "image_url=$PRODUCT_IMAGE_URL" \ -F "size=auto" \ -o no-bg.png \ https://remover.dev/v1.0/removebg
Account JSON matches the Ruby gem: credits.total, subscription, payg, and enterprise, plus api.free_calls and api.sizes. credits.payg is purchased credits and the signup grant. credits.subscription is the current monthly allowance. credits.total is the sum. enterprise is 0. free_calls is 0 because signup credits are prepaid balance, not a monthly counter.
What do I change in existing code?
Mostly the host. POST /v1.0/removebg, the X-Api-Key header, and the common parameters are familiar on purpose, so the move can stay small. Snippets for curl, Node, Python, PHP, the Ruby gem, WordPress, and Shopify are on this page.
Do credits expire?
Purchased packs and the 5 signup credits do not expire. API plan credits reset each cycle. The plan is 1,000 images a month at $20, or $192 a year.
What happens when many requests arrive at once?
They are processed one at a time, in arrival order, and each still returns the image in the same response. A request that cannot start within about 10 seconds gets 503 with a Retry-After header and a JSON error with code service_unavailable. It is not charged. Retry after that many seconds, with the same Idempotency-Key if you send one.
Will the cutout match what we had before?
The request shape is familiar. The model is U²-NetP, a compatibility matte, so the result will differ on some images. type is echoed and does not switch models. Shadows and semitransparency are accepted and ignored.