Cómo generar imágenes con Nano Banana 2.1 y Nano Banana Pro mediante la Google Flow API

6 min de lectura • 15 de junio de 2026 (6 de noviembre de 2026)

useapi.net es una API de terceros. No está afiliada a Google ni cuenta con su respaldo.

Índice

  1. Introducción
  2. Modelos compatibles
    1. Upscale a 2K/4K
  3. Precios
  4. Cómo generar una imagen de Nano Banana con curl
  5. Imágenes de referencia y personajes
  6. Genera por lotes con un script
  7. Ejemplos
  8. Preguntas frecuentes
  9. Conclusión

Introducción

Un solo POST síncrono a la Google Flow API de useapi.net devuelve hasta cuatro imágenes de Nano Banana 2.1, Nano Banana Pro o Nano Banana 2 Lite, hechas con tu cuenta de Google Flow. Las imágenes están incluidas en toda suscripción de Google AI, incluso en una cuenta gratuita, mientras que la Gemini API oficial cobra de US$0,034 a US$0,134 por imagen (a noviembre de 2026). No necesitas un proyecto de Google Cloud ni una clave de la Gemini API.

Esta guía muestra los modelos disponibles, la diferencia de precio, el flujo de imagen en una sola llamada con curl listo para copiar y un script en Node.js que genera imágenes por lotes a partir de una lista de prompts. ¿Quieres ver cómo se comportan los tres modelos con el mismo prompt? Consulta la comparación de los modelos Nano Banana. ¿Necesitas video? Consulta el tutorial de Veo 3.1, la guía hermana de esta.

Modelos compatibles

Elige el modelo en cada solicitud con el campo model (por defecto nano-banana-2-lite). Los tres modelos funcionan con cualquier suscripción de Google AI, incluso en una cuenta gratuita.

Id del modelo Nombre comercial Referencias (I2I) Proporciones Notas
nano-banana-2-lite (por defecto) Nano Banana 2 Lite / Gemini 3.1 Flash-Lite Image máx. 10 16:9, 4:3, 1:1, 3:4, 9:16, auto† Modelo de imagen por defecto de Google Flow desde julio de 2026. En el modo imagen a imagen se mantiene en 16:9, salvo que indiques una proporción
nano-banana-2 Nano Banana 2.1 máx. 10 16:9, 4:3, 1:1, 3:4, 9:16, auto† Usa auto por defecto en el modo imagen a imagen
nano-banana-pro Nano Banana Pro / Gemini 3 Pro Image máx. 10 16:9, 4:3, 1:1, 3:4, 9:16, auto† El modelo de imagen de mayor calidad. Usa auto por defecto en el modo imagen a imagen

† auto solo vale en el modo imagen a imagen (con al menos un reference_* o character_*): el backend toma la proporción de la primera imagen de referencia. Con varias referencias la orientación no está garantizada, así que indica una proporción explícita cuando todas las imágenes deban volver con el mismo formato.

Los tres aceptan count (1–4) y seed para reproducibilidad. Si omites model, la API usa nano-banana-2-lite, con o sin referencias. Dos alias obsoletos se siguen aceptando: nano-banana pasa a nano-banana-2, e imagen-4 pasa a nano-banana-2-lite (Google quitó Imagen de Google Flow en julio de 2026). Los detalles y las funciones de cada modelo están en la referencia de POST /images.

Upscale a 2K/4K

Las imágenes generadas con cualquiera de los tres modelos admiten upscale con POST /images/upscale: indica el mediaGenerationId de la imagen y un resolution de 2k (por defecto) o 4k. La respuesta llega en base64 en encodedImage. 2k funciona en cualquier plan, incluso en una cuenta gratuita. 4k requiere Google AI Ultra, y en cualquier otro plan responde 400 con 4k upscaling is not available for this account antes de resolver un captcha, así que no cuesta nada y no sirve de nada reintentar. Ninguno de los dos consume créditos de Flow.

Precios

Las imágenes no consumen créditos de Flow en ninguna suscripción de Google AI, incluso en una cuenta gratuita, y useapi.net no cobra nada por imagen. Solo necesitas un plan de pago para video con Omni 1.1 Flash, video con Omni 1.2 Flash de más de 10 segundos, extensiones con Omni 1.2 y upscale de video, y el upscale de imagen en 4k requiere Ultra. El precio de cada modelo en cada plan, frente a la API oficial, está en la tabla de precios de Google Flow.

Cómo generar una imagen de Nano Banana con curl

Necesitas un token de API de useapi.net y una cuenta de Google Flow conectada. La generación de imágenes es síncrona: un solo POST espera hasta que las imágenes estén listas (normalmente de 10 a 20 segundos) y las devuelve en la respuesta, así que no hay jobid que consultar. El segundo paso es solo guardar el resultado, desde la URL firmada o, cuando no viene, desde la imagen en base64 incluida en la respuesta.

  1. Envía el prompt — POST https://api.useapi.net/v1/google-flow/images:
curl -X POST "https://api.useapi.net/v1/google-flow/images" \
  -H "Authorization: Bearer $USEAPI_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Cat dressed like a pirate fencing with a real pirate, pirate looks absolutely terrified, this is happening on a deck of the Disney cruise ship",
    "model": "nano-banana-pro",
    "aspectRatio": "16:9",
    "count": 4,
    "seed": 123456
  }' > response.json

La llamada devuelve 200 OK con un jobId y un arreglo media, con un elemento por imagen (count va de 1 a 4, por defecto 4). La URL de descarga firmada de cada imagen está en media[].image.generatedImage.fifeUrl:

{
  "jobId": "j1731859345678i-u12345-email:jo***@gmail.com-bot:google-flow",
  "media": [
    {
      "image": {
        "generatedImage": {
          "seed": 123456,
          "mediaGenerationId": "user:12345-email:6a6f...-image:...",
          "prompt": "Cat dressed like a pirate fencing with a real pirate, pirate looks absolutely terrified, this is happening on a deck of the Disney cruise ship",
          "fifeUrl": "https://flow-content.google/image/...",
          "aspectRatio": "IMAGE_ASPECT_RATIO_LANDSCAPE"
        }
      }
    }
  ]
}
  1. Descarga la imagen desde fifeUrl (la URL firmada vale por tiempo limitado, así que descárgala pronto). A veces fifeUrl no viene y la imagen llega en base64 dentro de encodedImage. En ese caso, decodifica ese campo:
URL=$(jq -r '.media[0].image.generatedImage.fifeUrl // empty' response.json)
if [ -n "$URL" ]; then
  curl -o image_1.jpg "$URL"
else
  jq -r '.media[0].image.generatedImage.encodedImage' response.json | base64 -d > image_1.jpg
fi

El mediaGenerationId de cada imagen generada se puede reutilizar como referencia en una solicitud posterior. Consulta Imágenes de referencia y personajes más abajo.

¿Quieres también un webhook? Pasa un replyUrl en el cuerpo de la solicitud y la API también envía las actualizaciones de estado del job a esa URL. La llamada en sí sigue esperando las imágenes. El payload es igual a la respuesta de GET /jobs/jobId, donde una imagen terminada está en response.media[].image.generatedImage.fifeUrl.

Imágenes de referencia y personajes

Para guiar una imagen con una foto que ya tienes, súbela primero con POST /assets/email (bytes sin procesar, un Content-Type de imagen, PNG/JPEG/WebP de hasta 20 MB). La respuesta de la subida trae el id de la referencia anidado en mediaGenerationId.mediaGenerationId. Esa cadena anidada es la que devuelves como reference_1 (cada uno de los tres modelos acepta hasta 10 referencias):

# 1. Sube una imagen de referencia
curl -X POST "https://api.useapi.net/v1/google-flow/assets/john%40gmail.com" \
  -H "Authorization: Bearer $USEAPI_TOKEN" \
  -H "Content-Type: image/jpeg" \
  --data-binary @reference.jpeg

# Respuesta: el id de la referencia viene anidado un nivel más abajo:
# {
#   "mediaGenerationId": {
#     "mediaGenerationId": "user:12345-email:6a6f...-image:ff9aa5cc-..."
#   },
#   "width": 1024, "height": 1024, "email": "jo***@gmail.com"
# }

# 2. Genera usando esa referencia
curl -X POST "https://api.useapi.net/v1/google-flow/images" \
  -H "Authorization: Bearer $USEAPI_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "nano-banana-pro",
    "prompt": "Make this photograph look modern",
    "reference_1": "user:12345-email:6a6f...-image:ff9aa5cc-..."
  }'

Para mantener la misma identidad en muchas imágenes, junta 1–2 imágenes de referencia en un personaje reutilizable con POST /characters y luego pasa su id character como character_1…character_7. Los personajes se combinan libremente con reference_* y comparten el mismo límite de referencias de cada modelo. También puedes poner marcadores @reference_1 / @character_1 directamente en el prompt para indicar dónde entra cada imagen. Cada marcador en el prompt necesita un parámetro correspondiente en el cuerpo.

Genera por lotes con un script

Llegar a la imagen correcta requiere muchos intentos, y hacer cada uno a mano cansa. El script en Node.js de abajo lee una lista de prompts de prompts.json, sube las imágenes de referencia, envía cada solicitud y descarga todas las imágenes devueltas. Así pones un lote en cola y vuelves después a elegir las mejores. Como POST /images es síncrono, el script guarda cada resultado en cuanto la llamada responde.

Necesitas Node.js v21 o posterior. Pon prompts.json y google-flow-images.mjs en la misma carpeta y ejecuta node ./google-flow-images.mjs API_TOKEN EMAIL, donde API_TOKEN es tu token de API de useapi.net y EMAIL es el correo de tu cuenta de Google Flow conectada. El script encuentra la cuenta por el correo automáticamente y revisa el campo health antes de enviar.

¿Prefieres clonar y ejecutar en local? google-flow-images.mjs y prompts.json completos están en GitHub, en useapi/google-flow-api.

Abrir prompts.json
[
    {
        "prompt": "By default the nano-banana-2-lite model generates 4 image variations at 16:9."
    },
    {
        "model": "nano-banana-pro",
        "aspectRatio": "1:1",
        "count": 2,
        "seed": 123456,
        "prompt": "Nano Banana Pro (Gemini 3 Pro Image), two square variations. For all parameters see https://useapi.net/docs/api-google-flow-v1/post-google-flow-images"
    },
    {
        "model": "nano-banana-2",
        "aspectRatio": "auto",
        "reference_1": "./reference_image.jpeg",
        "prompt": "Image-to-image: pass a local reference file as reference_1 (uploaded automatically). auto aspect ratio derives from the first reference. All three models accept up to 10 references."
    },
    {
        "model": "nano-banana-2-lite",
        "aspectRatio": "9:16",
        "count": 4,
        "prompt": "Nano Banana 2 Lite portrait. Other models (nano-banana-2, nano-banana-pro) are selectable via the model field — see the POST /images docs."
    }
]
Abrir el script google-flow-images.mjs
/*

Script version 1.2, September 11, 2026

Script to batch-generate images using prompts with the Google Flow API v1 by useapi.net 🚀
Uses the synchronous POST /images endpoint (default model: nano-banana-2-lite) and saves each image from fifeUrl, or from encodedImage when fifeUrl is absent.
For more details visit https://useapi.net/docs/api-google-flow-v1/post-google-flow-images

Installation Instructions:
==========================

You need Node.js v21 or newer installed to run this script. Download and install Node.js from:

- Windows, macOS, Linux: https://nodejs.org/

After installation, verify by running the following command in a terminal:

   node -v

Running the Script:
===================

Usage: node google-flow-images.mjs <API_TOKEN> <EMAIL> [PROMPTS_FILE]

Replace API_TOKEN with your actual useapi.net API token, see https://useapi.net/docs/start-here/setup-useapi
Replace EMAIL with configured Google Flow email account, see https://useapi.net/docs/start-here/setup-google-flow
If optional PROMPTS_FILE not provided prompts.json will be used.

Example:
--------

node google-flow-images.mjs user:1234-abcdefhijklmnopqrstuv [email protected]

This command executes the script using API token user:1234-abcdefhijklmnopqrstuv with [email protected] Google Flow account email.

Changelog:
==========

- June 15, 2026: Initial release.
- September 10, 2026: Default model is now nano-banana-2-lite (Google removed Imagen from Flow, and imagen-4 now maps to nano-banana-2-lite). Saves encodedImage when fifeUrl is absent, and accepts .jpg reference images.
- September 11, 2026: A prompt whose reference_* file fails to upload is skipped and logged to google-flow-images_errors.txt instead of being submitted without that reference. Writes a downloaded image only once it has been fully received, so a failed download leaves no partial file for the next run to skip as "already exists".

*/

import fs from 'fs/promises';
import { writeFile } from 'node:fs/promises';


// Constants
const ERRORS_FILE = 'google-flow-images_errors.txt';
const DEFAULT_PROMPTS_FILE = 'prompts.json';
const DEFAULT_MODEL = 'nano-banana-2-lite';
const SLEEP_429 = 30 * 1000; // in milliseconds

const urlAccounts = 'https://api.useapi.net/v1/google-flow/accounts';
const urlImages = 'https://api.useapi.net/v1/google-flow/images';
const urlUploadAsset = 'https://api.useapi.net/v1/google-flow/assets/';

// Google Flow accepts png, jpeg and webp for reference images.
const supportedFileExtensions = ['png', 'jpg', 'jpeg', 'webp'];

// reference_1 .. reference_10 are accepted by POST /images.
const referenceParams = Array.from({ length: 10 }, (_, i) => `reference_${i + 1}`);

// { filename: mediaGenerationId }
const uploadedFiles = {};

// Utility to sleep for given milliseconds
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

// Function to fetch configured Google Flow API accounts
async function fetchAccounts(apiToken) {
    const response = await fetch(urlAccounts, {
        headers: {
            'Accept': 'application/json',
            'Authorization': `Bearer ${apiToken}`
        }
    });

    if (!response.ok) {
        console.error(`⛔ Error fetching accounts (HTTP ${response.status}): ${response.statusText}`);
        process.exit(1);
    }

    return response.json();
}

const elapsedTimeSec = (start) => (Date.now() - start) / 1000;

// Map a file extension to the Content-Type required by POST /assets
const contentTypeForExt = (ext) => ext === 'png' ? 'image/png' : ext === 'webp' ? 'image/webp' : 'image/jpeg';

async function uploadAsset(apiToken, email, filename) {

    // Check if already uploaded
    if (uploadedFiles.hasOwnProperty(filename))
        return uploadedFiles[filename];

    const startTime = Date.now();

    console.log(`⬆️  Account ${email} uploading file…`, filename);

    const body = new Blob([await fs.readFile(filename)]);

    const fileExt = filename.split('.').pop().toLowerCase();

    const response = await fetch(`${urlUploadAsset}${encodeURIComponent(email)}`, {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Authorization': `Bearer ${apiToken}`,
            'Content-Type': contentTypeForExt(fileExt)
        },
        body
    });

    if (response.ok) {
        const json = await response.json();
        // POST /assets returns the reference id nested as mediaGenerationId.mediaGenerationId
        const mediaGenerationId = json?.mediaGenerationId?.mediaGenerationId;
        console.log(`🆗 mediaGenerationId (${elapsedTimeSec(startTime)} sec)`, mediaGenerationId);
        uploadedFiles[filename] = mediaGenerationId;
    }
    else {
        console.error(`❗ Unable to upload file HTTP ${response.status} (${elapsedTimeSec(startTime)} sec)`, await response.text());
        // Do not attempt to upload failed file again
        uploadedFiles[filename] = undefined;
    }

    return uploadedFiles[filename];
}

// Download a single image from its signed fifeUrl.
async function downloadImage(url, filename) {
    try {
        await fs.access(filename);
        console.log(`⚠️ ${filename} already exists. Skipping download.`);
        return;
    } catch {
        // File does not exist, proceed with downloading
    }

    if (!url) {
        console.error(`🛑 No fifeUrl for ${filename}`);
        return;
    }

    console.log(`✅ Downloading ${url} to ${filename}`);
    try {
        const imageResponse = await fetch(url);
        if (!imageResponse.ok) {
            console.error(`⛔ Unable to download ${filename} (HTTP ${imageResponse.status})`, url);
            return;
        }
        // Read the whole body before creating the file, so a failed download leaves no
        // partial file behind for the next run to skip as "already exists".
        const data = Buffer.from(await imageResponse.arrayBuffer());
        await writeFile(filename, data);
    } catch (err) {
        console.error(`⛔ Error during download: ${err}`);
    }
}

// Submit a single prompt to the synchronous POST /images endpoint and download the results.
async function submitImage(apiToken, email, prompt, index) {
    const { model, prompt: text } = prompt;

    const useModel = model ?? DEFAULT_MODEL;

    console.log(`🚀 ${useModel} » Prompt #${index} • account ${email} …`);

    // Build the request body, uploading any local reference_* file to a mediaGenerationId first.
    const body = { model: useModel, email, prompt: text };

    for (const key of ['aspectRatio', 'count', 'seed'])
        if (prompt[key] !== undefined) body[key] = prompt[key];

    for (const refKey of referenceParams) {
        const value = prompt[refKey];
        if (value)
            body[refKey] = await uploadAsset(apiToken, email, value);
    }

    // A reference that failed to upload would be left out of the body, and the prompt would still be
    // generated (and charged) without it. Skip the prompt instead. uploadAsset remembers the failed file,
    // so a later prompt using it is skipped too, without another upload attempt.
    const failedUploads = referenceParams.filter(refKey => prompt[refKey] && !body[refKey]);
    for (const refKey of failedUploads) {
        console.error(`🛑 Prompt #${index} skipped: ${refKey} ${prompt[refKey]} failed to upload`);
        await fs.appendFile(ERRORS_FILE, `Upload failed for ${refKey} ${prompt[refKey]},#${index}:${text}\n`);
    }
    if (failedUploads.length)
        return;

    while (true) {
        const response = await fetch(urlImages, {
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${apiToken}`
            },
            body: JSON.stringify(body)
        });

        const responseText = await response.text();

        if (response.status == 200) {
            const json = JSON.parse(responseText);
            const media = json?.media ?? [];

            if (media.length == 0)
                console.error(`🛑 200 OK but no media for prompt #${index}:\n${text}\n`);

            // count > 1 returns multiple images in the media array.
            for (let i = 0; i < media.length; i++) {
                const img = media[i]?.image?.generatedImage;
                const filename = `google-flow_${index}_${i + 1}.jpg`;
                // fifeUrl is normally present. When it is absent the image arrived inline as base64 in encodedImage.
                if (!img?.fifeUrl && img?.encodedImage)
                    await fs.writeFile(filename, Buffer.from(img.encodedImage, 'base64'));
                else
                    await downloadImage(img?.fifeUrl, filename);
            }
            return 200;
        }

        switch (response.status) {
            case 429:
                console.log(`🔄️ Retry on HTTP ${response.status}`, responseText);
                await sleep(SLEEP_429);
                break;
            case 503:
                console.log(`🔄️ Service unavailable, retry on HTTP ${response.status}`, responseText);
                await sleep(SLEEP_429);
                break;
            case 402:
                console.log(`🛑 No subscription / insufficient credits`, responseText);
                await fs.appendFile(ERRORS_FILE, `${response.status},#${index}:${text}\n`);
                process.exit(1);
            case 400:
            case 500:
                console.log(`🛑 Rejected (validation or content moderation)`, responseText);
                await fs.appendFile(ERRORS_FILE, `${response.status},#${index}:${text}\n`);
                return response.status;
            default:
                console.log(`❗ FAILED with HTTP ${response.status}`, responseText);
                await fs.appendFile(ERRORS_FILE, `${response.status},#${index}:${text}\n`);
                return response.status;
        }
    }
}

// Main function
async function main() {
    const apiToken = process.argv[2];
    const email = process.argv[3];
    const promptFile = process.argv[4] || DEFAULT_PROMPTS_FILE;

    if (!apiToken || !email) {
        console.error('Usage: node google-flow-images.mjs <API_TOKEN> <EMAIL> [PROMPTS_FILE]');
        process.exit(1);
    }

    console.info('Script v1.2');
    console.info('Node version is: ' + process.version);

    const start = new Date();
    try {
        console.info('START EXECUTION', start);
        await execute(apiToken, email, promptFile);
    } catch (error) {
        console.error('⛔ Error during execution:', error.stack || error);
    } finally {
        console.info('COMPLETED', new Date());
        console.info('EXECUTION ELAPSED', diffInMinutesAndSeconds(start, new Date()));
    }
}

async function execute(apiToken, email, promptFile) {
    const accounts = await fetchAccounts(apiToken);

    console.info(`Configured Google Flow API accounts (${Object.keys(accounts).length}):`, Object.keys(accounts).join(', '));

    if (Object.keys(accounts).length <= 0) {
        console.error(`⛔ No configured Google Flow accounts found. Please refer to https://useapi.net/docs/start-here/setup-google-flow`);
        process.exit(1);
    }

    if (!accounts[email]) {
        console.error(`⛔ Account ${email} not found. Please refer to https://useapi.net/docs/start-here/setup-google-flow`);
        process.exit(1);
    }

    if (accounts[email].health && accounts[email].health !== 'OK') {
        console.error(`⛔ Account ${email} health is '${accounts[email].health}'. Please resolve and update the account, see https://useapi.net/docs/start-here/setup-google-flow`);
        process.exit(1);
    }

    const promptData = await fs.readFile(promptFile, 'utf8');
    const prompts = JSON.parse(promptData);
    console.log(`Total number of prompts to process`, prompts.length);

    let warnings = [];

    // Parameters accepted by this script for the POST /images endpoint.
    // See https://useapi.net/docs/api-google-flow-v1/post-google-flow-images for every model's full parameter set.
    const supportedParams = ['model', 'prompt', 'aspectRatio', 'count', 'seed', ...referenceParams];

    const invalidKeys = (prompt) => Object.keys(prompt).filter(key => !key.startsWith('__') && !supportedParams.includes(key))

    for (let i = 1; i <= prompts.length; i++) {
        const prompt = prompts[i - 1];
        const { prompt: text } = prompt;

        const validateImage = async (file) => {
            if (file) {
                try {
                    await fs.access(file);
                } catch {
                    warnings.push(`⚠️  Image '${file}' does not exist. Prompt ${i}`);
                }

                const ext = file.split('.').pop().toLowerCase();

                if (!supportedFileExtensions.includes(ext))
                    warnings.push(`⚠️  Image ${file} extension ${ext} not supported. Prompt ${i}`);
            }
        };

        const notSupported = invalidKeys(prompt);
        if (notSupported.length)
            warnings.push(`⚠️  Following params not supported: ${notSupported.join(',')}. Prompt ${i}`);

        if (!text)
            warnings.push(`⚠️  prompt is required. Prompt ${i}`);

        await Promise.all(referenceParams.map(refKey => validateImage(prompt[refKey])));
    }

    if (warnings.length > 0) {
        warnings.forEach(warning => console.warn(warning));
        console.error(`⛔ Execution stopped due to warnings.`);
        process.exit(1);
    }

    for (let i = 0; i < prompts.length; i++)
        await submitImage(apiToken, email, prompts[i], i + 1);
}

function diffInMinutesAndSeconds(date1, date2) {
    const diffInSeconds = Math.floor((date2 - date1) / 1000);
    return `${Math.floor(diffInSeconds / 60)} minutes ${diffInSeconds % 60} seconds`;
};

main();

Ejemplos

Imágenes reales generadas con esta misma Google Flow API con Nano Banana Pro y Nano Banana 2 Lite, tomadas directamente de nuestro blog y de la comparación de modelos (en inglés).

Nano Banana Pro — texto a imagen (fuente, en inglés): “Cat dressed like a pirate fencing with a real pirate… on a Disney cruise ship.”

Resultado de texto a imagen de Nano Banana Pro

Nano Banana Pro — 5 imágenes de referencia (fuente, en inglés): cinco retratos individuales combinados en una sola foto de grupo, “K-Pop group victory celebration”.

Foto de grupo de Nano Banana Pro hecha con varias referencias

Nano Banana 2 Lite, el modelo por defecto (fuente, en inglés): el prompt del apicultor de nuestra comparación de los tres modelos, generado en 9:16 con el más rápido de los tres.

Apicultor generado con Nano Banana 2 Lite mediante la Google Flow API

Preguntas frecuentes

  • ¿Existe una API de Nano Banana 2? Con useapi.net, sí: en la Google Flow API, nano-banana-2 genera imágenes con Nano Banana 2.1, la versión que usa Google Flow, con cualquier suscripción de Google AI o en una cuenta gratuita, sin cobro por imagen. Nano Banana 2 (Gemini 3.1 Flash Image) cuesta US$0,067 por imagen 1K en la Gemini API oficial de Google (a noviembre de 2026). Es un endpoint REST normal, sin proyecto de Cloud.
  • ¿Existe una API de Nano Banana Pro? Con useapi.net, sí: Nano Banana Pro (Gemini 3 Pro Image) se ejecuta como nano-banana-pro en el endpoint POST /images, y una sola solicitud síncrona devuelve hasta cuatro imágenes, sin cobro por imagen. La Gemini API oficial de Google cobra US$0,134 por imagen Pro (a noviembre de 2026).
  • ¿Qué modelo usa la API por defecto? En useapi.net, el modelo por defecto es nano-banana-2-lite (Gemini 3.1 Flash-Lite Image), con o sin referencias. Cámbialo en cada solicitud con model igual a nano-banana-2 (Nano Banana 2.1) o nano-banana-pro (Gemini 3 Pro Image, la mayor calidad). Los tres aceptan hasta 10 imágenes de referencia y admiten upscale a 2K/4K. Nano Banana 2 Lite vs 2.1 vs Pro muestra los tres con el mismo prompt.
  • ¿Imagen 4 sigue disponible en Google Flow? En useapi.net, el id de modelo imagen-4 sigue funcionando, así que tu código actual sigue corriendo. Pero Google quitó Imagen de Google Flow en julio de 2026, y esas solicitudes ahora generan imágenes con nano-banana-2-lite, el modelo de imagen por defecto de Google Flow desde entonces. Para elegir otro modelo, define model como nano-banana-2 o nano-banana-pro.
  • ¿Necesito un captcha o un proyecto de Google Cloud? Con useapi.net no necesitas un proyecto de Google Cloud ni resolver captchas por tu cuenta. Google Flow pide un reCAPTCHA en cada imagen, y el worker de useapi.net lo resuelve todo automáticamente: tu primera cuenta de Google Flow incluye 300 resoluciones gratis con nuestras propias claves de AntiCaptcha, CapSolver y EzCaptcha, y después agregas las claves de tu proveedor con POST /accounts/captcha-providers. El script de esta guía no envía captchaToken.

Conclusión

Visita nuestro servidor de Discord o nuestro canal de Telegram para cualquier pregunta de soporte.

Consulta nuestro repositorio de GitHub con ejemplos de código.

También publicado en

También publicado en dev.to (en inglés) y compartido en Bluesky.

Empieza a usar la API

Una sola suscripción de US$15 al mes cubre todas las API de useapi.net: un token para todos los servicios. Conectas hasta 3 cuentas propias por servicio, cada una con la suscripción de su sitio web, y useapi.net se encarga de la API REST, el balanceo de carga y el polling. ¿Necesitas más cuentas? Cada suscripción adicional cuesta US$10 al mes y suma 3 cuentas más por servicio.

Suscríbete — US$15/mes Pagar con cripto

¿No tienes una tarjeta de crédito internacional? También puedes suscribirte con criptomonedas (los pagos con cripto no se reembolsan). Los precios y los planes por volumen están en la página de suscripción. Si pagas con Stripe, recibes el reembolso completo dentro de los 14 días posteriores a la primera compra, si tienes menos de 50 generaciones exitosas. ¿Ya tienes una suscripción? Cambia la cantidad en el portal de clientes de Stripe en lugar de volver a comprar.