poofbg
The official Python SDK for the Poof background removal API. Removes backgrounds from images and from video.
Migrating from remove.bg? It shuts down on 1 December 2026 — see the remove.bg alternative and migration guide.
Installation
pip install poofbg
Quick Start
from poof import Poof
# Initialize the client
client = Poof(api_key="your-api-key")
# Remove background from an image
result = client.remove_background("photo.jpg")
# Save the result
result.save("output.png")
Usage
Remove Background
from poof import Poof
client = Poof(api_key="your-api-key")
# From a file path
result = client.remove_background("image.jpg")
# From bytes
with open("image.jpg", "rb") as f:
image_bytes = f.read()
result = client.remove_background(image_bytes)
# From a file object
with open("image.jpg", "rb") as f:
result = client.remove_background(f)
# Save the result
result.save("output.png")
# Or get the bytes directly
image_data = result.data
# or: image_data = bytes(result)
Options
# Different output format
result = client.remove_background("photo.jpg", format="webp")
# Crop to subject bounds
result = client.remove_background("photo.jpg", crop=True)
# RGB output with background color (no transparency)
result = client.remove_background(
"photo.jpg",
channels="rgb",
bg_color="#ffffff"
)
# Different size presets
result = client.remove_background("photo.jpg", size="preview")
# Exact output size, never stretched: subject cropped, then fitted into 500x500
result = client.remove_background("photo.jpg", crop=True, width=500, height=500)
# Fill the canvas instead (overflow cropped around the subject), on white
result = client.remove_background(
"photo.jpg", width=1080, height=1080, fit="cover", format="jpg", bg_color="#ffffff"
)
# Cap the width and keep the aspect ratio; small images are left as they are
result = client.remove_background("photo.jpg", width=1000, fit="scale-down")
Video
Videos go through the same remove_background() call. Poof detects the media type from the bytes: an image comes back at once, a video is accepted as a Job that you poll and then download. The result is a transparent WebM by default; format="mov" gives a ProRes 4444 MOV, format="mp4" an H.264 video composited on bg_color, and channels="alpha" a grayscale alpha matte. Audio, frame rate and duration are preserved. Video costs 5 credits per second.
from poof import Job, Poof
client = Poof(api_key="your-api-key")
# Submit, wait for the job and download the transparent WebM
job = client.remove_background("clip.mp4", wait=True)
client.download(job, "clip.webm")
# Or poll yourself, with progress
job = client.remove_background("clip.mp4", format="mov")
job = client.wait_for_job(job, on_progress=lambda j: print(f"{j.progress:.0%}"))
client.download(job, "clip.mov")
# From a public URL (up to 500 MB), green-screen MP4
job = client.remove_background(
url="https://example.com/clip.mp4", format="mp4", bg_color="#00ff00", wait=True
)
print(job.credits, job.duration_seconds, job.result_url)
# Check on a job later by id
job = client.get_job("job_8f3a1c2e9b7d4a10")
if job.is_done:
...
When you do not know whether an input is an image or a video, check the return type:
result = client.remove_background(path)
if isinstance(result, Job):
client.download(client.wait_for_job(result), "out.webm")
else:
result.save("out.png")
crop, padding, width, height and fit are image-only; sending them with a video raises a ValidationError. Results stay on the CDN for 24 hours (job.expires_at). A failed job is refunded and wait_for_job() raises a PoofError with code == "job_failed".
Result Metadata
result = client.remove_background("photo.jpg")
print(f"Image size: {result.width}x{result.height}")
print(f"Processing time: {result.processing_time_ms}ms")
print(f"Content type: {result.content_type}")
print(f"Request ID: {result.request_id}")
Account Info
info = client.me()
print(f"Plan: {info['plan']}")
print(f"Credits used: {info['usedCredits']} / {info['maxCredits']}")
Context Manager
with Poof(api_key="your-api-key") as client:
result = client.remove_background("photo.jpg")
result.save("output.png")
# Client is automatically closed
Error Handling
from poof import (
Poof,
PoofError,
AuthError,
RateLimitError,
PaymentRequiredError,
ValidationError,
)
client = Poof(api_key="your-api-key")
try:
result = client.remove_background("photo.jpg")
except AuthError as e:
print(f"Authentication failed: {e.message}")
except PaymentRequiredError as e:
print(f"Insufficient credits: {e.message}")
except RateLimitError as e:
print(f"Rate limited: {e.message}")
except ValidationError as e:
print(f"Invalid request: {e.message}")
except PoofError as e:
print(f"API error: {e.message} (code: {e.code})")
All exceptions include:
message: Human-readable error descriptioncode: Machine-readable error codedetails: Additional troubleshooting inforequest_id: Unique ID for supportstatus_code: HTTP status code
Configuration
# Custom timeout (default: 60 seconds)
client = Poof(api_key="...", timeout=120)
# Custom base URL
client = Poof(api_key="...", base_url="https://api.example.com/v1")
# Bring your own httpx client
import httpx
with httpx.Client(timeout=30, http2=True) as http_client:
client = Poof(api_key="...", httpx_client=http_client)
result = client.remove_background("photo.jpg")
API Reference
Poof(api_key, *, base_url, timeout, httpx_client)
Create a new Poof client.
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key |
str |
required | Your Poof API key |
base_url |
str |
https://api.poof.bg/v1 |
API base URL |
timeout |
float |
60.0 |
Request timeout in seconds |
httpx_client |
httpx.Client |
None |
Custom HTTP client |
client.remove_background(image=None, *, url, format, channels, bg_color, size, crop, padding, width, height, fit, wait)
Remove the background from an image or a video.
| Parameter | Type | Default | Description |
|---|---|---|---|
image |
str | Path | bytes | BinaryIO |
None |
Image or video to upload (one of image/url) |
url |
str |
None |
Public HTTPS URL of the image or video instead of an upload |
format |
"png" | "jpg" | "webp" / "webm" | "mov" | "mp4" |
"png" / "webm" |
Output format (images / videos) |
channels |
"rgba" | "rgb" | "alpha" |
"rgba" |
Color channels (alpha = grayscale matte only) |
bg_color |
str |
white | Background color when the output has no alpha (rgb, jpg, mp4) |
size |
"full" | "preview" | "medium" | "hd" |
"full" |
Output size preset (megapixel cap; video capped at 1080p); ignored when width/height is set |
crop |
bool | str |
False |
Images only. Crop to subject bounds, or an aspect ratio like "1:1" |
padding |
str |
"10%" |
Images only. Padding around the subject when cropping ("10%", "0.1", or "10%,7.5%") |
width |
int |
None |
Images only. Output width in pixels (1-6000); alone, height follows the aspect ratio |
height |
int |
None |
Images only. Output height in pixels (1-6000); alone, width follows the aspect ratio |
fit |
"contain" | "cover" | "scale-down" |
"contain" |
Images only. How to fit into width x height without stretching: pad, crop the overflow, or pad without enlarging |
wait |
bool |
False |
Videos only. Block until the job finishes and return the completed Job |
Returns a RemoveBackgroundResult for an image, with:
data: Image bytescontent_type: MIME typewidth,height: Image dimensionsprocessing_time_ms: Processing timerequest_id: Request ID for supportsave(path): Save to file
Returns a Job for a video (see below).
client.get_job(job)
Fetch the current state of a video job by id or Job. Polling is free and does not count against the rate limit. Returns a Job.
client.wait_for_job(job, *, poll_interval=3.0, timeout=600.0, on_progress=None)
Poll a job until it completes and return the completed Job. Raises PoofError with code="job_failed" if the job fails and code="timeout" if it is not done within timeout seconds. on_progress is called with the latest Job after every poll.
client.download(job, path)
Download a completed job (or a bare result_url) to path. No API key is needed; the file is served from the CDN for 24 hours.
Job
| Attribute | Type | Description |
|---|---|---|
id |
str |
Job id (job_...) |
status |
str |
queued, processing, completed or failed |
progress |
float |
Fraction processed, 0 to 1 |
is_done |
bool |
True once completed or failed |
duration_seconds, fps, width, height, frames |
Properties of the input video | |
credits |
int |
Credits charged (5 per second, refunded on failure) |
format, channels |
str |
Output format and channels |
result_url |
str | None |
Public download URL once completed |
expires_at |
str | None |
When result_url stops working (24 h after completion) |
error |
dict | None |
{"code", "message"} when failed |
stats |
dict | None |
Processing statistics once completed |
raw |
dict |
The job object as returned by the API |
client.me()
Get account information.
Returns an AccountInfo dict:
organizationId: Organization IDplan: Plan namemaxCredits: Total creditsusedCredits: Used creditsautoRechargeThreshold: Auto-recharge threshold (if enabled)
License
MIT
Metadata
Release files for poofbg 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| poofbg-0.3.0.tar.gz | 12.4 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| poofbg-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.1 kB
Release files / poofbg-0.3.0.tar.gz
| Download URL | poofbg-0.3.0.tar.gz |
|---|---|
| Size | 12.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a2c0d4ffcd6ea1b0b9cc1b90541696fc0c846037e3c50b2f64949c9e2beeb197
|
|
BLAKE2b-256 checksum How to use checksums |
0ebfb86f72863a66c2f6744b337012f642c5dd4df1490926a6c92cbd5730e844
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logRelease files / poofbg-0.3.0-py3-none-any.whl
| Download URL | poofbg-0.3.0-py3-none-any.whl |
|---|---|
| Size | 13.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b2157a2d9d85a98efe30aa5ee5f9d7060bdad2a6ecebd551bc26b9f2e57549ac
|
|
BLAKE2b-256 checksum How to use checksums |
0c91fa86574a626e4dba58f36f802fdb95a1427594143b84f8dfb5da6d2aeaf2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logSecurity for poofbg 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for poofbg-0.3.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.