BiRefNet Remove Background
The cutout node with actual knobs on it
- image
- background_color
- IMAGE
- MASK
- MASK_IMAGE
BiRefNet is the model that made everyone stop arguing about background removal. Hair, fur, fabric mesh - the cases rembg's older models always got wrong - and it's MIT, which is why it ended up everywhere, including in ComfyUI's own core in May 2026.
What it is
A background remover, wrapping BiRefNet with the controls a one-click remover usually hides. The interesting bit is what comes out the other end: three outputs, and a matte you can shape.
How it works
The architecture is vendored into the pack as a plain nn.Module under models/birefnet/arch/, and the weights are loaded straight from safetensors. No transformers, no trust_remote_code, no timm - which for a lot of people is the actual selling point, because those dependencies are exactly the kind that fight with whatever else is installed in your environment.
Weights are fetched from Hugging Face on the node's first run - not at import - into ComfyUI/models/background_removal/<name>.safetensors, the same folder ComfyUI's core BiRefNet nodes use, so the files are shared rather than duplicated. The downloader is the pack's own and resumes; the model stays resident between runs and swaps when you pick a different one. fp16 on CUDA, fp32 elsewhere.
Eleven checkpoints, and the choice matters more than any slider:
BiRefNet-general(the default) andBiRefNet-portrait, both swin_v1_l at 1024.BiRefNet-HRandBiRefNet-HR-mattingat 2048 - what you want above roughly 1500px.BiRefNet_lite/BiRefNet_lite-2KandBiRefNet_lite-mattingon a Swin-Tiny backbone, for constrained hardware.- The
mattingfamily, which predicts fractional alpha instead of a hard mask - veils, glass, smoke, motion blur. BiRefNet_dynamic, trained across a range of sizes, andLucida.
The inputs that matter
image and model are required; everything else has a sane default.
The matte controls are applied in a fixed order, and knowing the order saves time: sensitivity first (below 1 the matte is amplified, so faint areas count as foreground - push it down when a dark subject keeps losing its edges), then mask_blur (Gaussian, in pixels), then mask_offset (grow or shrink by one pixel per step), then invert_output if you want the background instead of the subject. refine_foreground hardens the matte edge and scales the colours by it, which is the one to try when background = Alpha gives you a visible fringe.
background picks the output shape: Alpha gives RGBA with the matte in the alpha channel, Color gives RGB over background_color. The colour picker wants frontend 1.28 or newer; on an older frontend that input shows up as a socket and the default #222222 is used no matter what you picked.
Outputs: IMAGE (RGBA or the flattened RGB), MASK (the matte itself), and MASK_IMAGE (the matte as an RGB image, which is what you want if you're previewing or comparing mattes rather than using them).
What you'd wire it into
MASK is the useful one. Compositing a subject onto a new background, masking an inpaint so it only touches the subject, feeding a detail pass - all of it wants the matte, not the RGBA image. MASK_IMAGE exists so you can look at it.
Installing it
ComfyUI Manager → search ComfyUI-BCNodes → install → restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/0xBeycan/ComfyUI-BCNodes
pip install -r ComfyUI-BCNodes/requirements.txt
The first run downloads a checkpoint, so give it a minute and don't queue twice. It's under BCNodes/mask.
Where people get burned
RGBA downstream. Plenty of nodes assume three channels. If something after this errors or comes back looking wrong, switch background to Color and composite with the MASK output instead.
Resolution versus checkpoint. With sixteen-odd BiRefNet weights in the wild, people agonise over the pick and skip the thing that matters more: feed the model an image near its inference size. An HR model on a 2048 input is a different league from a lite model choking on the same file.
Do not bathe your LoRA training set in this. Background-removing a training dataset removes the backgrounds your subject was going to be decoupled from - and the KB is blunt about it for good reason. Cutouts are for compositing and product work, not for datasets.
Nothing rendered and no error. Check the console: the weight download happens on first execution, and a failed fetch looks a lot like a node that did nothing.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| model | COMBO | BiRefNet-general | 11 options: BiRefNet-general, BiRefNet_512x512, BiRefNet-HR, BiRefNet-portrait, BiRefNet-matting, BiRefNet-HR-matting, +5 |
| sensitivityopt | FLOAT | 1.000–1 | Below 1 the matte is amplified, so faint areas count as foreground. |
| mask_bluropt | INT | 00–64 | Gaussian blur of the matte edges, in pixels. |
| mask_offsetopt | INT | 0-20–20 | Grow (positive) or shrink (negative) the matte, one pixel per step. |
| invert_outputopt | BOOLEAN | false | Keep the background instead of the subject. |
| refine_foregroundopt | BOOLEAN | false | Harden the matte edge and scale the colours by it, for cleaner cut-outs on transparent output. |
| backgroundopt | COMBO | Alpha | Alpha: RGBA output with the matte as alpha. Color: RGB output over background_color. |
| background_coloropt | COLOR | #222222 | Used when background is Color. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |
| MASK | MASK | — |
| MASK_IMAGE | IMAGE | — |