Local API#

Optional HTTP API that speaks the same contract from withoutBG for Mac and Docker service-* images. Traffic stays on loopback. Images are processed on device.

Hosts#

Endpoints#

  • GET /health: liveness
  • GET /openapi.json: live OpenAPI from the running server. Canonical copy: /openapi/local-api.json
  • POST /v1/remove-background: cutout or matte

Query param ?output=cutout|matte (default cutout).

Request body: raw image bytes, or multipart field image. Response: PNG plus X-Latency-Ms header.

Smart Brush (Keep / Remove)#

New with Open Weights v4. Send masks next to the image in the same multipart request and the server fixes the cutout with the stroke-edit network, on device:

  • keep_mask: white where something went missing and should stay.
  • remove_mask: white where something should go.
  • matte (optional): the previous matte, to keep refining in rounds.

Masks and matte are PNGs at the image's size. Send at least one mask. One stroke on an object reaches the whole object, and pixels away from your strokes stay as they were. Where Keep and Remove overlap, Remove wins. Invalid masks return 422.

curl Smart Brush

curl -sS -X POST \
  'http://127.0.0.1:8000/v1/remove-background?output=cutout' \
  -F 'image=@input.jpg' \
  -F 'remove_mask=@remove.png' \
  -F 'keep_mask=@keep.png' \
  -F 'matte=@matte.png' \
  -o fixed.png

Examples#

curl cutout#

curl cutout

curl -sS -X POST \
  'http://127.0.0.1:8000/v1/remove-background?output=cutout' \
  -H 'Content-Type: image/jpeg' \
  --data-binary @input.jpg \
  -o cutout.png

curl matte#

curl matte

curl -sS -X POST \
  'http://127.0.0.1:8000/v1/remove-background?output=matte' \
  -F 'image=@input.jpg' \
  -o matte.png

Python#

Python urllib

import urllib.request

url = "http://127.0.0.1:8000/v1/remove-background?output=cutout"
with open("input.jpg", "rb") as f:
    data = f.read()
req = urllib.request.Request(url, data=data, method="POST")
req.add_header("Content-Type", "image/jpeg")
with urllib.request.urlopen(req) as resp:
    open("cutout.png", "wb").write(resp.read())

Errors#

  • 400: invalid or missing image
  • 422: invalid Smart Brush mask or matte (wrong size, not an image, or a matte without a mask)
  • 500: inference failure
  • Connection refused: Local API not running (start Mac app Local API or Docker service)

GIMP plugin#

Point the GIMP plugin at http://127.0.0.1:8000 while Local API is running.

Privacy#

Local API binds to loopback. Open Model inference and Smart Brush stay on device. The Mac Local API never calls the cloud, even when the app's optional withoutBG Pro engine is on. The Docker server only does so for engine=pro requests, when you enable it. See Privacy.