Quickstart

These docs describe bgcut 0.6.1.

Run the local web app from npm without installing bgcut globally:

Shell
npx bgcut

Choose an interface

Hosted browserInteractive removal and before/after inspection without an install.
Local appThe browser workflow from the npm package on a loopback server.
CLIFile-in/file-out automation, shell scripts, and directory batches.
Node APIApplication code that reuses one native runtime across removals.

Web UI

Choose, drag, or paste an image. bgcut removes the background in the browser. Use the comparison slider to inspect the result, then copy or download the PNG, rerun the removal, or choose another image. The browser accepts JPEG, PNG, WebP, and AVIF.

⌘/Ctrl+OChoose image
⌘/Ctrl+VPaste image
NNew image
CCopy PNG
DDownload PNG
RRedo removal
←→Move focused comparison slider

Automatic browser mode tries ONNX Runtime WebGPU first. If WebGPU is unavailable or its setup or inference fails, bgcut retries with ONNX Runtime WebAssembly. Both paths run inference on the user's device.

Local app

Run bgcut with no image to start the packaged remover on 127.0.0.1. The local UI contains the bgcut brand and removal workflow only. Docs, Changelog, GitHub navigation, Privacy, Terms, and the site footer remain on bgcut.dev.

Shell
npm install -g bgcut
bgcut

# explicit form
bgcut serve

# fixed port
bgcut serve --port 8787

# keep the browser closed
bgcut serve --no-open

# machine-readable startup metadata
bgcut serve --json

serve --json does not open a browser. It prints one JSON object withurl, host, port, and pid. If --port is omitted, the operating system chooses an available port. Non-root app routes redirect to /. The server exposes/health, the validated model under /models/..., and the installed ONNX Runtime browser files under /runtime/.... Image inference still runs in the browser.

CLI

Pass one image path for the existing file-in/file-out flow. Pass several files or a directory for batch removal. Directory scans are recursive. Batch inference runs one image at a time and reuses one warm runtime.

Shell
bgcut photo.jpg
bgcut remove photo.jpg
bgcut photo.jpg -o portrait.png

# several files or a directory
bgcut first.jpg second.png
bgcut photos/
bgcut photos/ -o ./cutouts

# output formats
bgcut photo.jpg --png
bgcut photo.jpg --webp
bgcut photo.jpg --jpg

# provider constraints
bgcut photo.jpg --gpu
bgcut photo.jpg --cpu
InputsJPEG, PNG, WebP, AVIF files; recursive directories
OutputsPNG, lossless WebP, JPG/JPEG on white
Automatic engineStart the WebGPU runtime first, then use CPU if it cannot start
GPU-only--gpu returns an error if the WebGPU runtime cannot start

For a single file, --output names the output file. For a batch, it names an output directory and preserves nested paths. Without --output, each result is written next to its source image. Sharp/libvips decodes each image from its contents, not from the filename extension. bgcut also accepts -png, -webp, -jpg,-gpu, and -cpu.

Node API

Install bgcut from npm:

Shell
npm install bgcut
bgcut(options?)Open a reusable bgcut instance. Close it when finished.
remover.removeBackground(input, options?)Remove one image with the open instance.
remover.removeMany(inputs, options?)Process files, directories, or iterables sequentially and stream per-image results.
remover.close()Release the reusable native runtime.

Open bgcut

TypeScript
import { bgcut } from "bgcut";

const remover = await bgcut();

try {
  // Use remover.removeBackground() or remover.removeMany().
} finally {
  await remover.close();
}

Migrating from 0.5.x to 0.6.1

bgcut 0.6.1 does not export the old top-level removeBackground() orcreateBgcut() functions. Open one instance with bgcut(), call methods on that instance, and close it when finished. Choose the engine when opening the instance. Choose the output format per removal.

One image in 0.5.x:

TypeScript
import { removeBackground } from "bgcut";

const result = await removeBackground("photo.jpg", {
  engine: "cpu",
  format: "webp",
});

The same call in 0.6.1:

TypeScript
import { bgcut } from "bgcut";

const remover = await bgcut({ engine: "cpu" });

try {
  const result = await remover.removeBackground("photo.jpg", {
    format: "webp",
  });
} finally {
  await remover.close();
}

Reusable work in 0.5.x:

TypeScript
import { createBgcut } from "bgcut";

const remover = await createBgcut();

try {
  await remover.remove("first.jpg");
  await remover.remove("second.jpg");
} finally {
  await remover.close();
}

The same work in 0.6.1:

TypeScript
import { bgcut } from "bgcut";

const remover = await bgcut();

try {
  await remover.removeBackground("first.jpg");
  await remover.removeBackground("second.jpg");
} finally {
  await remover.close();
}

For several inputs, prefer removeMany(). It accepts files, directories, iterables, and async iterables. It yields each result as it finishes and keeps later inputs running after an image-level failure.

Single image

Use removeBackground() on the bgcut instance. Choose the output format per image when needed.

TypeScript
const result = await remover.removeBackground("photo.jpg");

const webp = await remover.removeBackground("photo.jpg", {
  format: "webp",
});

Multiple images

Use removeMany() for several files, a directory, an iterable, or an async iterable. Results are yielded one at a time. Processing is sequential so one warm runtime can be reused without decoding an entire batch up front.

TypeScript
for await (const item of remover.removeMany([
  "first.jpg",
  "second.png",
])) {
  if (!item.ok) {
    console.error(item.source.input, item.error);
    continue;
  }

  console.log(item.source.input, item.result);
}

Directory inputs are recursive by default. Pass recursive: false to process only the immediate image files.

TypeScript
for await (const item of remover.removeMany("photos", {
  recursive: false,
})) {
  // ...
}

Inputs and result

Single-image inputs can be a file path, Uint8Array, orArrayBuffer. removeMany() accepts one of those inputs or an iterable/async iterable of them. Supported image formats are JPEG, PNG, WebP, and AVIF.

TypeScript
type BgcutRemovalResult = {
  data: Uint8Array;
  width: number;
  height: number;
  format: "png" | "webp" | "jpg";
  engine: "webgpu" | "cpu";
  fallbackReason: string | undefined;
  timings: {
    totalMs: number;
    prepareMs: number;
    inferenceMs: number;
    encodeMs: number;
  };
};

Engines and lifecycle

Choose the engine when opening bgcut. bgcut({ engine: "gpu" })requires native WebGPU, while bgcut({ engine: "cpu" }) requires CPU. The default auto mode tries WebGPU first and falls back to CPU if runtime creation fails. Always call close() when finished.

Errors

Node API failures use one public error type. Handle BgcutError.codeinstead of depending on Effect or ONNX Runtime error classes.

TypeScript
import { BgcutError, bgcut } from "bgcut";

const remover = await bgcut();

try {
  await remover.removeBackground("photo.jpg");
} catch (error) {
  if (error instanceof BgcutError) {
    console.error(error.code, error.message);
  }
} finally {
  await remover.close();
}

Error codes are model, engine, input,inference, output, and closed.

Model and runtime

The model input is 512 x 512. bgcut restores the matte to the source image size before export.

bgcut uses studioludens/birefnet-lite-512 at one pinned source revision. The runtime has validated FP32 and internal-FP16 artifacts with the same 512 x 512 public model input.

Source revision4a3c40c36c94093cc1e724d9ea428b8fa4b57dc7
Inference size512 x 512
Export sizeOriginal source dimensions
ArtifactRuntimeSizeSHA-256
FP32birefnet-lite-512-ort-basic-webgpu-v2.onnxNative CLI, Node API, Chromium WebGPU, browser WebAssembly, Safari fallback195,872,736 bytes4461109672dda07a054892aef076b5fcc5fc40bbc91f51a357a7593c7f45ad9c
FP16birefnet-lite-512-ort-basic-webgpu-v2-fp16.onnxSafari WebGPU with shader-f1698,572,669 bytes37d4035765b97a0323729fdee787d16eb7238c39c467316e887c5292792f3e33

The npm package does not include either model artifact. Native CLI and Node API runs use FP32. The packaged local browser app can cache both artifacts in the operating-system user cache. Safari WebGPU uses FP16 only when the device exposes shader-f16; Safari without that feature, Chromium-family WebGPU, and browser WebAssembly use FP32. bgcut verifies the byte size and SHA-256 before reusing a cached model.

Architecture

Browser and native paths use a 512 x 512 model input and composite the matte at the source image size.

Browser pathBrowser decodeAutomatic mode tries WebGPU, then WebAssembly after supported failuresSafari WebGPU uses FP16 when the device exposes shader-f16; other browser paths use FP32WebGPU input uses TypeGPU resize and ImageNet normalizationWebAssembly input uses canvas resize and the same normalizationMatte compositing at source sizeTransparent PNG export
Native Node pathSharp/libvips decode and orientationLinear resize and ImageNet normalizationFP32 with ONNX Runtime Node WebGPU or CPUMatte compositing at source sizePNG, lossless WebP, or JPG export

Cloudflare Workers hosts bgcut.dev. Workers Static Assets serves the app files. Private R2 stores both pinned model artifacts and the ONNX Runtime browser files. The Worker exposes them through same-origin /models/* and /runtime/* routes.

Resources

Humans can use the docs and type declarations directly. Agents can start with the plain-text index or the packaged skill.