# Nano Banana Pro API: tutorial en Python, edición y precio

> Llama a Nano Banana Pro desde Python: id del modelo, image_size e input.image, la opción 4K, el precio por imagen de Google y el JSON de cada llamada.

- Canonical HTML: https://omniakey.com/es/blog/nano-banana-pro-api
- Markdown: https://omniakey.com/es/blog/nano-banana-pro-api.md
- Published: 2026-11-03 (updated 2026-11-03)
- Author: Kiki, COO at OmniaKey
- Language: es
- Category: API setup
- Reading time: 9 min
- All posts: https://omniakey.com/blog/llms.txt

---

Nano Banana Pro es `gemini-3-pro-image` de Google, y en OmniaKey se llama con un solo `POST /v1/media/tasks`. Nuestras tres pruebas en 3:4 salieron a 896x1200, 1792x2400 y 3584x4800, y todas las palabras del póster estaban bien escritas.

## Respuesta corta

- **Modelo:** `gemini-3-pro-image` es el id GA de Google. La ficha del modelo en Vertex indica una fecha de lanzamiento del 28 de mayo de 2026.
- **Llamada:** envía `POST https://api.omniakey.com/v1/media/tasks` con una `Idempotency-Key`, consulta `GET /v1/media/tasks/{id}` hasta que el estado sea succeeded y descarga `assets[0].url`.
- **Parámetros:** `parameters.aspect_ratio` y `parameters.image_size`; los valores de tamaño son 1K, 2K y 4K, con la K en mayúscula.
- **Límite de la petición:** 1 MiB para todo el cuerpo, incluidos los datos de imagen en Base64.
- **Precio de Google:** $0.134 por imagen de 1K/2K y $0.24 por imagen de 4K, según la página de precios de la API Gemini.
- **Nuestros tokens:** las tres tareas informaron de 1,133, 1,225 y 2,480 tokens de salida. A $120 por millón de tokens de imagen, son $0.136, $0.147 y $0.298.
- **Edición:** usa `operation: "edit"` y pon la imagen de origen en `input.image` como `{data, mime_type}`.

La [página del modelo Nano Banana Pro](https://omniakey.com/es/gemini-3-pro-image) en OmniaKey también acepta `gemini-3-pro-image-preview`, el id de la instantánea anterior, al mismo precio.

## El id del modelo y lo que necesitas

El id que va en tu código es `gemini-3-pro-image`. La [ficha del modelo en Vertex](https://cloud.google.com/vertex-ai/generative-ai/docs/models/gemini/3-pro-image) lo lista con etapa de lanzamiento GA y fecha del 28 de mayo de 2026. Admite salida en 1K, 2K y 4K.

El id -preview apunta al mismo modelo. La [tabla de modelos de imagen](https://docs.omniakey.com/es/media/image) de OmniaKey lo describe como "Same model, -preview snapshot id", con la misma tarifa por llamada.

Necesitas dos cosas:

1. Una clave de API de OmniaKey, exportada para que el script la lea: `export OMNIAKEY_API_KEY="your-key"`.
2. Python 3. El script de abajo usa solo la biblioteca estándar: urllib, json, time, uuid, base64 y pathlib. No hay que instalar ningún SDK.

## El script de Python

Tres pasos: crear la tarea, consultarla y descargar la imagen. Guárdalo como `nano_banana.py` y ejecútalo con `python3 nano_banana.py`.

```python
import base64
import json
import os
import time
import urllib.request
import uuid
from pathlib import Path

API = "https://api.omniakey.com/v1/media/tasks"
HEADERS = {
    "Authorization": f"Bearer {os.environ['OMNIAKEY_API_KEY']}",
    "Content-Type": "application/json",
}


def call(url, payload=None, headers=None, method=None):
    body = json.dumps(payload).encode() if payload is not None else None
    req = urllib.request.Request(url, data=body, headers=headers or HEADERS, method=method)
    with urllib.request.urlopen(req, timeout=60) as resp:
        return resp.status, json.loads(resp.read())


def create_task(prompt, aspect_ratio="3:4", image_size="2K", image_path=None):
    body = {
        "model": "gemini-3-pro-image",
        "type": "image",
        "operation": "generate" if image_path is None else "edit",
        "input": {"prompt": prompt},
        "parameters": {"aspect_ratio": aspect_ratio, "image_size": image_size},
    }
    if image_path:
        encoded = base64.b64encode(Path(image_path).read_bytes()).decode("utf-8")
        body["input"]["image"] = {"data": encoded, "mime_type": "image/png"}
    headers = {**HEADERS, "Idempotency-Key": str(uuid.uuid4())}
    status, task = call(API, body, headers, "POST")
    print("created", task["id"], "HTTP", status)
    return task


def wait(task_id, interval=3, timeout=300):
    deadline = time.time() + timeout
    while time.time() < deadline:
        _, task = call(f"{API}/{task_id}")
        print(task["status"], task["progress"]["percent"])
        if task["status"] in ("succeeded", "failed", "canceled"):
            return task
        time.sleep(interval)
    # A timeout is not a failure: keep the task id and poll it again.
    raise TimeoutError(f"task {task_id} is still running")


def download(task, out_path):
    asset = task["assets"][0]
    with urllib.request.urlopen(asset["url"], timeout=120) as resp:
        Path(out_path).write_bytes(resp.read())
    print("saved", out_path, asset["mime_type"], asset["byte_size"], "bytes")


if __name__ == "__main__":
    task = create_task(
        "A vintage travel poster for the Night Train from Zürich to Milano, "
        "departing 21:40 from platform 7. A steam train crosses a stone arch "
        "bridge below snowy mountains under a deep blue night sky, with a cream "
        "border. Spell every word exactly as written.",
        aspect_ratio="3:4",
        image_size="2K",
    )
    task = wait(task["id"])
    if task["status"] != "succeeded":
        raise SystemExit(f"{task['status']}: {task.get('error')}")
    download(task, "night-train.jpg")
```

`image_size` acepta 1K, 2K o 4K. La guía de imágenes de Google lo dice claro: "You must use an uppercase 'K' … Lowercase parameters (e.g., 1k) will be rejected." Envía 2K, no 2k.

`Idempotency-Key` es obligatoria. Generar un UUID nuevo en cada petición es la regla sencilla; reutiliza una clave solo cuando reintentes exactamente el mismo cuerpo. OmniaKey devuelve la tarea original con HTTP 200 en lugar de cobrarte dos veces, y responde 409 si la misma clave llega con un cuerpo distinto.

La llamada de creación devuelve 202 con un id. La [documentación de tareas multimedia](https://docs.omniakey.com/es/media/overview) de OmniaKey describe todo el ciclo; la tarea terminada trae estos campos:

```json
{
  "id": "task_AbMRVqzSnVh0VwBj0S7NuMUxy5sZtfHP",
  "status": "succeeded",
  "progress": {"percent": 100, "stage": "completed"},
  "usage": {"total_tokens": 1133},
  "assets": [
    {
      "kind": "image",
      "mime_type": "…",
      "url": "https://…signed-url…"
    }
  ]
}
```

Lee `assets[0].url` y descárgala en ese momento: el enlace firmado dura alrededor de una hora y el registro de la tarea se guarda 24 horas. El campo `mime_type` te dice el formato; los modelos Gemini suelen devolver JPEG.

El mismo script en 1:1 y 2K, con un cartel en chino como prompt, devolvió esto:

![Un cartel metálico oscuro sobre una pared de ladrillo con tres líneas de texto en chino y un número de teléfono](https://omniakey.com/_img/blog/nano-banana-pro-api/g2-sign.7e3e8e4d.1600.webp)

_2K, 1:1: 2048x2048 en 47.2 s. Las tres líneas en chino y el 010-6789 4321 salieron correctos; el óxido tapa parte del primer 0._

## Editar una imagen existente

Pon `operation: "edit"` y pasa la imagen de origen en `input.image` como `{data, mime_type}`. El script de arriba ya lo hace cuando le das un image\_path:

```python
task = create_task(
    "Hang this poster in a thin black frame on a warm white wall, with a brass "
    "picture light above it, a low wooden cabinet below and a trailing plant on "
    "the right. Keep the poster exactly as it is.",
    aspect_ratio="1:1",
    image_size="2K",
    image_path="night-train-2k.png",
)
```

El cuerpo que envía tiene este aspecto:

```json
{
  "model": "gemini-3-pro-image",
  "type": "image",
  "operation": "edit",
  "input": {
    "prompt": "Hang this poster in a thin black frame on a warm white wall…",
    "image": {"data": "…base64…", "mime_type": "image/png"}
  },
  "parameters": {"aspect_ratio": "1:1", "image_size": "2K"}
}
```

La imagen de origen del ejemplo es un PNG, así que el script la etiqueta `image/png`; cambia esa etiqueta para un JPEG. Para varias referencias, usa `input.images` y da a cada entrada la misma forma `{data, mime_type}`. La guía de Google pone el límite en 14 imágenes de referencia; para `gemini-3-pro-image` el reparto es 6 imágenes de objeto, 5 de personaje y 3 de estilo.

Mantén el cuerpo por debajo de 1 MiB. Base64 aumenta el archivo alrededor de un tercio, así que reduce o comprime el origen antes de codificarlo. Nuestra edición usó el póster de 2K y conservó cada palabra y la maquetación:

![El póster del tren nocturno en un marco negro sobre una pared, con una lámpara de cuadro encima y una planta a la derecha](https://omniakey.com/_img/blog/nano-banana-pro-api/g3-edit.98011b5c.1600.webp)

_2K, edición 1:1: 2048x2048 en 49.9 s. El texto y el diseño del póster sobrevivieron; el marco es un rectángulo limpio._

## 1K, 2K y 4K: qué aporta cada uno

Ejecutamos el mismo prompt del póster en 3:4 con los tres tamaños. Los píxeles coincidieron exactamente con la tabla de Google para 3:4: 896x1200 en 1K, 1792x2400 en 2K y 3584x4800 en 4K. El texto del póster fue correcto en los tres tamaños.

![El póster del tren nocturno en 1K: tren de vapor sobre un puente de piedra, montañas nevadas y cielo azul profundo](https://omniakey.com/_img/blog/nano-banana-pro-api/g1-1k.12bc0ed0.896.webp)

_1K, 3:4: 896x1200 en 28.4 s. Las cuatro líneas del póster están bien; las lámparas y las bielas de la locomotora se amontonan._

![El mismo póster del tren nocturno en 2K, con un pueblo y dos agujas añadidos en la ladera derecha](https://omniakey.com/_img/blog/nano-banana-pro-api/g1-2k.38a932bb.1600.webp)

_2K, 3:4: 1792x2400 en 48.2 s. Mismo texto, más un pueblo y dos agujas en la ladera derecha._

![El mismo póster del tren nocturno en 4K, con tres vagones y el ténder dibujados detrás de la locomotora](https://omniakey.com/_img/blog/nano-banana-pro-api/g1-4k.6c8048ad.1600.webp)

_4K, 3:4: 3584x4800 en 66.9 s. Aparecen tres vagones y el ténder; las juntas del ladrillo varían de grosor._

Lo que cambia con el tamaño es el detalle, no la ortografía:

- **1K:** el frontal del tren está apretado: lámparas, ruedas y bielas quedan muy juntas.
- **2K:** el pueblo y sus dos agujas aparecen en la ladera derecha, la chimenea suelta un hilo claro de humo y el puente muestra siete arcos.
- **4K:** los tres vagones y el ténder se separan, y la sillería muestra juntas de distinto grosor. La maquinaria bajo la locomotora sigue simplificada.

La velocidad subió con el tamaño: 28.4 s, 48.2 s y 66.9 s. Cada tamaño se ejecutó una vez, así que lee esos segundos como una sola pasada.

Google cobra la salida de imagen a $120 por millón de tokens, y su tabla da 1,120 tokens tanto para 1K como para 2K y 2,000 tokens para 4K. De ahí sale su propia estimación:

```text
1,120 × $120 ÷ 1,000,000 = $0.134 per 1K image
1,120 × $120 ÷ 1,000,000 = $0.134 per 2K image
2,000 × $120 ÷ 1,000,000 = $0.24  per 4K image
```

Nuestras tareas informaron de más tokens que los ejemplos de Google. Aquí está la misma aritmética con nuestros números:

```text
1,133 × $120 ÷ 1,000,000 = $0.136 per 1K image
1,225 × $120 ÷ 1,000,000 = $0.147 per 2K image
2,480 × $120 ÷ 1,000,000 = $0.298 per 4K image
```

|Tamaño|Píxeles, 3:4|Nuestro tiempo|Nuestros tokens|Estimación de Google|
|-|-|-|-|-|
|1K|896x1200|28.4 s|1,133|$0.134|
|2K|1792x2400|48.2 s|1,225|$0.134|
|4K|3584x4800|66.9 s|2,480|$0.24|

OmniaKey cobra la llamada de imagen a tarifa plana, no por token, así que su importe no se mueve con esos recuentos; la [página del modelo](https://omniakey.com/es/gemini-3-pro-image) tiene la tarifa actual por llamada, y una tarea fallida se reembolsa. La estimación de Google por tarifa de tokens para las mismas tres imágenes es $0.134, $0.134 y $0.24.

## Errores con los que te vas a topar

Las fallas de aquí se reducen casi siempre a un nombre de campo o a un tamaño de archivo, no al modelo. Estas son las que la documentación multimedia de OmniaKey lista para este endpoint:

|HTTP|Código o estado|Qué significa|Qué hacer|
|-|-|-|-|
|400|`invalid_request`|Cuerpo mal formado, operación no admitida o parámetro incorrecto|Revisa el JSON y los nombres de campo de abajo|
|503|`no_available_channel`|Ningún canal atiende este modelo ahora|Cambia de modelo; reintentar no lo arregla|
|—|`failed`|La tarea terminó sin resultado|Lee `error.code` y `error.message`|

Una tarea fallida no es un error HTTP: la llamada de creación salió bien, así que consulta la tarea y lee su objeto `error`. Las tareas fallidas y canceladas se reembolsan de forma automática.

Un origen a resolución completa enviado en Base64 puede empujar el cuerpo por encima de 1 MiB. Redúcelo primero y mira la longitud codificada, no solo el tamaño del archivo.

La guía de Google rechaza un `1k` en minúscula. Usa 1K, 2K o 4K.

La documentación de imagen de OmniaKey también rechaza `size` y un `mime_type` de primer nivel en los modelos Gemini, porque no son parámetros de Gemini. Usa `parameters.aspect_ratio` y `parameters.image_size`, y lee el formato de salida en el campo `mime_type` de la respuesta.

## Preguntas frecuentes

### ¿Cuál es el id de modelo de la API de Nano Banana Pro?

`gemini-3-pro-image`. La ficha de Vertex de Google lo marca como GA con fecha de lanzamiento del 28 de mayo de 2026, y OmniaKey acepta el mismo id. El id anterior `gemini-3-pro-image-preview` sigue funcionando en OmniaKey y apunta al mismo modelo.

### ¿Cuánto cuesta una imagen de Nano Banana Pro?

Google estima $0.134 para una imagen de 1K o 2K y $0.24 para una de 4K, con su tarifa de $120 por millón de tokens de imagen. Nuestras tareas informaron de 1,133, 1,225 y 2,480 tokens, que a esa tarifa son $0.136, $0.147 y $0.298. La página del modelo en OmniaKey lista su propia tarifa por llamada.

### ¿Nano Banana Pro puede escribir texto en chino?

Sí. Nuestro cartel de 2K volvió con tres líneas correctas en chino — 同福客栈, 住宿 餐饮 茶水 y 010-6789 4321 — con los 11 dígitos y el guion.

### ¿Pido 1K, 2K o 4K?

Para un póster como el nuestro, 2K es el punto medio útil. Los tres tamaños escribieron bien el póster, así que 4K compra detalle más fino — vagones separados y juntas de ladrillo — en vez de mejor texto. Usa 1K para borradores en los que 896x1200 sea suficiente.

### ¿Por qué mi edición devolvió 400 invalid\_request?

Las causas habituales son un cuerpo de más de 1 MiB, el origen en el campo equivocado o un modelo Gemini que recibe `size` o un `mime_type` de primer nivel. Pon la imagen en `input.image` como `{data, mime_type}`, mantén el cuerpo codificado por debajo de 1 MiB y usa `aspect_ratio` y `image_size`.

## Fuentes consultadas

- [Google Cloud: ficha del modelo Gemini 3 Pro Image](https://cloud.google.com/vertex-ai/generative-ai/docs/models/gemini/3-pro-image) — consultada el 3 nov 2026.
- [Google: guía de generación de imágenes de la API Gemini](https://ai.google.dev/gemini-api/docs/image-generation) — consultada el 3 nov 2026.
- [Google: precios de la API Gemini](https://ai.google.dev/gemini-api/docs/pricing) — consultada el 3 nov 2026.
- [Google: anuncio de Nano Banana Pro](https://blog.google/technology/ai/nano-banana-pro/) — consultado el 3 nov 2026.

## Registro de cambios

- 2026-11-03: primera versión; cinco llamadas de prueba hechas ese día a través de OmniaKey.
