bria-eraser removes objects from a photo. You send the image and a black-and-white mask, and it fills the masked area with matching background. There is no prompt field. This guide shows a request that ran end to end, the Python to run it, and the details that decide whether your own masks work. You need a HiAPI key from the dashboard.
Minimal request (curl)
The model uses the unified async endpoint, POST /v1/tasks. Both URLs below are public and were reachable when this was written:
curl -X POST "https://api.hiapi.ai/v1/tasks" \
-H "Authorization: Bearer $HIAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "bria-eraser",
"input": {
"image_url": "https://dev-static.hiapi.ai/model-onboarding/bria-eraser/2026/10/21/1792546025379-46c31ddb2b52110d-e1-street-src.png",
"mask_url": "https://dev-static.hiapi.ai/model-onboarding/bria-eraser/2026/10/21/1792546025861-e5d2a17ae1d12d41-e1-street-mask.png",
"mask_type": "manual"
}
}'
The call returns at once with a task id, not an image:
{"code":200,"data":{"taskId":"tk-hiapi-01M5K80RFJN3J788MMJT7YDVNB"},"message":"success"}
Poll GET /v1/tasks/<taskId> until data.status is success, then read data.output[0].url.
Python: submit, poll, download
# pip install requests; export HIAPI_KEY=your-key first
import os, time, requests
API = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {os.environ['HIAPI_KEY']}"}
def erase(image_url: str, mask_url: str, out_path: str) -> str:
r = requests.post(API, headers=HEADERS, timeout=30, json={
"model": "bria-eraser",
"input": {"image_url": image_url, "mask_url": mask_url, "mask_type": "manual"},
})
r.raise_for_status()
task_id = r.json()["data"]["taskId"]
for _ in range(60):
time.sleep(3)
try:
d = requests.get(f"{API}/{task_id}", headers=HEADERS, timeout=30).json()["data"]
except requests.RequestException:
continue # transient network error: poll the SAME task id again
if d["status"] == "success":
img = requests.get(d["output"][0]["url"], timeout=60)
img.raise_for_status()
with open(out_path, "wb") as f:
f.write(img.content)
return task_id
if d["status"] == "fail":
raise RuntimeError(f"task {task_id} failed: {d}")
raise TimeoutError(task_id)
Keep the task id. If a poll fails, poll that id again. Do not resubmit, because each submission is a separate billed task.
Request fields
| Field | Required | Notes |
|---|---|---|
input.image_url | yes | Public http/https URL. JPEG, PNG or WEBP. |
input.mask_url | yes | Black-and-white image with the same aspect ratio as the source. White is erased, black is kept. |
input.mask_type | no | manual (default) for brush-drawn masks, automatic for masks from a segmentation tool. |
input.preserve_alpha | no | Default false. Set true to keep the transparency of an input that has an alpha channel. |
Production: use a callback
Polling is fine for testing. For a service, pass a top-level callback so HiAPI notifies you when the task finishes:
{
"model": "bria-eraser",
"input": { "image_url": "...", "mask_url": "..." },
"callback": { "url": "https://your-domain.com/hiapi/callback", "when": "final" }
}
Keep polling as a fallback in case a callback is missed. Output URLs expire, so copy the file to your own storage as soon as the task succeeds.
What I ran and saw
I ran the request from the curl section once on the day of writing and polled until it finished.
- Status sequence:
handling→archiving→success.archivingcomes after the work is done and beforeoutputappears. Treat it as "not finished" and keep polling. - Time: the task went from created to completed in 16 seconds. The
outputURL appeared a few seconds after that. - Output: a PNG on
temp.hiapi.ai,1360 × 768with an alpha channel. This is the same size as the source image, which matches the docs' statement that the original resolution is kept. - Billing: the model's price in the public pricing data was $0.0575 per image when I checked. See pricing for the current figure.
- Validation error: I sent
mask_type: "bogus"as a deliberate test. The API rejected it with HTTP 400:
{"code":400,"data":null,"error_code":"INVALID_REQUEST","message":"invalid input: mask_type: value must be one of 'manual', 'automatic'"}
I checked one request on one image. I did not test other mask styles, very large images, or a mask whose aspect ratio differs from the image. The notes below on those cases come from the model documentation, not from my tests.
Mask tips (from the docs)
- Paint a little past the edge of the object. A mask that hugs the outline tends to leave a halo of the original object.
- Keep the mask the same aspect ratio as the photo. The docs require this and do not describe what happens otherwise.
- Use
automaticonly for masks that come from a segmentation or cut-out tool. Usemanualfor brush masks.
Which page should I read?
This guide covers mask-based removal with a dedicated endpoint. For a prompt-driven edit that uses general image-to-image models, see image inpainting and object removal. To remove a whole background instead of one object, see the background remover guide. The model page is at bria-eraser and the field reference is in the API docs.
FAQ
Does bria-eraser need a prompt?
No. The docs say no prompt is needed, and the request I ran contained only the image, the mask and mask_type.
Which color in the mask is removed?
White is erased and black is kept.
Is the output smaller than my input?
In my run the output was 1360 × 768, identical to the source image.
Should I poll or use a callback?
Poll while testing. Use callback.url with when: "final" in production, with polling as a fallback.





