| # rembg · birefnet-general — API Reference |
|
|
| Background-removal service (model: **birefnet-general**). Exposes a REST API and |
| a Gradio web UI on a single port (**7860**). All inference runs through **one |
| shared worker** — every request (UI or API) is queued and processed one image at |
| a time. |
|
|
| - **Base URL:** `https://xocen-rembg.hf.space` |
| - **Web UI:** `https://xocen-rembg.hf.space/` → redirects to `/ui` |
| - **Content type of results:** `image/png` (single) or `application/zip` (batch) |
|
|
| > Note: birefnet-general on free CPU is slow (~10–30 s per image). Large batches |
| > take a while because they run sequentially through the single worker. |
|
|
| --- |
|
|
| ## Endpoints |
|
|
| | Method | Path | Purpose | Returns | |
| |--------|------|---------|---------| |
| | GET | `/` | Redirect to the web UI | 307 → `/ui` | |
| | GET | `/health` | Liveness + queue status | JSON | |
| | GET | `/jobs` | List current jobs (queued + processing) | JSON | |
| | POST | `/remove` | Remove background from one image | `image/png` | |
| | POST | `/remove/batch` | Remove background from many images | `application/zip` | |
| | GET | `/kill?key=…` | Cancel queued jobs + hard-restart worker | JSON | |
|
|
| --- |
|
|
| ### GET /health |
|
|
| Health check and live queue stats. |
|
|
| ```bash |
| curl https://xocen-rembg.hf.space/health |
| ``` |
|
|
| **200 OK** |
| ```json |
| { |
| "status": "ok", |
| "model": "birefnet-general", |
| "queue": 0, |
| "in_flight": 0 |
| } |
| ``` |
| - `queue` — jobs waiting to start. |
| - `in_flight` — jobs currently being processed (0 or 1 with a single worker). |
|
|
| --- |
|
|
| ### GET /jobs |
|
|
| List the jobs the server currently knows about — both waiting and processing. |
| Jobs disappear from the list once they finish (the response is already returned |
| to that client). Useful for watching a batch drain. |
|
|
| ```bash |
| curl https://xocen-rembg.hf.space/jobs |
| ``` |
|
|
| **200 OK** |
| ```json |
| { |
| "total": 3, |
| "queue": 2, |
| "in_flight": 1, |
| "jobs": [ |
| { "id": "9f2c…", "status": "processing", "label": "a.jpg", "age_seconds": 12.4 }, |
| { "id": "1b07…", "status": "queued", "label": "b.jpg", "age_seconds": 12.3 }, |
| { "id": "44de…", "status": "queued", "label": "c.jpg", "age_seconds": 12.3 } |
| ] |
| } |
| ``` |
| - `jobs` is ordered oldest-first; with one worker the oldest is the one |
| `processing`. |
| - `label` is the original filename when known (set by `/remove`, |
| `/remove/batch`, and the UI), otherwise `null`. |
| - `age_seconds` is how long the job has existed (queued + processing time). |
|
|
| --- |
|
|
| ### POST /remove |
|
|
| Remove the background from a **single** image. |
|
|
| - **Body:** `multipart/form-data` |
| - **Field name:** `file` (must be an image; max size = `MAX_FILE_MB`, default 30 MB) |
| - **Response:** `image/png` with a transparent background |
|
|
| ```bash |
| curl -X POST https://xocen-rembg.hf.space/remove \ |
| -F "file=@input.jpg" \ |
| --output output.png |
| ``` |
|
|
| **Errors** |
| | Status | When | |
| |--------|------| |
| | 400 | Field isn't an image, or file exceeds the size limit | |
|
|
| --- |
|
|
| ### POST /remove/batch |
|
|
| Remove backgrounds from **multiple** images in one call. |
|
|
| - **Body:** `multipart/form-data` |
| - **Field name:** `files` — repeat it once per image (max count = `MAX_BATCH_FILES`, default 20) |
| - **Response:** `application/zip` containing one PNG per input (named after the |
| original file, with a `.png` extension). If any image fails, the ZIP also |
| contains `_errors.txt` listing the failures — the rest still succeed. |
|
|
| ```bash |
| curl -X POST https://xocen-rembg.hf.space/remove/batch \ |
| -F "files=@a.jpg" \ |
| -F "files=@b.png" \ |
| -F "files=@c.webp" \ |
| --output results.zip |
| |
| unzip -l results.zip |
| # a.png |
| # b.png |
| # c.png |
| # _errors.txt (only present if something failed) |
| ``` |
|
|
| **Errors** |
| | Status | When | |
| |--------|------| |
| | 400 | More than `MAX_BATCH_FILES` files uploaded | |
|
|
| Per-file problems (not an image, too large, inference error) do **not** fail the |
| whole batch — that file is skipped and recorded in `_errors.txt`. |
|
|
| --- |
|
|
| ### GET /kill |
|
|
| Cancel everything: drops all queued jobs and **hard-restarts the worker |
| process**, aborting the job currently in progress. Guarded by a secret key. |
|
|
| - **Query param:** `key` — must equal the `KILL_API_KEY` env var (set as a Space |
| secret). |
|
|
| ```bash |
| curl "https://xocen-rembg.hf.space/kill?key=YOUR_KEY" |
| ``` |
|
|
| **200 OK** |
| ```json |
| { "killed_pending": 3, "worker_restarted": true } |
| ``` |
|
|
| **Errors** |
| | Status | When | |
| |--------|------| |
| | 401 | Missing or wrong `key` | |
| | 503 | `KILL_API_KEY` is not configured on the server | |
|
|
| After a kill, the worker respawns and reloads the model on the next request |
| (a few seconds of warm-up). |
|
|
| --- |
|
|
| ## Usage examples |
|
|
| ### Python (`requests`) |
|
|
| ```python |
| import requests |
| |
| BASE = "https://xocen-rembg.hf.space" |
| |
| # single |
| with open("input.jpg", "rb") as f: |
| r = requests.post(f"{BASE}/remove", files={"file": f}) |
| r.raise_for_status() |
| with open("output.png", "wb") as out: |
| out.write(r.content) |
| |
| # batch |
| files = [ |
| ("files", ("a.jpg", open("a.jpg", "rb"), "image/jpeg")), |
| ("files", ("b.png", open("b.png", "rb"), "image/png")), |
| ] |
| r = requests.post(f"{BASE}/remove/batch", files=files) |
| r.raise_for_status() |
| with open("results.zip", "wb") as out: |
| out.write(r.content) |
| |
| # kill |
| requests.get(f"{BASE}/kill", params={"key": "YOUR_KEY"}) |
| ``` |
|
|
| ### JavaScript (browser / Node `fetch`) |
|
|
| ```js |
| const BASE = "https://xocen-rembg.hf.space"; |
| |
| // single |
| const fd = new FormData(); |
| fd.append("file", fileInput.files[0]); |
| const res = await fetch(`${BASE}/remove`, { method: "POST", body: fd }); |
| const blob = await res.blob(); // image/png |
| const url = URL.createObjectURL(blob); |
| |
| // batch |
| const fd2 = new FormData(); |
| for (const f of fileInput.files) fd2.append("files", f); |
| const zip = await (await fetch(`${BASE}/remove/batch`, { method: "POST", body: fd2 })).blob(); |
| ``` |
|
|
| --- |
|
|
| ## Configuration (server-side env vars) |
|
|
| Set these in the Space → **Settings → Variables and secrets**. |
|
|
| | Var | Default | Meaning | |
| |-----|---------|---------| |
| | `KILL_API_KEY` | _(unset)_ | Required for `/kill`; unset → `/kill` returns 503. Store as a **secret**. | |
| | `WORKERS` | `1` | Worker processes (each holds one ~1 GB model copy). Keep at 1 on free CPU. | |
| | `MAX_BATCH_FILES` | `20` | Max files per `/remove/batch` request. | |
| | `MAX_FILE_MB` | `30` | Max size per uploaded file. | |
|
|
| --- |
|
|
| ## Behavior notes |
|
|
| - **Single queue:** UI and API share one worker. With `WORKERS=1`, only one image |
| is processed at a time; others wait in `queue`. Check progress via `/health`. |
| - **No auth on `/remove*`:** only `/kill` is key-protected. Add a proxy/auth layer |
| if you need to restrict who can submit images. |
| - **Output is always PNG** (RGBA with transparency), regardless of input format |
| (JPG, PNG, WebP, …). |
|
|