图片去背景API · 指南

如何用API去除图片背景:自动抠图生成透明背景PNG

面向开发者的抠图API指南:发送一个请求,返回一张透明背景PNG。包含可运行的cURL、Python和JavaScript代码,以及批量处理、重试、限制,还有remove.bg自助API停止服务后的应对方法。

更新于 2026年10月24日 · 阅读约 7 分钟

手动去除一张照片的背景需要几分钟。要为应用中每一张商品图、头像或缩略图都这样做,就需要一个去背景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_filemultipart表单数据。JPG、PNG或WebP,最大25 MB
image_url公开的http(s) URL。API会下载它,最多跟随3次重定向,超时时间15秒
image_file_b64JSON请求体中的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或5xxJSON:{"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的选项:

参数取值作用
formatpng, jpg, webp输出格式。默认png。JPG没有透明度,会合成到bg_color或白色上
bg_color十六进制(ffffff、#fff)、rgb(255, 255, 255)或颜色名称填充背景。默认透明
sizepreview, medium, hd, full保持宽高比的百万像素上限,从不放大:preview最多0.25 MP,medium 1.5 MP,hd 4 MP,full为原图(最多25 MP)
croptrue、false或1:1、4:5、16:9等比例按主体裁剪。指定比例时,会以主体为中心把裁剪框扩展到该比例
padding像素、小数或百分比裁剪时在主体周围添加的留白,最多500 px
channelsrgba, rgb, alpha透明抠图(默认)、不透明图片,或以白色表示主体的灰度蒙版
width, height1到6000以像素为单位的精确输出尺寸,在裁剪之后应用。从不拉伸
fitcontain, cover, scale-down同时设置width和height时图片的适配方式
roix1 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/removebghttps://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个积分对应一次成功的全分辨率去背景。

套餐积分价格每张图片
Starter4,000$17$0.0043
Pro15,000$49$0.0033
Scale40,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结果总是会被合成到纯色背景上。

继续阅读

立即开始免费提取文本

数秒でYouTubeの動画をテキストに変換します。クレジットカードは必要ありません。

YOUTUBETRANSCRIPT.DEVをお試しください →
如何用API去除图片背景(抠图API教程)