API de eliminación de fondos: envías una solicitud y recibes el PNG terminado.
Sube un archivo, envía la URL pública de una imagen o pásala en base64. La mayoría de las imágenes individuales vuelven terminadas en la misma respuesta HTTP, normalmente en unos segundos. Si alguna tarda más, recibes un id de trabajo para obtener el resultado sin volver a enviar la imagen. Para grandes volúmenes hay un endpoint de lotes.
1 crédito por imagen procesada con éxito · las imágenes fallidas son gratis · claves en tu cuenta
$ curl -X POST https://removebackground.dev/v1/remove \
-H "x-api-key: $REMOVEBG_API_KEY" \
-F 'image_file=@dog.jpg' -o dog.png
← 200 OK · image/png · normalmente unos segundos
guardado dog.png (transparente, resolución completa)Inicio rápido
Copia, pega y sustituye YOUR_API_KEY. Cada ejemplo guarda el resultado directamente en un archivo, y los de JavaScript y Python además esperan si reciben un 202.
curl -X POST https://removebackground.dev/v1/remove \
-H 'x-api-key: YOUR_API_KEY' \
-F 'image_file=@photo.jpg' \
-o photo-no-bg.pngEnvía tu imagen
POST /v1/remove acepta la imagen de cuatro formas. Envía una de ellas; si una solicitud incluye varias, gana image_file, luego image_file_b64, luego image_url y por último el cuerpo sin procesar. Estos ejemplos leen tu clave de la variable de entorno REMOVEBG_API_KEY (defínela con export REMOVEBG_API_KEY=…); fíjate en las comillas dobles, que permiten que la shell la sustituya.
curl -X POST https://removebackground.dev/v1/remove \
-H "x-api-key: $REMOVEBG_API_KEY" \
-F 'image_file=@photo.jpg' \
-o photo-no-bg.pngDatos de formulario multipart, campo image_file. JPG, PNG o WebP, hasta 25 MB.
Todos los ejemplos guardan el cuerpo en un archivo. Ese archivo solo es una imagen cuando el estado es 200; consulta Gestiona la respuesta.
Gestiona la respuesta
La mayoría de las imágenes individuales vuelven terminadas en la misma respuesta. Cuando la cola está inusualmente ocupada y una imagen tarda más de unos 55 segundos, recibes 202 Accepted con un id de trabajo. El trabajo sigue en marcha: obtén su resultado con el id. Volver a enviar la imagen iniciaría un segundo trabajo y podría costar un segundo crédito.
| Estado | Cuerpo | Qué hacer |
|---|---|---|
200 | La imagen (image/png, image/jpeg o image/webp) | Guárdala. Usa el Content-Type para elegir la extensión del archivo. |
202 | JSON: { id, status, status_url, result_url } | No es una imagen. Espera un par de segundos y haz GET a result_url. No vuelvas a enviar la imagen. |
4xx / 5xx | JSON: { "error": { "code", "message" } } | No es una imagen. Lee el código (ver Errores) y no guardes el cuerpo como imagen. |
Un ejemplo completo
Gestiona la imagen terminada, un 202, un trabajo que falla y un límite de tiempo local. Envía la imagen una sola vez y solo reintenta las consultas de estado, que son seguras.
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: resending with the same key returns the same job, never a second
# charge, so this POST is safe to retry after a timeout or a dropped connection.
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 = the image; anything else raises
# 202: still processing. Wait for the same job; never send the image again.
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 it later at /v1/jobs/{job_id}.")
print(remove_background("https://example.com/photo.jpg"))Requiere Python 3 y requests (pip install requests).
- Detener tu script no detiene el trabajo; puede terminar igualmente y cobrarse. Su resultado aparecerá en tu Studio.
- Los límites de tiempo los eliges tú, no son una promesa nuestra; la mayoría de las imágenes terminan en unos segundos.
- El endpoint compatible con remove.bg funciona de otra forma: nunca responde 202 (ver más abajo).
Autenticación
Envía tu clave de API en la cabecera x-api-key. Crea y revoca claves en la página de tu cuenta; cada llamada gasta los créditos de esa cuenta. Todos los endpoints están bajo https://removebackground.dev y aceptan solicitudes CORS, pero CORS no hace que sea seguro poner una clave en una página web: guárdala en tu servidor (ver Seguridad). Los errores son JSON: { "error": { "code": "…", "message": "…" } }.
El contrato completo está publicado como OpenAPI 3.1 (openapi.json), para generadores de clientes, Postman o tests; los asistentes de programación con IA pueden empezar por llms.txt.
POST /v1/remove
En tiempo real. Elimina el fondo de una imagen. Normalmente la imagen terminada es el cuerpo de la respuesta (image/png, image/jpeg o image/webp), por lo general tras unos segundos. Los parámetros pueden ser campos de formulario, claves JSON o valores de query string; también puedes hacer POST de los bytes de la imagen sin procesar con Content-Type: image/jpeg, image/png, image/webp o application/octet-stream. Máximo 25 MB. Consulta Envía tu imagen para cada método de entrada.
| Parámetro | Tipo | Descripción |
|---|---|---|
image_file | file | La imagen (JPG, PNG o WebP), como datos de formulario multipart. |
image_file_b64 | string | La imagen en base64, con o sin el prefijo data:image/…;base64, (25 MB tras decodificar). Práctico desde JSON. |
image_url | string | Una URL pública http(s) de la imagen. La descargamos (hasta 3 redirecciones, 15 s). Si se envían varias, gana image_file, luego image_file_b64, luego image_url y por último el cuerpo sin procesar. |
format | png | jpg | webp | Formato de salida. Por defecto, png. JPG no tiene transparencia: se aplana sobre bg_color o sobre blanco. |
bg_color | color | Rellena el fondo: hex (ffffff, #fff), rgb(255, 255, 255) o white, black, red, green, blue, yellow, gray / grey. transparent (por defecto) lo mantiene transparente. |
size | preview | medium | hd | full | Límite de megapíxeles, mantiene la relación de aspecto y nunca amplía: preview ≤ 0,25 MP, medium ≤ 1,5 MP, hd ≤ 4 MP, full (por defecto) la resolución original (hasta 25 MP). Se ignora si se define width o height. |
crop | true | false | W:H | Recorta al cuadro delimitador del sujeto. Con una relación de aspecto (1:1, 4:5, 4:3, 16:9…), el cuadro se amplía (nunca se reduce) a esa relación alrededor del sujeto; la zona fuera de la foto queda transparente (o con bg_color). Por defecto, false. |
padding | px | fracción | % | Con crop: margen añadido a cada lado. 0.1 o 10% = una décima parte del ancho (izquierda/derecha) y del alto (arriba/abajo) del sujeto; "10%,7.5%" define el horizontal y el vertical por separado; 24px (o un número entero mayor que 1 sin unidad) son píxeles, hasta 500. Por defecto, 0. |
channels | rgba | rgb | alpha | rgba (por defecto): recorte transparente. rgb: opaco, aplanado sobre bg_color o blanco. alpha: máscara PNG en escala de grises (blanco = sujeto), con el mismo tamaño y recorte que el recorte normal. type=mask sigue funcionando como alias de alpha. |
width / height | 1–6000 | Tamaño de salida exacto en píxeles, aplicado después de crop (prevalece sobre size). Si solo indicas uno, el otro sigue la relación de aspecto. Nunca se estira. |
roi | x1 y1 x2 y2 | Región de interés, en px o % (p. ej. 0% 0% 50% 100%). Solo se conserva el sujeto que está dentro; todo lo de fuera pasa a ser fondo. Las coordenadas se refieren a la imagen original. Por defecto: la imagen completa. |
fit | contain | cover | scale-down | Con width y height. contain (por defecto): encaja dentro, centrado, y el resto queda transparente (o con bg_color). cover: llena el cuadro y recorta lo que sobra alrededor del sujeto. scale-down: como contain, pero nunca amplía. |
Las opciones se aplican en este orden: roi, size (o width/height más adelante), crop + padding + relación de aspecto, width/height + fit, después channels o el color de fondo y, por último, el formato. Todas las opciones cuestan el mismo crédito. Los parámetros desconocidos se ignoran.
Ejemplo: JPG en HD sobre blanco, recortado al sujeto con 40 px de margen
curl -X POST https://removebackground.dev/v1/remove \
-H 'x-api-key: YOUR_API_KEY' \
-F 'image_file=@product.jpg' \
-F 'bg_color=ffffff' \
-F 'format=jpg' \
-F 'size=hd' \
-F 'crop=true' \
-F 'padding=40' \
-o product-no-bg.jpgEjemplo: imagen cuadrada para marketplace, sujeto centrado con un 10% de margen
curl -X POST https://removebackground.dev/v1/remove \
-H 'x-api-key: YOUR_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.jpgEjemplo: entrada en base64, salida como máscara alfa
printf '{"image_file_b64":"%s","channels":"alpha"}' "$(base64 < portrait.jpg | tr -d '\n')" > request.json
curl -X POST https://removebackground.dev/v1/remove \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
--data-binary @request.json \
-o portrait-mask.png200 OK
Los bytes de la imagen, con estas cabeceras:
| Cabecera | Significado |
|---|---|
X-Image-Width / X-Image-Height | Tamaño del resultado en píxeles (también se envía como X-Width / X-Height). |
X-Request-ID | Tu X-Request-ID si enviaste uno; si no, un id generado. Indícalo al contactar con soporte. |
X-Processing-Time-Ms | Tiempo dedicado a la solicitud (también X-Processing-Ms). |
X-Matte-Confidence | 0–1: lo nítida que es la máscara (media de |2a − 1| sobre los píxeles, a = alfa). Cerca de 1 es un recorte limpio; valores más bajos indican muchos bordes suaves o dudosos. |
X-Matte-Ambiguous-Ratio | Proporción de píxeles con alfa estrictamente entre 0,1 y 0,9 (pelo, cristal, desenfoque de movimiento). Útil para marcar imágenes que conviene revisar. |
X-Credits-Remaining | Tu saldo después de esta imagen. |
X-Removal-Id | Id del resultado almacenado. |
X-Job-Id | Id del trabajo detrás de la solicitud (se puede usar con /v1/jobs/:id). |
202 Accepted (alternativa cuando la cola es larga)
Si la imagen no está terminada en unos 55 segundos, por ejemplo cuando la cola está inusualmente ocupada, recibes 202 con el JSON { id, status, status_url, result_url } (más Location y Retry-After: 2). Consulta status_url hasta que done sea true y luego descarga result_url. Se te cobra una sola vez, solo cuando la imagen sale bien. No vuelvas a enviar la imagen sin una Idempotency-Key: eso inicia un segundo trabajo. Consulta Gestiona la respuesta para ver un ejemplo completo.
GET /v1/jobs/:id
Estado de un trabajo creado con /v1/remove o /v1/batch. Misma clave; solo ves tus propios trabajos.
| Campo | Significado |
|---|---|
status | queued, processing, succeeded, partial, failed o canceled |
done | true cuando ya no queda nada por ejecutar |
total, succeeded, failed, skipped | recuento de imágenes |
credits_charged | créditos que usó este trabajo (1 por imagen procesada con éxito) |
status_url, result_url | dónde consultar el estado y dónde descargar |
items[] | por imagen: position, input, status, error { code, message } y, si sale bien, removal_id, width, height, format, result_url |
GET /v1/jobs/:id/result
Los bytes de la imagen de un trabajo terminado, con las mismas cabeceras que /v1/remove. ?item=N elige una imagen de un trabajo por lotes (por defecto, 0). Responde 409 not_ready con Retry-After: 2 mientras sigue en curso, o con el error de la propia imagen si falló.
POST /v1/batch
Pon en cola hasta 100 URLs de imágenes como un solo trabajo: JSON { "image_urls": ["https://…", …], "format": "jpg", "bg_color": "ffffff", "size": "hd", "crop": "1:1", "padding": "10%" }, con las mismas opciones que /v1/remove (también channels, width, height y fit). Responde 202 al instante con { id, status, total, invalid, duplicates, status_url }. Consulta el trabajo y después obtén la result_url de cada elemento. 1 crédito por imagen que sale bien; como máximo 3 trabajos por lotes abiertos por cuenta. Guía paso a paso con respuestas de ejemplo en Lotes, de principio a fin.
Endpoint compatible con remove.bg
La API de autoservicio de remove.bg termina el 1 December 2026, 09:00 CET (anuncio). Las integraciones existentes con remove.bg funcionan aquí cambiando una línea: https://api.remove.bg/v1.0/removebg → https://removebackground.dev/v1.0/removebg, con una clave de removebackground.dev en la misma cabecera X-Api-Key. Misma cola, el mismo crédito por imagen procesada con éxito y la misma calidad de resultado que /v1/remove. Guía de migración.
POST /v1.0/removebg
Cuerpo multipart, urlencoded o JSON con los nombres de parámetros de remove.bg. Responde con los bytes de la imagen y las cabeceras de remove.bg, o con { "data": { "result_b64", "foreground_top", "foreground_left", "foreground_width", "foreground_height" } } si envías Accept: application/json. Los errores usan el formato de remove.bg: { "errors": [{ "title", "code", "detail" }] }. A diferencia de /v1/remove, nunca responde 202: espera hasta 110 segundos y luego devuelve un 503 por tiempo de espera. El trabajo sigue en marcha y se cobra si sale bien, así que reintentar esa solicitud inicia un segundo trabajo.
| Parámetro | Estado | Notas |
|---|---|---|
image_file / image_file_b64 / image_url | Compatible | Cuerpos multipart, urlencoded o JSON. JPG, PNG o WebP de hasta 25 MB. |
size | Compatible | auto, full, 4k y 50MP dan la resolución original (hasta 25 MP); preview, small y regular ≈ 0,25 MP; medium 1,5 MP; hd 4 MP. Siempre 1 crédito. |
format | Compatible | auto (PNG si hay transparencia; si no, JPG), png, jpg, webp y zip (color.jpg + alpha.png). |
crop / crop_margin | Compatible | px o % del sujeto, de 1 a 4 valores al estilo CSS ("10% 20%" = vertical, horizontal); como máximo 500px o 50% por lado. |
roi | Compatible | "x1 y1 x2 y2" en px o %: solo se conserva el sujeto dentro de la región. |
scale / position | Compatible | scale del 10% al 100% u original; position center, original o "x% y%". |
channels | Compatible | rgba (recorte) o alpha (máscara en escala de grises). |
bg_color | Compatible | Hex con o sin # (81d4fa), o un nombre de color. Un hex de 8 dígitos conserva el color y descarta su alfa. |
bg_image_url / bg_image_file | Compatible | El recorte se compone sobre tu imagen de fondo, ajustada en modo cover al tamaño de salida. |
Accept: application/json | Compatible | Devuelve { data: { result_b64, foreground_top, foreground_left, foreground_width, foreground_height } }. |
type / type_level | Aceptado, se ignora | El sujeto se detecta automáticamente; X-Type siempre es "other". |
semitransparency | Aceptado, se ignora | Los bordes suaves y las zonas semitransparentes salen tal cual de la máscara del modelo. |
shadow_type / shadow_opacity / add_shadow | Aceptado, se ignora | No se añaden sombras. |
Solicitudes largas | Diferencia | Esperamos hasta 110 segundos; si una imagen no está lista para entonces, recibes un 503 que puedes reintentar (no se cobra salvo que haya terminado). |
Ejemplo
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/removebgCabeceras de respuesta
| Cabecera | Significado |
|---|---|
X-Width / X-Height | Tamaño del resultado en píxeles. |
X-Credits-Charged | Créditos que usó esta imagen: siempre 1 (las imágenes fallidas cuestan 0). |
X-Type | Siempre "other" (la detección del sujeto es automática). |
X-Foreground-Top / -Left / -Width / -Height | Cuadro delimitador del sujeto en el resultado, en píxeles. |
X-Request-ID | Repite tu X-Request-ID, o un id generado. Extra. |
X-Matte-Confidence / X-Matte-Ambiguous-Ratio | Lo limpia que es la máscara (0–1) y la proporción de píxeles suaves. Extra: útil para marcar imágenes que conviene revisar. |
Errores
| Estado | Significado |
|---|---|
400 | Parámetro o imagen no válidos (códigos como invalid_size, invalid_crop_margin, missing_source, file_too_large, unknown_foreground). |
402 | insufficient_credits: recarga en la página de precios. |
403 | auth_failed: falta X-Api-Key o no es válida. |
429 | rate_limit_exceeded. |
500 / 503 | El procesamiento falló, superó el tiempo de espera o el servicio no está disponible momentáneamente. Reintenta; las imágenes fallidas son gratis. |
GET /v1.0/account
Tu saldo con el formato de cuenta de remove.bg: { "data": { "attributes": { "credits": { "total", "subscription": 0, "payg", "enterprise": 0 }, "api": { "free_calls": 0, "sizes": "all" } } } }. Todos los créditos son de pago por uso y no caducan nunca, así que total es igual a payg. GET https://removebackground.dev/v1.0/account con tu X-Api-Key.
Errores (endpoints /v1)
Las imágenes fallidas nunca se cobran.
| Estado | Códigos | Significado |
|---|---|---|
400 | missing_image, invalid_url, invalid_body, invalid_json, invalid_image_b64, invalid_format, invalid_bg_color, invalid_size, invalid_crop, invalid_padding, invalid_type, invalid_channels, invalid_width, invalid_height, invalid_fit, invalid_roi, fetch_failed, fetch_timeout, rejected, too_many_images, invalid_images | La solicitud o la URL de la imagen no se pueden usar. |
401 | unauthorized | x-api-key ausente, incorrecta o revocada. |
402 | insufficient_credits, out_of_credits | Tu saldo está a cero. Recarga en la página de precios. |
404 | not_found | Ese trabajo no existe (o no es tuyo). |
409 | not_ready, canceled, idempotency_key_reused | GET …/result mientras el trabajo sigue en curso (reintenta tras 2 s), el trabajo se canceló o se reutilizó una Idempotency-Key para otra solicitud. |
410 | result_unavailable | El resultado se eliminó o caducó. |
413 | too_large | La imagen pesa más de 25 MB. |
422 | processing_failed, invalid_image, missing_upload | El archivo no es una imagen legible. No se cobra. |
429 | rate_limited, too_many_batches | Has superado el límite de solicitudes por cuenta (espera lo que indique Retry-After) o ya tienes 3 trabajos por lotes en curso. |
502 | model_unavailable, upstream_error, … | No pudimos procesar la imagen tras varios reintentos. No se cobra. |
503 | server_paused, unavailable | La API está en pausa (antes del lanzamiento) o no está disponible momentáneamente. Reintenta más tarde. |
Lotes, de principio a fin
1. Enviar
curl -X POST https://removebackground.dev/v1/batch \
-H "x-api-key: $REMOVEBG_API_KEY" \
-H 'Content-Type: application/json' \
-d '{ "image_urls": ["https://example.com/front.jpg", "https://example.com/back.jpg"], "format": "png", "size": "hd" }'Hasta 100 URLs públicas de imágenes, más cualquiera de las opciones de /v1/remove. Las dos URLs de ejemplo de arriba costarían hasta 2 créditos si fueran imágenes reales. La respuesta llega al instante:
202 Accepted
{
"id": "3f6c2a9e-8d1b-4c7a-9e2f-5b8d0a1c4e77",
"status": "queued",
"total": 2,
"invalid": 0,
"duplicates": 0,
"status_url": "https://removebackground.dev/v1/jobs/3f6c2a9e-8d1b-4c7a-9e2f-5b8d0a1c4e77"
}invalid cuenta las entradas que no son URLs http(s) y duplicates cuenta las repetidas; ambas se descartan y nunca se cobran. Guarda el id: es la forma de retomar el trabajo tras un reinicio.
2. Consulta el trabajo
GET /v1/jobs/:id cada pocos segundos hasta que done sea true. status pasa de queued a processing y termina como succeeded, partial (algunas imágenes fallaron) o failed. Un elemento que se está reintentando muestra retrying.
{
"id": "3f6c2a9e-…",
"status": "partial",
"done": true,
"total": 2, "succeeded": 1, "failed": 1, "skipped": 0,
"credits_charged": 1,
"items": [
{ "position": 0, "input": "https://example.com/front.jpg", "status": "succeeded",
"removal_id": "…", "width": 1600, "height": 1200, "format": "png",
"result_url": "https://removebackground.dev/v1/jobs/3f6c2a9e-…/result?item=0" },
{ "position": 1, "input": "https://example.com/back.jpg", "status": "failed",
"error": { "code": "fetch_failed", "message": "…" } }
]
}3. Descarga cada resultado
GET /v1/jobs/:id/result?item=N para cada elemento correcto (o usa su result_url). item es la position empezando en cero. Las posiciones siguen tu lista después de quitar las URLs no válidas y repetidas, así que si alguno de esos contadores es mayor que 0, empareja los resultados por input y no por índice.
- Un lote deja de contar para el límite de 3 lotes abiertos en cuanto
donees true. - La API no tiene endpoint de cancelación, webhooks ni descarga en ZIP. Los lotes iniciados desde la página Bulk se pueden cancelar o descargar en ZIP allí.
Reintentos, duplicados y facturación
Envía una Idempotency-Key y los reintentos no cobrarán dos veces. Añade una cabecera Idempotency-Key (cualquier cadena única de hasta 255 caracteres, como un UUID) a POST /v1/remove o POST /v1/batch, una clave por imagen o por lote. Si vuelves a enviar la misma solicitud con la misma clave, recibes el trabajo que creó la primera, con Idempotent-Replayed: true: ni trabajo nuevo ni cargo nuevo, aunque la primera solicitud siga en curso. La misma clave con otra imagen u otras opciones responde 409 idempotency_key_reused. Las claves pertenecen a tu cuenta y no caducan.
Sin clave, cada POST crea un trabajo nuevo, y cada trabajo que sale bien cuesta 1 crédito (el endpoint compatible con remove.bg POST /v1.0/removebg no admite claves). Consultar un trabajo (GET /v1/jobs/…) siempre es gratis y se puede repetir sin riesgo.
IDEMPOTENCY_KEY=$(uuidgen) # one per image; send the same one on every retry
curl -X POST https://removebackground.dev/v1/remove \
-H "x-api-key: $REMOVEBG_API_KEY" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-F 'image_file=@photo.jpg' \
-o photo-no-bg.pngQué cuesta un crédito
| Situación | Cargo |
|---|---|
| Solicitud rechazada antes de procesarse (clave incorrecta, opción no válida, demasiado grande, sin créditos) | Gratis. |
| La imagen no se puede procesar (422 imagen no válida, 502 tras nuestros reintentos) | Gratis. |
| La imagen sale bien | 1 crédito, cobrado una sola vez, cuando sale bien. Nuestros reintentos internos no añaden cargos. |
| Recibes un 202 | Nada por ahora. El trabajo sigue en marcha y solo se cobra 1 crédito si sale bien. |
| Tu cliente agota el tiempo de espera o se desconecta mientras espera | El trabajo sigue en marcha y se cobra si sale bien. El resultado aparece en tu Studio. |
| Envías la misma solicitud dos veces con la misma Idempotency-Key | Un solo trabajo, como máximo 1 crédito. La repetición recibe el mismo trabajo (cabecera Idempotent-Replayed: true). |
| Envías la misma imagen dos veces sin clave | Dos trabajos distintos; cada uno que sale bien cuesta 1 crédito. |
| Vuelves a descargar un resultado terminado | Gratis, tantas veces como quieras mientras esté almacenado. |
| Un lote sale bien en parte | 1 crédito por imagen que salió bien; credits_charged en el trabajo muestra el total. |
| Un lote incluye la misma URL dos veces | Las repeticiones dentro de un mismo lote se descartan antes de entrar en la cola y nunca se cobran. Las URLs idénticas en lotes distintos son trabajos separados. |
| Te quedas sin créditos durante un lote | Las imágenes ya terminadas quedan pagadas; el resto se marca como omitido (out_of_credits) y es gratis. Compra créditos y envía las URLs restantes en un lote nuevo. |
Cuándo reintentar
| Qué pasó | Qué hacer |
|---|---|
| GET /v1/jobs/:id o …/result falla (error de red, 5xx) | Puedes reintentar sin riesgo: consultar un trabajo nunca crea trabajo ni cargos. Espera un poco entre intentos. |
| GET …/result responde 409 not_ready | Espera lo que indique Retry-After (2 s) y vuelve a consultar. No reenvíes la imagen. |
| GET …/result responde 410 result_unavailable | El resultado almacenado se eliminó. Volver a procesar la imagen es un trabajo nuevo y cuesta 1 crédito. |
| POST responde 400, 413 o 422 | Corrige primero la solicitud o la imagen; si la envías sin cambios, recibirás la misma respuesta. |
| POST responde 401 o 402 | Corrige la clave o recarga créditos. No lo repitas en bucle. |
| POST responde 429 rate_limited | Espera los segundos que indique Retry-After y vuelve a enviarla (con la misma Idempotency-Key). ¿Más de 60 imágenes por minuto? Usa POST /v1/batch: una sola solicitud para hasta 100. |
| POST /v1/batch responde 429 too_many_batches | Espera a que termine uno de tus 3 lotes abiertos (consúltalo) y luego envía el nuevo. |
| POST /v1/… responde 503 (unavailable, server_paused) | No se creó ningún trabajo. Reintenta tras una breve espera. (El endpoint compatible con remove.bg es distinto: su 503 por tiempo de espera significa que el trabajo sigue en marcha). |
| POST /v1/remove responde 502 | Ese trabajo falló y no se cobró. Un reintento es un trabajo nuevo. |
| El POST agota el tiempo de espera, se corta la conexión o recibes un 500 | Con Idempotency-Key: reenvía la misma solicitud con la misma clave y recibirás el trabajo original. Sin ella, puede que el trabajo ya exista y se cobre: revisa primero tu Studio. |
| POST responde 409 idempotency_key_reused | Esa clave ya se usó con otra imagen u otras opciones. Genera una clave nueva para cada imagen nueva. |
Límites y almacenamiento
| Límite | Valor | Error si se supera |
|---|---|---|
| Archivo de imagen | 25 MB (25 × 1024 × 1024 bytes); JPG, PNG o WebP, detectado a partir de los bytes del archivo | 413 too_large · 422 processing_failed |
| Cuerpo Base64 / JSON | 25 MB tras decodificar (el cuerpo de la solicitud puede ocupar un tercio más) | 413 too_large |
| Resolución de entrada | Las imágenes de más de 25 MP se reducen a 25 MP antes de procesarse | — |
| Tamaño de salida | width y height, cada uno de 1 a 6000 px | 400 invalid_width / invalid_height |
| Descarga de image_url | solo http(s), tiempo de espera de 15 s, hasta 3 redirecciones; se rechazan las direcciones privadas, de loopback y link-local, en cada redirección | 400 invalid_url · fetch_failed · fetch_timeout |
| Espera en POST /v1/remove | Unos 55 s; después, 202 con el id del trabajo | 202 |
| Tamaño del lote | 100 URLs de imágenes por POST /v1/batch | 400 too_many_images |
| Lotes abiertos | 3 trabajos de varias imágenes sin terminar por cuenta (las imágenes individuales no cuentan) | 429 too_many_batches |
| Frecuencia de solicitudes | 60 solicitudes por minuto por cuenta, sumando POST /v1/remove, /v1/batch y /v1.0/removebg. Un lote cuenta una vez, sea cual sea su tamaño. Consultar trabajos no tiene límite | 429 rate_limited (con Retry-After) |
Cuánto tiempo se conservan los resultados
Cada resultado se guarda de forma privada en tu cuenta durante 48 horas después de crearse y luego se elimina. Hasta entonces puedes volver a descargarlo gratis con GET /v1/jobs/:id/result o desde tu Studio. Después, los enlaces de resultado responden 410 result_unavailable; volver a procesar la imagen es un trabajo nuevo. Los registros de estado del trabajo se pueden seguir consultando cuando la imagen ya no existe. Consulta la política de privacidad para ver cómo se gestionan las subidas; no usamos tus imágenes para entrenar modelos.
Seguridad
Guarda tu clave de API en un servidor que controles. No la pongas en código del navegador, apps móviles, repositorios públicos ni URLs. Para que tus propios usuarios quiten fondos, envía sus imágenes a través de tu backend y añade ahí tu propio inicio de sesión y tus límites de gasto.
- La API admite CORS para que funcione desde herramientas y código del servidor. Eso no hace que sea seguro poner una clave en una página web: cualquiera puede leerla ahí.
- Todas las claves de una cuenta gastan el mismo saldo de créditos. Crea una clave distinta por app o entorno en la página de tu cuenta, para poder revocar una sin romper las demás.
- Si se filtra una clave, revócala enseguida en la página de tu cuenta (deja de funcionar al instante) y crea una nueva. Solo guardamos un hash de cada clave, así que no podemos volver a mostrártela.
Solución de problemas
| Síntoma | Qué está pasando |
|---|---|
| Mi PNG no se abre | El cuerpo era JSON (un trabajo 202 o un error), no una imagen. Comprueba el estado HTTP y el Content-Type antes de guardar. |
| Mi script agotó el tiempo de espera, pero la imagen aparece en Studio | El trabajo siguió en marcha cuando dejaste de esperar. Obtén el resultado con su id de trabajo en lugar de reenviarla. |
| Me cobraron dos veces por una imagen | Se envió dos veces sin Idempotency-Key (a menudo por un reintento automático tras un tiempo de espera agotado). Usa una clave por imagen y reutilízala en los reintentos. |
| La URL se abre en mi navegador, pero la API no puede descargarla | Puede que el servidor requiera cookies o inicio de sesión, bloquee servidores, redirija más de 3 veces o tarde más de 15 s, o que la URL firmada haya caducado. Sube el archivo en su lugar. |
| Mi lote se detuvo a medias | Revisa items[] en el trabajo: los elementos fallidos tienen un código de error; los omitidos con out_of_credits indican que se agotó el saldo. |
| Una opción parece no hacer nada | Los nombres de parámetros desconocidos se ignoran sin avisar. Comprueba la ortografía con la tabla de parámetros. En /v1.0/removebg, algunas opciones de remove.bg se aceptan pero se ignoran (ver esa tabla). |
| El fondo no es transparente | JPG no admite transparencia. Usa format=png o webp y no definas bg_color. |
| El enlace del resultado devuelve 410 | El resultado almacenado se eliminó. Volver a procesarlo cuesta 1 crédito. |