手动去除一张照片的背景需要几分钟。要为应用中每一张商品图、头像或缩略图都这样做,就需要一个去背景API:发送一个HTTP请求,就能拿到抠好的图片。
本指南介绍如何正确集成抠图API。你会得到可运行的cURL、Python和JavaScript代码,值得了解的输出选项,如何处理较慢的图片和批量任务,以及如何重试而不重复付费。示例使用我们的姊妹产品removebackground.dev,但这些做法适用于任何服务商。
去背景API的工作原理
你发送一张图片,服务商运行一个把主体和背景分离的分割模型,然后返回一张新图片。结果的核心是alpha通道:一个逐像素的值,表示每个像素有多少属于主体。完全不透明的像素是主体,完全透明的像素是背景,介于两者之间的值用来处理头发、毛发和玻璃等柔和边缘。
基于这个蒙版,API可以返回几种结果:
- 透明背景的抠图,通常是去掉背景的PNG或WebP
- 纯色背景上的主体,为要求白色背景的电商平台合成为JPG
- 蒙版本身,一张灰度图,可用于你自己的合成流程
- 裁剪或缩放后的版本,按主体裁剪并适配到精确尺寸
发请求是最简单的部分。生产环境的集成还要处理耗时较长的图片、大批量任务、速率限制、重试,以及让API密钥远离用户。
选择去背景API时要看什么
写代码之前,先用你自己的图片和流量对照检查以下几点。
| 标准 | 检查什么 | 为什么重要 |
|---|---|---|
| 边缘质量 | 用你自己的20到50张图片测试头发、毛发、透明物体和杂乱背景 | 服务商之间的差距体现在难处理的情况上 |
| 输入方式 | 文件上传、公开URL、base64、原始字节 | 决定你能否在队列worker中直接调用,而不必先下载图片 |
| 输出选项 | 格式、背景颜色、裁剪、留白、精确尺寸、蒙版输出 | 省去你这边的二次图片处理 |
| 较慢的图片 | 当图片处理时间超过你的HTTP超时会发生什么 | 没有任务ID,重试时可能要付两次费 |
| 批量处理 | batch端点、批次大小、部分失败如何报告 | 决定你如何处理商品目录导入 |
| 计费 | 按成功还是按请求收费,订阅还是积分,积分是否过期 | 量大时失败的图片和重试的费用会累积 |
| 限制 | 文件大小、分辨率、速率限制、结果保存时间 | 决定你的队列和存储设计 |
| 隐私 | 上传和结果保存多久,图片是否用于训练模型 | 常常是客户的硬性要求 |
第1步:创建API密钥
在removebackground.dev注册,并在账户页面创建密钥。新账户可获得50个免费积分,足够运行下面的示例并用你自己的图片测试。
把密钥保存在服务器的环境变量中:
export REMOVEBG_API_KEY="your_api_key"
每次调用都在x-api-key请求头中发送密钥,每次调用都会消耗该账户的积分。为每个应用或环境创建单独的密钥,这样撤销其中一个不会影响其他的。
第2步:用cURL去除背景
实时端点是POST https://removebackground.dev/v1/remove。最快的测试方式是文件上传:
curl -X POST https://removebackground.dev/v1/remove \
-H "x-api-key: $REMOVEBG_API_KEY" \
-F 'image_file=@photo.jpg' \
-o photo-no-bg.png
大多数单张图片会在同一个响应中处理完毕返回,通常只需几秒,结果是全分辨率的透明背景PNG。
该端点支持四种方式接收图片。任选其一发送:
| 输入 | 发送方式 |
|---|---|
| image_file | multipart表单数据。JPG、PNG或WebP,最大25 MB |
| image_url | 公开的http(s) URL。API会下载它,最多跟随3次重定向,超时时间15秒 |
| image_file_b64 | JSON请求体中的base64,可带或不带data:image前缀,解码后最大25 MB |
| 原始请求体 | 图片字节,Content-Type为image/jpeg、image/png、image/webp或application/octet-stream |
如果一个请求同时包含多种,优先级依次为image_file、image_file_b64、image_url,最后是原始请求体。选项可以作为表单字段、JSON键或查询字符串参数发送。
有一点要注意:无论状态码是什么,-o都会保存响应体。如果密钥错误或图片无效,你的"PNG"其实是一段JSON错误。信任文件之前先检查状态码。
第3步:用Python处理200、202和错误
去背景API无法保证每张图片都能在一次HTTP请求内处理完。当队列异常繁忙、某张图片耗时超过约55秒时,removebackground.dev会返回202 Accepted和一个任务ID,而不是图片。任务会继续运行,你用这个ID获取结果。
| 状态码 | 响应体 | 该怎么做 |
|---|---|---|
| 200 | 图片(image/png、image/jpeg或image/webp) | 保存它。根据Content-Type选择文件扩展名 |
| 202 | 包含id、status、status_url和result_url的JSON | 等几秒,然后GET结果。不要重新发送图片 |
| 4xx或5xx | JSON:{"error": {"code", "message"}} | 读取code。不要把响应体当作图片保存 |
关键规则:收到202后绝不要重新发送图片。 那会启动第二个任务,可能多花一个积分。下面是完整的Python版本,只发送一次图片,并且只重试安全的调用:
import os
import time
import uuid
import requests
API = "https://removebackground.dev"
KEY = os.environ["REMOVEBG_API_KEY"] # keep the key on your server
EXT = {"image/png": ".png", "image/jpeg": ".jpg", "image/webp": ".webp"}
def save(res, stem):
"""Save an image response with the right extension; raise on anything else."""
mime = res.headers.get("Content-Type", "").split(";")[0]
if res.status_code != 200 or mime not in EXT:
raise RuntimeError(f"HTTP {res.status_code}: {res.text[:500]}")
path = stem + EXT[mime]
with open(path, "wb") as f:
f.write(res.content)
return path
def remove_background(image_url, stem="result", max_wait=300):
s = requests.Session()
s.headers["x-api-key"] = KEY
# One key per image: a retry with the same key returns the same job, never a second charge.
idem = {"Idempotency-Key": str(uuid.uuid4())}
for attempt in range(3):
try:
res = s.post(f"{API}/v1/remove", data={"image_url": image_url},
headers=idem, timeout=(10, 120))
break
except requests.ConnectionError:
if attempt == 2:
raise
time.sleep(2)
if res.status_code != 202:
return save(res, stem) # 200 is the image; anything else raises
# 202: still processing. Wait for the same job.
job_id = res.json()["id"]
deadline = time.monotonic() + max_wait
while time.monotonic() < deadline:
time.sleep(2) # the API sends Retry-After: 2
res = s.get(f"{API}/v1/jobs/{job_id}/result", timeout=30)
if res.status_code == 409 and res.json()["error"]["code"] == "not_ready":
continue
return save(res, stem) # the image, or the job's own error
raise TimeoutError(f"Job {job_id} is still running. Check /v1/jobs/{job_id} later.")
print(remove_background("https://example.com/photo.jpg"))
它需要Python 3和requests(pip install requests)。有两个细节容易忽略。第一,停止脚本并不会停止任务:任务可能仍会完成并被扣费,结果会出现在你账户的Studio中。第二,任务运行期间GET /v1/jobs/:id/result会返回409 not_ready,应把它当作"等待",而不是失败。
用JavaScript(Node.js)实现同样的流程
在Node.js 18或更高版本中实现同样的流程,使用内置的fetch、FormData和Blob,上传本地文件:
import { readFile, writeFile } from "node:fs/promises"
import { randomUUID } from "node:crypto"
const API = "https://removebackground.dev"
const KEY = process.env.REMOVEBG_API_KEY // server side only
const EXT = { "image/png": ".png", "image/jpeg": ".jpg", "image/webp": ".webp" }
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
async function save(res, stem) {
const mime = (res.headers.get("content-type") || "").split(";")[0]
if (res.status !== 200 || !EXT[mime]) {
throw new Error("HTTP " + res.status + ": " + (await res.text()).slice(0, 500))
}
const path = stem + EXT[mime]
await writeFile(path, Buffer.from(await res.arrayBuffer()))
return path
}
export async function removeBackground(filePath, stem = "result", maxWaitMs = 300000) {
const form = new FormData()
form.append("image_file", new Blob([await readFile(filePath)]), "upload")
form.append("format", "png")
const res = await fetch(API + "/v1/remove", {
method: "POST",
// Reuse the same Idempotency-Key if you retry this POST.
headers: { "x-api-key": KEY, "Idempotency-Key": randomUUID() },
body: form,
})
if (res.status !== 202) return save(res, stem)
const { id } = await res.json()
const deadline = Date.now() + maxWaitMs
while (Date.now() < deadline) {
await sleep(2000)
const result = await fetch(API + "/v1/jobs/" + id + "/result", {
headers: { "x-api-key": KEY },
})
if (result.status === 409) {
const body = await result.json()
if (body.error && body.error.code === "not_ready") continue
throw new Error("Job " + id + ": " + body.error.code)
}
return save(result, stem)
}
throw new Error("Job " + id + " is still running. Check /v1/jobs/" + id + " later.")
}
console.log(await removeBackground("photo.jpg"))
API支持CORS请求,便于工具开发和测试。但这并不意味着在包含密钥的网页中调用是安全的。详见下面的安全部分。
第4步:控制输出
大多数应用并不需要原始的全分辨率抠图。它们需要白底的方形商品图、小尺寸预览或蒙版。直接向API请求最终文件,可以省去二次处理。以下是/v1/remove的选项:
| 参数 | 取值 | 作用 |
|---|---|---|
| format | png, jpg, webp | 输出格式。默认png。JPG没有透明度,会合成到bg_color或白色上 |
| bg_color | 十六进制(ffffff、#fff)、rgb(255, 255, 255)或颜色名称 | 填充背景。默认透明 |
| size | preview, medium, hd, full | 保持宽高比的百万像素上限,从不放大:preview最多0.25 MP,medium 1.5 MP,hd 4 MP,full为原图(最多25 MP) |
| crop | true、false或1:1、4:5、16:9等比例 | 按主体裁剪。指定比例时,会以主体为中心把裁剪框扩展到该比例 |
| padding | 像素、小数或百分比 | 裁剪时在主体周围添加的留白,最多500 px |
| channels | rgba, rgb, alpha | 透明抠图(默认)、不透明图片,或以白色表示主体的灰度蒙版 |
| width, height | 1到6000 | 以像素为单位的精确输出尺寸,在裁剪之后应用。从不拉伸 |
| fit | contain, cover, scale-down | 同时设置width和height时图片的适配方式 |
| roi | x1 y1 x2 y2,单位px或% | 只保留该区域内的主体 |
每个选项都同样只花1个积分,未知参数会被静默忽略,所以拼写错误不会报错。一张商品居中、留白10%的方形电商图片是这样的:
curl -X POST https://removebackground.dev/v1/remove \
-H "x-api-key: $REMOVEBG_API_KEY" \
-F 'image_file=@product.jpg' \
-F 'crop=1:1' -F 'padding=10%' \
-F 'width=1000' -F 'height=1000' \
-F 'format=jpg' -F 'bg_color=white' \
-o product-square.jpg
成功的响应还带有有用的响应头。X-Credits-Remaining显示处理该图片后的余额。X-Matte-Confidence(0到1)表示蒙版的确定程度,X-Matte-Ambiguous-Ratio给出头发、玻璃或运动模糊等柔和像素的占比。记录这两个值,就能把低置信度的抠图标记出来交给人工审核,而不必逐张检查。
第5步:批量处理图片
对于商品目录导入和历史数据回填,不要发出几百个单独请求。POST /v1/batch把最多100个公开图片URL作为一个任务排队,选项与/v1/remove相同,并立即返回202:
import os
import time
import uuid
import requests
API = "https://removebackground.dev"
s = requests.Session()
s.headers["x-api-key"] = os.environ["REMOVEBG_API_KEY"]
urls = ["https://example.com/front.jpg", "https://example.com/back.jpg"]
job = s.post(f"{API}/v1/batch",
json={"image_urls": urls, "format": "png", "size": "hd"},
headers={"Idempotency-Key": str(uuid.uuid4())}, timeout=30)
job.raise_for_status()
job_id = job.json()["id"] # save it: it's how you resume after a restart
while True:
time.sleep(3)
status = s.get(f"{API}/v1/jobs/{job_id}", timeout=30).json()
if status["done"]:
break
print(status["status"], "credits charged:", status["credits_charged"])
for item in status["items"]:
if item["status"] != "succeeded":
print("failed:", item["input"], item.get("error"))
continue
img = s.get(item["result_url"], timeout=60)
with open(f"out-{item['position']}.{item['format']}", "wb") as f:
f.write(img.content)
文档中有几条规则,设计时要围绕它们:
- 任务的最终状态是succeeded、partial(部分图片失败)或failed。
items中的每个项目都有自己的状态,失败时还会有错误代码。 - 不是http(s) URL的条目和重复的URL会被丢弃,且不收费。只要其中任一数量大于0,就应按
input而不是按位置匹配结果。 - 每个账户最多同时有3个未完成的批量任务。一旦
done为true,该批次就不再计入。 - 如果批次中途积分用完,已完成的图片照常计费,其余的被标记为skipped并注明out_of_credits,不收费。
- API没有取消端点、webhook或ZIP下载,所以轮询是标准做法。读取任务免费,且不受速率限制。
想要一个可以直接运行的脚本?用Python批量处理指南介绍了从文件夹到文件夹的完整流程。
第6步:安全重试,让计费可预测
重复扣费来自网络超时。客户端放弃后重试,一张图片就有了两个任务。解决方法是Idempotency-Key请求头:任何不超过255个字符的唯一字符串,例如UUID,每张图片或每个批次一个。如果你用同一个密钥再次发送相同的请求,会得到第一次请求创建的任务,附带Idempotent-Replayed: true请求头,且不会产生新的费用。把同一个密钥用于另一张图片,会返回409 idempotency_key_reused。
| 响应 | 该怎么做 |
|---|---|
| POST时出现网络错误、超时或500 | 用同一个Idempotency-Key重新发送同一请求 |
| 429 rate_limited | 等待Retry-After中的秒数,然后用同一个密钥重新发送 |
| 429 too_many_batches | 等到3个未完成批次中的一个完成 |
| 400、413或422 | 修正请求或图片。原样重发只会得到相同结果 |
| 401或402 | 修正密钥或充值。不要循环重试 |
| 获取结果时409 not_ready | 等2秒再查询。不要重新提交图片 |
| 410 result_unavailable | 保存的结果已删除。重新处理是一个新任务,花费1个积分 |
| POST时502 | 该任务失败且未扣费。重试一次就是一个新任务 |
计费遵循一条简单规则:图片成功处理扣1个积分,失败不收费。处理前被拒绝的请求、无法读取的图片以及服务商自身重试后仍失败的情况都免费,结果保存期间再次下载已完成的结果也免费。
设计时要考虑的限制
| 限制 | 数值 |
|---|---|
| 图片文件 | 25 MB,JPG、PNG或WebP,根据文件字节识别 |
| 输入分辨率 | 超过25 MP的图片会在处理前缩小到25 MP |
| 输出尺寸 | 宽和高各为1到6000 px |
| image_url下载 | 仅限http(s),超时15秒,最多3次重定向。拒绝私有地址和回环地址 |
| POST /v1/remove中的等待 | 约55秒,之后返回带任务ID的202 |
| 批次大小 | 每个请求100个图片URL |
| 未完成批次 | 每个账户3个 |
| 请求速率 | 所有POST端点合计每个账户每分钟60个请求。一个批次无论大小只算一次 |
| 结果保存 | 48小时,之后删除 |
如果每分钟需要处理超过60张图片,答案就是batch端点:一个请求最多涵盖100张图片。下载结果后请立即保存到你自己的存储桶,因为48小时后结果链接会返回410。根据服务商的文档,上传的图片不会用于训练模型。
从remove.bg API迁移
remove.bg的独立网站和自助API将于2026年12月1日09:00 CET停止服务。其API将迁移到Leonardo.Ai,需要修改你的集成。如果你不想重写任何代码,removebackground.dev提供兼容remove.bg的端点,迁移只需改一行:
| 迁移前 | 迁移后 |
|---|---|
| https://api.remove.bg/v1.0/removebg | https://removebackground.dev/v1.0/removebg |
你可以保留相同的X-Api-Key请求头(使用removebackground.dev的密钥)、相同的参数名、相同的响应头和相同的错误格式:
curl -H "X-Api-Key: $REMOVEBG_API_KEY" \
-F 'image_file=@photo.jpg' -F 'size=auto' \
-F 'crop=true' -F 'crop_margin=10%' -F 'bg_color=ffffff' \
-o no-bg.jpg https://removebackground.dev/v1.0/removebg
切换前先了解差异:
- 没有202。 兼容端点最多等待110秒,然后返回503超时。任务会继续运行,成功则扣费,所以盲目重试该请求会启动第二个任务。
- 该端点没有幂等键。如果需要安全重试,请逐步迁移到
/v1/remove。 - 部分选项会被接受但被忽略: type和type_level(主体会自动检测)、semitransparency以及阴影选项(不会添加阴影)。
- 任何尺寸都只要1个积分,包括全分辨率。
迁移指南提供了cURL、Python、Node和PHP的迁移前后代码,以及Zapier、Make和n8n的操作步骤。
不要把API密钥放在客户端
这是会造成真金白银损失的错误。如果你的密钥出现在网页、移动应用、公开代码仓库或URL中,任何人都能读取并花掉你的积分。
- 要让你的用户去除背景,请通过你的后端发送他们的图片,并从后端调用API。
- 在后端添加你自己的登录和按用户计算的消费限额。
- 每个应用或环境使用一个密钥。
- 如果密钥泄露,在账户页面撤销它,它会立即失效。服务商只保存每个密钥的哈希值,所以请创建新密钥,而不是试图找回旧密钥。
示例:为YouTube缩略图抠图
如果你为创作者开发工具,缩略图是一个显而易见的用途。缩略图大多以小尺寸被看到,所以抠图要撑起整个画面:一张脸或一个产品,放得很大,在简单背景前边缘清晰。YouTube建议使用16:9的3840 x 2160 px,最小宽度640 px,从电脑上传时接受最大50 MB的JPG或PNG,但从移动应用上传时只接受2 MB。
API这边只需一次调用,即可返回按主体裁剪的透明背景PNG,直接放到16:9画布上:
curl -X POST https://removebackground.dev/v1/remove \
-H "x-api-key: $REMOVEBG_API_KEY" \
-F 'image_file=@me.jpg' \
-F 'crop=true' -F 'padding=5%' \
-o me-cutout.png
抠图请拍一张静态照片,而不要截取视频帧,因为视频帧常有运动模糊;另外右下角要留空,因为YouTube会在那里显示视频时长。YouTube缩略图页面介绍了设计方面的内容,我们的获得前1,000个订阅者指南则解释了缩略图为何如此重要。
在ChatGPT、Claude或Cursor中去除背景
并不是每项工作都需要写代码。removebackground.dev还在https://removebackground.dev/mcp运行一个MCP服务器,所以你可以在ChatGPT、Claude、Cursor、VS Code或n8n中上传照片,请它去除背景。在Claude Code中,只需一条命令:
claude mcp add --transport http removebackground https://removebackground.dev/mcp
然后在Claude Code中输入/mcp登录。该服务器提供三个工具:remove_background、用于耗时超过几秒的去背景任务的get_job,以及check_credits。每张图片花费1个积分,与API相同。
价格
removebackground.dev按量付费,没有订阅。积分永不过期,失败的图片免费,新账户可获得50个免费积分。通过API,1个积分对应一次成功的全分辨率去背景。
| 套餐 | 积分 | 价格 | 每张图片 |
|---|---|---|---|
| Starter | 4,000 | $17 | $0.0043 |
| Pro | 15,000 | $49 | $0.0033 |
| Scale | 40,000 | $99 | $0.0025 |
价格以美元计,未使用的积分可在30天内退款。超过Scale的批量价格可按需申请。最新详情请查看价格页面。
总结
可靠的去背景集成归结为几个习惯:把密钥留在服务器上,保存响应体前先检查状态码,收到202后等待任务而不是重新发送,每个POST都带上Idempotency-Key,批量工作使用batch端点。
包括OpenAPI 3.1规范在内的完整参考见API文档。如果你除了图片还处理视频,我们的YouTube字幕API对比和语音转文字API集成指南在文本处理上使用了同样的生产环境做法。
常见问题
什么是去背景API?+
它是一个HTTP端点,接收一张图片,返回去掉背景后的同一张图片,通常是透明背景的PNG。你发送文件、URL或base64,服务商替你运行分割模型。
如何用Python去除图片背景?+
使用requests库,把密钥放在请求头中,将图片POST到API,状态码为200时把响应体保存为文件。如果API对较慢的图片可能返回202,就轮询任务的结果URL,而不是重新发送图片。本指南中的Python示例同时处理了这两种情况。
去背景API要多少钱?+
取决于服务商。removebackground.dev每成功处理一张图片收取1个积分,积分包从$17购买4,000积分(每张$0.0043)到$99购买40,000积分(每张$0.0025)。没有订阅,积分永不过期,失败的图片免费,新账户可获得50个免费积分。
remove.bg API关闭后,我还能继续使用原来的remove.bg代码吗?+
remove.bg的自助API将于2026年12月1日09:00 CET停止服务。removebackground.dev提供兼容remove.bg的端点,你只需把URL从https://api.remove.bg/v1.0/removebg改为https://removebackground.dev/v1.0/removebg,并在同一个X-Api-Key请求头中使用removebackground.dev的密钥。
可以直接在浏览器中调用去背景API吗?+
不应该这样做。随网页或应用一起分发的API密钥,任何人都能读取。请通过你自己的后端发送图片,把密钥保存在后端,并为你的用户添加自己的登录和消费限额。
如何获得透明背景PNG而不是白色背景?+
请求PNG或WebP格式输出,并且不要设置背景颜色。JPG无法保存透明度,所以JPG结果总是会被合成到纯色背景上。