Saltar al contenido

Fondo transparente con GPT Image 2 y 2.5: modelo, código y fallos

Un «not supported», un fondo pintado o un PNG opaco tienen causas distintas: pasarela, prompt, guardado o visor. Elige modelo y comprueba el alfa en el archivo.

•••11 min de lectura•Guías de API
Tetera azul de cerámica sobre una cuadrícula de transparencia junto a una petición JSON con background transparent, insignias PNG y WebP, un panel para comprobar el archivo y la misma tetera sobre fondos blanco, negro, azul y amarillo

Sí, puedes generar un PNG o WebP con fondo transparente con los modelos de imagen de OpenAI. A 25 de septiembre de 2026, la referencia de la Images API lo recoge así:

  • gpt-image-2.5-flare y gpt-image-2.5-sunburst: admiten background: "transparent" sin ninguna etiqueta de preview. Son los modelos que OpenAI recomienda para integraciones nuevas.
  • gpt-image-2 (y su instantánea gpt-image-2-2026-04-21): la transparencia funciona, pero sigue en preview, es decir, en acceso preliminar sin la madurez de una función estable.
  • ChatGPT: según la ayuda de OpenAI, ChatGPT Images puede seguir la instrucción de dejar el fondo transparente. Lo que no está documentado es si el archivo que descargas conserva el canal alfa; compruébalo antes de usarlo.

En la API hay dos condiciones fijas: pedir la transparencia de forma explícita (el valor por defecto, auto, no la pide) y usar png o webp, porque JPEG no tiene canal alfa. Si ya haces eso y aun así falla, el síntoma suele indicar en qué paso está el problema: un servicio intermedio que rechaza el parámetro, un prompt que describe un fondo, un archivo que se guardó mal o un visor que pinta negro detrás.

Qué modelo y qué vía elegir para el fondo transparente

Tu situaciónQué usarPor qué
Empiezas una integración nuevagpt-image-2.5-flare (rápido, para el día a día) o gpt-image-2.5-sunburst (cuando importa la precisión en ediciones)Transparencia admitida sin preview; OpenAI los recomienda para proyectos nuevos
Ya tienes código con gpt-image-2 que funcionaPuedes seguir con él, sabiendo que la transparencia está en previewEl modelo no está retirado ni tiene fecha de cierre
Necesitas la Batch APIgpt-image-2Los modelos 2.5 no admiten v1/batch; gpt-image-2 sí
No programas y solo necesitas un par de recursosChatGPT, con comprobación del archivo descargadoEs la vía más corta, pero OpenAI no documenta el formato ni el alfa de la descarga

La diferencia entre Flare y Sunburst que describe la guía de generación de imágenes es de enfoque (velocidad frente a precisión en ediciones); no hay datos públicos que comparen la calidad del contorno transparente entre los dos. Si te importa ese detalle, genera el mismo recurso con ambos y compáralos con la comprobación de más abajo.

El fondo transparente no aparece como recargo en la página de precios: pagas los mismos tokens de imagen que por una salida opaca. Las tarifas por token son idénticas en los tres modelos, pero el consumo no: con la calculadora oficial, una imagen de 1024×1024 en calidad medium cuesta USD 0,01317 de salida con 2.5 frente a USD 0,05268 con gpt-image-2. Los nombres de calidad no equivalen entre generaciones, así que para comparar costes con detalle tienes Precio por imagen de la API de OpenAI: GPT Image 2.5 y GPT Image 2, y para decidir entre los dos modelos nuevos, GPT Image 2.5: qué cambia, cuánto cuesta y cómo usar la API.

Por qué hay textos que dicen que GPT Image 2 no admite transparencia

La respuesta cambió dos veces en poco más de un mes. Hasta agosto de 2026, gpt-image-2 no ofrecía transparencia. En agosto, OpenAI la abrió en preview para ese modelo. El 8 de septiembre de 2026 llegaron las instantáneas de GPT Image 2.5, con la transparencia ya admitida, y ChatGPT Images 2.5 se lanzó esa misma semana. Un texto escrito antes de agosto dirá que no se puede, y uno de agosto hablará solo de la preview; antes de fiarte, mira su fecha y a qué modelo se refiere.

Petición y guardado en PNG con fondo transparente sin perder el alfa

El siguiente script llama directamente a la Images API de OpenAI, que está disponible en España y México según la lista de países admitidos. Necesitas Python 3, una clave en la variable OPENAI_API_KEY y dos paquetes:

bash
python -m pip install requests Pillow

Guárdalo como generar.py y ejecútalo con python generar.py png o python generar.py webp. Cada ejecución es una generación real que se factura en tu cuenta.

python
import base64
import io
import os
import sys
from pathlib import Path

import requests
from PIL import Image

BASE_URL = os.environ.get("IMAGES_BASE_URL", "https://api.openai.com/v1" )
MODELO = os.environ.get("IMAGE_MODEL", "gpt-image-2.5-flare")
FORMATO = sys.argv[1] if len(sys.argv) > 1 else "png"
if FORMATO not in ("png", "webp"):
    sys.exit("Uso: python generar.py png|webp")

PROMPT = (
    "Pegatina de una tetera de cerámica azul con flores blancas, "
    "sujeto aislado y completo sobre un fondo totalmente transparente. "
    "Sin escenario, sin fondo de color, sin cuadrícula de ajedrez, "
    "sin sombra proyectada, sin texto y sin marca de agua."
)

respuesta = requests.post(
    f"{BASE_URL}/images/generations",
    headers={"Authorization": f"Bearer {os.environ['OPENAI_API_KEY']}"},
    json={
        "model": MODELO,
        "prompt": PROMPT,
        "background": "transparent",
        "output_format": FORMATO,
        "size": "1024x1024",
        "quality": "medium",
    },
    timeout=300,
)
if respuesta.status_code != 200:
    sys.exit(f"HTTP {respuesta.status_code}: {respuesta.text[:500]}")

datos = respuesta.json()
print("background:", datos.get("background"))
print("output_format:", datos.get("output_format"))

b64 = (datos.get("data") or [{}])[0].get("b64_json")
if not b64:
    sys.exit("La respuesta no trae data[0].b64_json")

contenido = base64.b64decode(b64)
with Image.open(io.BytesIO(contenido)) as img:
    real = img.format  # "PNG", "WEBP" o "JPEG"

extension = {"PNG": "png", "WEBP": "webp", "JPEG": "jpg"}.get(real, "bin")
destino = Path(f"tetera.{extension}")
destino.write_bytes(contenido)  # los bytes tal cual, sin recodificar
print(f"Guardado {destino}: {real}, {len(contenido)} bytes")

if datos.get("background") == "opaque":
    print("AVISO: el servicio aplicó un fondo opaco")
if real != FORMATO.upper():
    print(f"AVISO: pediste {FORMATO} y llegó {real}")

Tres detalles del script te ahorran diagnósticos equivocados:

  1. Lee el campo background de la respuesta. La API devuelve en el JSON el ajuste que aplicó: "transparent" u "opaque", junto a output_format. Si ves opaque, el problema está en la petición o en el servicio, no en tu código de guardado. Ese campo informa del ajuste, no de la calidad del recorte: el contorno lo compruebas después en el archivo.
  2. Guarda los bytes decodificados sin pasar por un editor. La imagen llega en base64 en data[0].b64_json (con los modelos GPT Image no existe response_format ni URL de descarga). Escribir esos bytes directamente es lo que recomienda la guía de prompts de OpenAI: cualquier paso por RGB elimina la transparencia.
  3. Nombra el archivo según su contenido real. El script abre los bytes con Pillow y usa la extensión del formato detectado, no la que pediste. Cambiar el nombre de tetera.webp a tetera.png no convierte nada.

Con PNG no envíes output_compression; ese parámetro solo sirve para WebP y JPEG. Si quieres WebP comprimido, añade "output_compression": 80 (de 0 a 100, por defecto 100) únicamente cuando FORMATO sea webp. Es un ajuste del codificador, no una promesa de que el archivo pese un 80 % menos.

Las variables IMAGE_MODEL e IMAGES_BASE_URL sirven para repetir exactamente la misma petición con gpt-image-2, con Sunburst o contra otro servicio compatible (con la clave de ese servicio en OPENAI_API_KEY). Así distingues un fallo del modelo de un fallo de la vía que usas.

El prompt manda sobre el parámetro

OpenAI lo advierte en su cookbook de recursos transparentes: si el prompt describe un fondo, una escena o un color de fondo, el modelo puede pintarlo aunque envíes background: "transparent". Por eso el prompt del ejemplo pide un sujeto aislado sobre fondo totalmente transparente y excluye escenario, fondo de color, cuadrícula y sombras. Callar el fondo por completo no es lo que aconseja OpenAI: su recomendación es pedir la transparencia y excluir de forma explícita lo que no quieres.

Si tu recurso necesita sombra o reflejo, pídelos expresamente y revisa el resultado; si no, suele ser más sencillo añadir la sombra después en tu diseño o con CSS.

Esquema en tres pasos de la petición a la API, el guardado del archivo y la comprobación del canal alfa, con una tabla que compara PNG, WebP y JPEG y una tetera sobre fondos claro, oscuro y azul

Comprueba el canal alfa en el propio archivo

Una cuadrícula en el visor, la extensión .png o un HTTP 200 no demuestran que haya transparencia. Lo que cuenta es el canal alfa de los píxeles: 0 es totalmente transparente, 255 es opaco y los valores intermedios son semitransparencias (bordes suaves, cristal, humo, pelo).

Guarda esto como comprobar.py y ejecútalo sobre cualquier archivo: el que acabas de generar, el que descargaste de ChatGPT o el que sirve tu web.

python
import sys
from pathlib import Path

from PIL import Image

ruta = Path(sys.argv[1])
with Image.open(ruta) as img:
    formato, modo = img.format, img.mode
    rgba = img.convert("RGBA")  # si no había alfa, lo crea opaco (255)

hist = rgba.getchannel("A").histogram()
total = rgba.width * rgba.height
transparentes, opacos = hist[0], hist[255]
parciales = total - transparentes - opacos

print(f"{ruta.name}: {formato}, modo {modo}, {rgba.width}x{rgba.height}")
print(f"alfa 0: {transparentes} | alfa 1-254: {parciales} | alfa 255: {opacos}")

if opacos == total:
    print("OPACO: el archivo no tiene ningún píxel transparente")
elif transparentes == total:
    print("VACÍO: todo es transparente, no hay sujeto visible")
else:
    print(f"CON ALFA: {100 * transparentes / total:.1f} % totalmente transparente")

# Composición sobre blanco, negro y magenta para revisar bordes
colores = [(255, 255, 255), (0, 0, 0), (255, 0, 255)]
ancho, alto = rgba.size
tira = Image.new("RGB", (ancho * len(colores), alto))
for i, color in enumerate(colores):
    fondo = Image.new("RGBA", rgba.size, color + (255,))
    tira.paste(Image.alpha_composite(fondo, rgba).convert("RGB"), (i * ancho, 0))
salida = ruta.with_name(f"{ruta.stem}-{ruta.suffix.lstrip('.')}-fondos.png")
tira.save(salida)
print(f"Revisa {salida}")

Cómo leer el resultado:

  • OPACO: no hay transparencia en el archivo. Convertir a RGBA no lo arregla, porque solo añade un alfa de 255 en todos los píxeles; el fondo blanco o negro sigue formando parte de la imagen.
  • VACÍO: el archivo es transparente, pero no contiene nada. Hay que regenerar.
  • CON ALFA: hay transparencia real. Ahora abre la tira de tres fondos. Un halo claro sobre negro o un borde oscuro sobre blanco indica un contorno contaminado; una cuadrícula que se ve igual sobre los tres colores está pintada dentro de la imagen, no es transparencia.

El porcentaje de píxeles totalmente transparentes depende del recurso: una pegatina centrada tendrá mucho margen vacío; un gráfico a toda página o un objeto de cristal, poco. No hay un umbral universal, por eso el script no exige ninguno.

Comprobación del canal alfa de una tetera: histograma del alfa, detalle ampliado del borde, la tetera sobre fondos blanco, oscuro y amarillo y tres casos erróneos marcados como PNG opaco, archivo vacío y bordes con halo

Fondo opaco, error 400 o halo: diagnóstico por síntoma

SíntomaCausa probableQué hacer
HTTP 400 con Transparent background is not supported for this modelEl servicio que usas entre tu código y OpenAI no admite o no reenvía el parámetro, o el modelo pedido no es uno de los que lo admitenRepite la petición directamente contra api.openai.com con el mismo modelo. Si ahí funciona, el límite está en el intermediario
HTTP 200 y background: "opaque" en la respuestaNo se envió transparent (quizá quedó en auto) o el servicio lo sustituyóRevisa el cuerpo que realmente sale de tu código y el modelo
La respuesta no trae el campo backgroundEl servicio no devuelve ese campoPasa directamente a comprobar.py
transparent en la respuesta, pero la imagen tiene escena, color de fondo o cuadrícula pintadaEl prompt describía un fondo, o no excluía la cuadrículaReescribe el prompt: sujeto aislado, fondo totalmente transparente, sin escenario ni cuadrícula
comprobar.py dice OPACOPediste o recibiste JPEG, el archivo pasó por RGB o es una captura de pantallaGuarda los bytes originales en PNG o WebP; una captura nunca conserva el alfa
comprobar.py dice VACÍOLa generación no produjo sujeto visible o una transformación lo borróCompara con el archivo recién decodificado y regenera si hace falta
Se ve con fondo negro o blanco, pero comprobar.py dice CON ALFAEs el color que el visor pone detrásNo hay nada que arreglar; revisa la tira de fondos
El original está bien, pero en tu web aparece con fondoEl CMS, el CDN o el generador de miniaturas convierte a JPEG o elimina el alfaDescarga la copia que sirve tu web y pásale comprobar.py
Hay alfa, pero el contorno tiene haloRecorte imperfecto en los píxeles semitransparentesRegenera o prueba otra calidad; para una foto de producto exacta, valora una herramienta de recorte específica

El error de la primera fila merece una aclaración. La documentación de OpenAI admite la transparencia en los tres modelos, pero cada servicio intermedio decide qué parámetros acepta. A 25 de septiembre de 2026, la ficha de openai/gpt-image-2 en Cloudflare Workers AI indica que ese modelo no admite fondos transparentes en su plataforma, y en un relé autoalojado de código abierto se ha documentado ese mismo 400 incluso con los modelos 2.5. Que un servicio exponga el nombre del modelo no significa que reenvíe todas sus opciones; cuando el intermediario va por detrás de OpenAI, el código no tiene nada que corregir.

Cuando tengas que reportar un fallo, guarda el modelo, la URL base, el cuerpo enviado, la respuesta JSON completa (sin la clave) y el archivo original sin tocar.

Si la API responde con otros errores antes de llegar a la imagen, GPT Image 2: cómo resolver el error de organización sin verificar cubre el aviso «Your organization must be verified» y GPT Image 2: cómo resolver invalid size y obtener una imagen de 1024×576, los tamaños rechazados.

ChatGPT: pide el fondo transparente y comprueba la descarga

La página de ayuda Images in ChatGPT dice que ChatGPT Images puede seguir instrucciones para «make the background transparent». Basta con pedirlo en la conversación, por ejemplo: «Genera un icono de una tetera azul, aislado, con el fondo totalmente transparente y sin cuadrícula». También puedes subir una imagen y pedir que quite el fondo.

La ayuda no dice en qué formato se descarga el archivo ni si conserva un canal alfa real. Usa el botón Guardar para descargar el archivo (no hagas una captura) y pásale comprobar.py, o ábrelo en un editor con capas y pon una capa de color debajo. Si no hay alfa, la vía fiable es la API. Para saber cuándo te basta ChatGPT y cuándo compensa pasar a la API, tienes Generador de imágenes de ChatGPT: ruta oficial, herramientas gratis y límite del API.

Quitar el fondo de una imagen que ya tienes

El endpoint /v1/images/edits acepta el mismo background: "transparent". Coloca tu foto en producto.png junto al script:

python
import base64
import os

import requests

BASE_URL = os.environ.get("IMAGES_BASE_URL", "https://api.openai.com/v1" )

with open("producto.png", "rb") as foto:
    respuesta = requests.post(
        f"{BASE_URL}/images/edits",
        headers={"Authorization": f"Bearer {os.environ['OPENAI_API_KEY']}"},
        data={
            "model": "gpt-image-2.5-sunburst",
            "prompt": (
                "Elimina todo el fondo y deja solo el producto sobre un fondo "
                "totalmente transparente. Conserva su forma, sus colores y el "
                "texto de la etiqueta. Sin mesa, sin pared, sin sombra y sin cuadrícula."
            ),
            "background": "transparent",
            "output_format": "png",
        },
        files={"image": ("producto.png", foto, "image/png")},
        timeout=300,
    )
respuesta.raise_for_status()
datos = respuesta.json()
print("background:", datos.get("background"))
with open("producto-sin-fondo.png", "wb") as salida:
    salida.write(base64.b64decode(datos["data"][0]["b64_json"]))

Ten en cuenta que el resultado es una imagen regenerada, no el recorte de tu foto: el modelo puede alterar ligeramente la forma, el color o el texto de una etiqueta, y la máscara solo orienta la edición, no la delimita píxel a píxel. Si el producto tiene que quedar idéntico al original (catálogos, envases con marca), compáralo a simple vista con la foto, y si cambia, usa una herramienta de recorte específica o una máscara manual sobre el original.

En cada edición posterior repite la instrucción de conservar el fondo transparente; si no, un retoque de color puede devolverte un fondo nuevo. La mecánica de archivos, formularios y máscaras está en Editar imágenes con GPT Image 2: variations y errores de dall-e-2.

PNG o WebP

Los dos formatos conservan la transparencia; la elección depende de a dónde va el archivo:

  • PNG si el recurso va a un editor, a una presentación o a otra persona que lo seguirá retocando. Es el formato por defecto de la API y no admite output_compression.
  • WebP si va directamente a una web. Admite transparencia tanto con pérdida como sin pérdida, según la documentación de WebP.

No hace falta volver a generar para cambiar de formato. Si tienes un PNG que ya pasó la comprobación, conviértelo en local:

python
from PIL import Image

with Image.open("tetera.png") as original:
    original.save("tetera.webp", format="WEBP", lossless=True, exact=True)

En el codificador WebP de Pillow, lossless=True usa compresión sin pérdida y exact=True conserva los valores de color de los píxeles transparentes. Un WebP sin pérdida no siempre pesa menos que el PNG original; mide el tuyo. Después, pasa comprobar.py también sobre el WebP. Si alguien te pide un JPEG, compón la imagen sobre el color que corresponda y guarda aparte el original transparente.

Si tus recursos transparentes acaban en un PSD con capas, el siguiente paso está en De GPT Image 2 a un PSD editable: prepara las capas para la próxima revisión.

Si usas un proveedor externo

La vía de referencia es la API de OpenAI directa. Si trabajas con un proveedor externo y el tuyo rechaza la transparencia con GPT Image 2.5, cualquier alternativa tiene que pasar la misma prueba antes de integrarla. Por ejemplo, la documentación de laozhang.ai afirma que sus modelos gpt-image-2.5-flare-vip y gpt-image-2.5-sunburst-vip generan PNG transparentes y quitan el fondo en ediciones con background: "transparent", con un precio de USD 0,03 por llamada y sin soporte de mask. Son datos del proveedor, no una garantía de calidad ni de disponibilidad. Para probarlo, ejecuta generar.py con IMAGES_BASE_URL=https://api.laozhang.ai/v1 e IMAGE_MODEL=gpt-image-2.5-flare-vip, y da el resultado por bueno solo si comprobar.py encuentra alfa y la tira de fondos sale limpia.

Preguntas frecuentes

¿GPT Image 2 admite fondo transparente?

Sí, en preview: con background: "transparent" y salida png o webp, gpt-image-2 puede devolver un archivo con canal alfa. Si empiezas desde cero, los modelos GPT Image 2.5 (Flare y Sunburst) tienen la función admitida sin esa etiqueta y son los que OpenAI recomienda para proyectos nuevos.

¿Cuesta más pedir el fondo transparente?

La página de precios de OpenAI no muestra ningún recargo por transparencia: pagas los tokens de imagen como en cualquier generación. Lo que sí cambia el coste es el modelo y la calidad elegidos.

¿Por qué mi PNG se ve con fondo negro?

Muchas veces es el visor, que pinta negro detrás de los píxeles transparentes. Si comprobar.py indica CON ALFA, el archivo está bien; si indica OPACO, el negro forma parte de la imagen y hay que revisar la petición o el guardado.

¿Puedo pedir transparencia en JPEG?

No. JPEG no tiene canal alfa, así que la transparencia exige png o webp. La respuesta exacta de la API si combinas jpeg con transparent no está documentada; evita esa combinación.

¿Encontraste un error o un problema que el artículo no cubre? Envía la URL del artículo y lo que viste a hi@laozhang.ai. Lo revisamos y actualizamos el artículo.