Generate Images

November 17, 2025 (June 5, 2026)

Table of contents

  1. Model Capabilities
  2. Content Moderation
  3. Response Codes
    1. 429 — Rate limit / quota exhausted
    2. 503 — Service unavailable
    3. 403 — Request rejected by Google
  4. Request Headers
  5. Request Body
  6. Responses
  7. Model
  8. Examples
  9. Try It

Generate images using AI models Imagen 4, Nano Banana / Gemini 2.5 Flash Image, Nano Banana 2 / Gemini 2.5 Pro Image, and Nano Banana Pro / Gemini 3 Pro Image from text prompts with optional reference images. Use any Google AI subscription or even free account for image generations.

This endpoint features dynamic concurrency management, allowing anywhere from 3 to 20 parallel generations depending on real-time capacity. Image generation typically completes within 10-20 seconds.

Model Capabilities

Parameter Imagen 4
imagen-4 (default)
Nano Banana 2
nano-banana-2
Nano Banana Pro
nano-banana-pro
T2I (text-to-image)
I2I (reference images) ✓ (max 3) ✓ (max 10) ✓ (max 10)
Aspect ratios 16:9, 4:3, 1:1, 3:4, 9:16 16:9, 4:3, 1:1, 3:4, 9:16, auto 16:9, 4:3, 1:1, 3:4, 9:16, auto
Default aspect ratio 16:9 16:9 (T2I) / auto (I2I) 16:9 (T2I) / auto (I2I)
count ✓ (1-4) ✓ (1-4) ✓ (1-4)
seed
Subscription all all all

auto is only valid in image-to-image mode (at least one reference_* provided) — the backend derives the aspect ratio from the first reference image.

Legacy alias nano-banana is still accepted and maps to nano-banana-2.

Content Moderation

If your generation is moderated, retrying with the same prompt often succeeds on subsequent attempts — moderation decisions can vary between requests. Alternatively, switching between imagen-4, nano-banana-2, and nano-banana-pro models may help, as each has different content-moderation behavior.

Response Codes

429 — Rate limit / quota exhausted

Google returns at least four known distinct RESOURCE_EXHAUSTED variants in the response body. Always check the reason field on the returned error to pick the right strategy:

Reason code What it means What to do
PUBLIC_ERROR_UNUSUAL_ACTIVITY_TOO_MUCH_TRAFFIC This is a captcha-provider issue, not a useapi.net issue. Google’s reCAPTCHA Enterprise scored the captcha token below its risk threshold — usually because the provider is overloaded or being fingerprinted by Google (the provider’s infrastructure is processing too many high-volume requests at once and Google flags them collectively). Our worker has already auto-retried with fresh captcha tokens (up to captchaRetry attempts, default 3) before returning this. Spread the load across multiple captcha providers — configure several providers via POST /accounts/captcha-providers (e.g. CapSolver + AntiCaptcha + 2Captcha) and use captchaOrder on the request to cycle through them. Adding balance to existing providers can also help, since some prioritize higher-balance accounts. As a short-term measure, wait 30-60s and retry, or bump captchaRetry higher in the request body.
PUBLIC_ERROR_USER_REQUESTS_THROTTLED Google-side per-user concurrency limit. The token was fine; this account is sending too many requests at once. Hold for ~hour, retry after 10-60min. Reduce parallel generations per account.
PUBLIC_ERROR_PER_MODEL_DAILY_QUOTA_REACHED This account hit Google’s per-model daily quota. Retrying within the day will not succeed. Hold for the day (quota resets at UTC midnight), or switch to a different model.
PUBLIC_ERROR_USER_QUOTA_REACHED This account hit its overall Google Flow quota cap — separate from per-model limits, blocks all models on this account. Add more Google Flow accounts via POST /accounts so the load is spread. Hold this specific account until the quota resets, or omit email in your request to let load balancing pick a healthier account.

Automatic quarantine. When you omit email, the load balancer automatically quarantines an account on any of PUBLIC_ERROR_USER_QUOTA_REACHED, PUBLIC_ERROR_PER_MODEL_DAILY_QUOTA_REACHED, or PUBLIC_ERROR_USER_REQUESTS_THROTTLED and routes subsequent requests to the remaining healthy accounts. See Quarantine pre-filter for the TTLs and exact behavior.

If every account is quarantined for the requested model, the response is 429 with error: "no_eligible_account" plus a Retry-After header — see the example payload in the 429 response tab below.

503 — Service unavailable

Transient Google-side issue. Wait 5-10 seconds and retry. If the response body says "Captcha service failed", the issue is with your captcha provider (check API key and balance) rather than Google — don’t retry until the provider is back.

403 — Request rejected by Google

Captcha token rejected by Google despite our internal retries — a captcha-provider issue. Increase captchaRetry (default 3) in the request body to 5 or higher, and configure additional providers via POST /accounts/captcha-providers so captchaOrder can cycle across them. If issues persist, contact your reCAPTCHA provider(s) support.

https://api.useapi.net/v1/google-flow/images

Request Headers

Authorization: Bearer {API token}
Content-Type: application/json
# Alternatively you can use multipart/form-data
# Content-Type: multipart/form-data

Request Body

{
  "prompt": "A serene mountain landscape at sunset with vibrant colors",
  "model": "imagen-4",
  "aspectRatio": "16:9",
  "count": 4,
  "seed": 123456
}
  • email is optional. The email address of the Google Flow account to use.

    When only one account is configured, the API will automatically use that account.

    With multiple accounts configured, omitting the email parameter triggers automatic load balancing based on image generation job statistics to select the healthiest account.

    If reference images (reference_1 to _10) are provided, the email parameter can be omitted—the API will automatically use the same account where the images were uploaded.

  • prompt is required, text description for image generation.
  • model is optional, the AI model to use for image generation (default: imagen-4).
    Supported values: imagen-4, nano-banana-2, nano-banana-pro. Legacy alias nano-banana is still accepted and maps to nano-banana-2.
  • aspectRatio is optional, output image aspect ratio. Supported values: 16:9, 4:3, 1:1, 3:4, 9:16, auto. Legacy aliases landscape (→ 16:9) and portrait (→ 9:16) are still accepted. auto is only valid with nano-banana-2 or nano-banana-pro when at least one reference_* is provided — the backend derives the aspect ratio from the first reference image. Default:
    • text-to-image (no references): 16:9
    • imagen-4 image-to-image: 16:9
    • nano-banana-2 / nano-banana-pro image-to-image: auto
  • count is optional, number of image variations to generate (1-4, default: 4).
  • seed is optional, random seed for reproducible results (integer ≥ 0).
  • reference_1 to reference_10 are optional, use mediaGenerationId from POST /assets/email for reference images. imagen-4 supports max 3 references, nano-banana-2 and nano-banana-pro support up to 10.
  • character_1 to character_7 are optional, character reference-ids from POST /characters. Characters mix freely with reference_* — they share the same per-model image-ref budget on Google’s side (per-character image counts roll into the total). Imagen models that don’t accept reference images also don’t accept characters.
  • replyUrl is optional, webhook URL for job status callbacks. Receives POST requests with job status updates (created, completed, failed). The JSON payload shape matches GET /jobs/jobId response. Callbacks timeout after 5 seconds.
  • replyRef is optional, custom reference string passed back in webhook callbacks. Useful for tracking jobs on your end.
  • captchaToken, captchaRetry, captchaOrder are optional, mutually exclusive captcha parameters. See Captcha Parameters for details.

Auto-detection: If model is not specified: with references selects nano-banana-2, without references defaults to imagen-4.

Responses

  • 200 OK

    Images generated successfully. Returns job ID and media array with generated image data.

    {
      "jobId": "j1731859345678i-u12345-email:jo***@gmail.com-bot:google-flow",
      "media": [
        {
          "name": "…redacted…",
          "workflowId": "…redacted…",
          "image": {
            "generatedImage": {
              "seed": 123456,
              "mediaGenerationId": "user:12345…redacted…",
              "mediaVisibility": "PRIVATE",
              "prompt": "A serene mountain landscape at sunset with vibrant colors",
              "modelNameType": "IMAGEN_3_5",
              "workflowId": "…redacted…",
              "fifeUrl": "https://storage.googleapis.com/…redacted…",
              "aspectRatio": "IMAGE_ASPECT_RATIO_LANDSCAPE",
              "requestData": {
                "promptInputs": [
                  {
                    "textInput": "A serene mountain landscape at sunset with vibrant colors"
                  }
                ],
                "imageGenerationRequestData": {
                  "imageGenerationImageInputs": []
                }
              }
            }
          }
        }
      ],
      "captcha": {
        "service": "AntiCaptcha",
        "taskId": "abc123...",
        "durationMs": 3500,
        "attempts": [
          {
            "service": "AntiCaptcha",
            "taskId": "abc123...",
            "durationMs": 3500,
            "success": true
          }
        ]
      }
    }
    
  • 400 Bad Request

    Invalid request (validation error, reference count exceeded, email mismatch, or content policy violation).

    General error:

    {
      "error": "Invalid request parameters"
    }
    

    Content policy error:

    {
      "error": {
        "code": 400,
        "message": "Request contains an invalid argument.",
        "status": "INVALID_ARGUMENT",
        "details": [
          {
            "@type": "type.googleapis.com/google.rpc.ErrorInfo",
            "reason": "PUBLIC_ERROR_UNSAFE_GENERATION"
          }
        ]
      }
    }
    
  • 401 Unauthorized

    Invalid API token.

    {
      "error": "Unauthorized"
    }
    
  • 402 Payment Required

    Subscription expired or insufficient credits.

    {
      "error": "Account has no subscription or subscription expired"
    }
    
  • 403 Forbidden

    Request rejected by Google. See Response Codes › 403 above for guidance. Example payload:

    {
      "code": 403,
      "created": "2025-12-23T21:54:26.393Z",
      "error": "API error: 403",
      "jobid": "j1223215426393445325i-u12345-email:us***@gmail.com-bot:google-flow",
      "request": {
        "aspectRatio": "portrait",
        "count": 4,
        "email": "us***@gmail.com",
        "model": "nano-banana-pro",
        "prompt": "A serene mountain landscape at sunset",
        "reference_1": {
          "email": "us***@gmail.com",
          "id": "CAMaJDMxZGNl...***...YmUwMmM",
          "referenceId": "user:12345-email:***-image:CAMaJDMxZGNl...***...YmUwMmM",
          "type": "image",
          "user": 12345
        }
      },
      "response": {
        "captcha": {
          "attempts": [
            {
              "service": "AntiCaptcha",
              "taskId": "14af1dbb-885c-4e25-8121-7a79489dfd0e",
              "durationMs": 5357,
              "success": true
            },
            {
              "service": "AntiCaptcha",
              "taskId": "fd044078-0a4a-4303-a585-26fd5d2acb00",
              "durationMs": 5376,
              "success": true
            },
            {
              "service": "AntiCaptcha",
              "taskId": "ab0251dc-6930-4a82-966a-71fe6ab6aa42",
              "durationMs": 5789,
              "success": true
            }
          ],
          "durationMs": 18091,
          "service": "AntiCaptcha",
          "taskId": "ab0251dc-6930-4a82-966a-71fe6ab6aa42"
        },
        "error": {
          "code": 403,
          "details": [
            {
              "@type": "type.googleapis.com/google.rpc.ErrorInfo",
              "reason": "PUBLIC_ERROR_SOMETHING_WENT_WRONG"
            }
          ],
          "message": "reCAPTCHA evaluation failed",
          "status": "PERMISSION_DENIED"
        }
      },
      "status": "failed",
      "type": "image",
      "updated": "2025-12-23T21:54:45.319Z"
    }
    
  • 404 Not Found

    Account not found or not configured.

    {
      "error": "Google Flow account [email protected] not found"
    }
    
  • 429 Too Many Requests

    Google returns at least four known distinct RESOURCE_EXHAUSTED variants. See Response Codes › 429 above for the right strategy per reason. Example payloads:

    Example — reCAPTCHA evaluation failed (PUBLIC_ERROR_UNUSUAL_ACTIVITY_TOO_MUCH_TRAFFIC):

    {
      "error": {
        "code": 429,
        "message": "reCAPTCHA evaluation failed",
        "status": "RESOURCE_EXHAUSTED",
        "details": [
          {
            "@type": "type.googleapis.com/google.rpc.ErrorInfo",
            "reason": "PUBLIC_ERROR_UNUSUAL_ACTIVITY_TOO_MUCH_TRAFFIC"
          }
        ]
      }
    }
    

    Example — per-user throttling:

    {
      "error": {
        "code": 429,
        "message": "Resource has been exhausted (e.g. check quota).",
        "status": "RESOURCE_EXHAUSTED",
        "details": [
          {
            "@type": "type.googleapis.com/google.rpc.ErrorInfo",
            "reason": "PUBLIC_ERROR_USER_REQUESTS_THROTTLED"
          }
        ]
      }
    }
    

    Example — per-model daily quota reached (e.g., using nano-banana-pro on non-Ultra account):

    {
      "error": {
        "code": 429,
        "message": "Resource has been exhausted (e.g. check quota).",
        "status": "RESOURCE_EXHAUSTED",
        "details": [
          {
            "@type": "type.googleapis.com/google.rpc.ErrorInfo",
            "reason": "PUBLIC_ERROR_PER_MODEL_DAILY_QUOTA_REACHED",
            "metadata": {
              "canUpgradeForQuota": "true"
            }
          }
        ]
      }
    }
    

    Example — account-wide quota reached (PUBLIC_ERROR_USER_QUOTA_REACHED):

    {
      "error": {
        "code": 429,
        "message": "Resource has been exhausted (e.g. check quota).",
        "status": "RESOURCE_EXHAUSTED",
        "details": [
          {
            "@type": "type.googleapis.com/google.rpc.ErrorInfo",
            "reason": "PUBLIC_ERROR_USER_QUOTA_REACHED"
          }
        ]
      }
    }
    

    Example — every configured account is quarantined for the requested model (no_eligible_account):

    When you omit email and every one of your accounts is currently quarantined for the requested model (see Quarantine pre-filter), the API short-circuits with this 429 response — no upstream call to Google is made. Response headers include Retry-After: <seconds> per RFC 7231.

    {
      "error": "no_eligible_account",
      "message": "All your Google Flow accounts have hit Google's daily quota for model 'nano-banana-pro'. This quota resets at UTC midnight (2026-05-20T00:00:10.000Z). Try a different model, or wait.",
      "retryAfter": "2026-05-20T00:00:10.000Z",
      "skipReasons": [
        { "email": "[email protected]", "reason": "PUBLIC_ERROR_PER_MODEL_DAILY_QUOTA_REACHED", "model": "nano-banana-pro" },
        { "email": "[email protected]",   "reason": "PUBLIC_ERROR_PER_MODEL_DAILY_QUOTA_REACHED", "model": "nano-banana-pro" }
      ]
    }
    

    skipReasons lists every account considered and the reason it was filtered, so you can decide whether to wait, switch model, or add more accounts. To bypass the load balancer entirely, specify email explicitly — the request will be sent to Google regardless of quarantine state.

  • 500 Internal Server Error

    One or more generated images were moderated by Google’s content policy. Try one of the following:

    • Switch to imagen-4 model (often successfully processes prompts rejected by nano-banana)
    • Modify your prompt or remove/change reference images
    • Retry the same request (moderation decisions can vary between attempts)
    {
      "error": {
        "code": 500,
        "message": "Internal error encountered.",
        "status": "INTERNAL"
      }
    }
    
  • 503 Service Unavailable

    Service temporarily unavailable or captcha provider error. See Response Codes › 503 above for guidance. Example payloads:

    {
      "error": {
        "code": 503,
        "message": "Service temporarily unavailable.",
        "status": "UNAVAILABLE",
        "details": [
          {
            "@type": "type.googleapis.com/google.rpc.ErrorInfo",
            "reason": "SERVICE_UNAVAILABLE"
          }
        ]
      }
    }
    
    {
      "error": "Captcha service failed: ERROR_ZERO_BALANCE",
      "code": 503
    }
    
  • 596 Session Error

    Google session refresh failed. The account cookies needs to be updated following the instructions in Setup Google Flow.

    {
      "error": "Failed to refresh session."
    }
    

Model

  • jobId - Unique job identifier (for use with GET /jobs/jobId)
  • media - Array of generated images (1-4 images based on count)
  • media[].image.generatedImage - Generated image data object
  • generatedImage.fifeUrl - Direct signed URL to access the generated image (valid for limited time)
  • generatedImage.seed - Seed used for this generation (for reproducibility)
  • generatedImage.mediaGenerationId - mediaGenerationId for use in subsequent API calls
  • generatedImage.prompt - The prompt used for generation
  • generatedImage.modelNameType - Model variant used (IMAGEN_3_5, R2I, GEM_PIX, GEM_PIX_2, NARWHAL)
  • generatedImage.aspectRatio - Generated image aspect ratio (IMAGE_ASPECT_RATIO_LANDSCAPE, IMAGE_ASPECT_RATIO_LANDSCAPE_FOUR_THREE, IMAGE_ASPECT_RATIO_SQUARE, IMAGE_ASPECT_RATIO_PORTRAIT_THREE_FOUR, or IMAGE_ASPECT_RATIO_PORTRAIT)
  • generatedImage.mediaVisibility - Visibility setting (always “PRIVATE”)
  • generatedImage.workflowId - Unique workflow identifier
  • generatedImage.requestData - Request data used for this generation including prompt inputs and reference images
  • media[].name - Internal identifier for the media item
  • media[].workflowId - Unique workflow identifier for this generation
  • captcha - Captcha metadata for debugging/research
  • captcha.service - Provider that returned the successful token
  • captcha.taskId - Task ID from the captcha service
  • captcha.durationMs - Total time for all captcha attempts
  • captcha.attempts - Array of all captcha attempts (including failures)
{
  jobId: string                         // Job identifier
  media: Array<{
    name: string                    // Internal media identifier
    workflowId: string              // Unique workflow ID
    image: {
      generatedImage: {
        seed: number
        mediaGenerationId: string   // Format: user:{userid}-email:{hex}-image:{id}
        mediaVisibility: string     // "PRIVATE"
        prompt: string
        modelNameType: string       // "IMAGEN_3_5" | "R2I" | "GEM_PIX" | "GEM_PIX_2" | "NARWHAL"
        workflowId: string
        fifeUrl: string             // Direct signed URL to generated image
        aspectRatio: string         // "IMAGE_ASPECT_RATIO_LANDSCAPE" | "IMAGE_ASPECT_RATIO_LANDSCAPE_FOUR_THREE" | "IMAGE_ASPECT_RATIO_SQUARE" | "IMAGE_ASPECT_RATIO_PORTRAIT_THREE_FOUR" | "IMAGE_ASPECT_RATIO_PORTRAIT"
        requestData: {
          promptInputs: Array<{
            textInput: string
          }>
          imageGenerationRequestData: {
            imageGenerationImageInputs: Array<{
              mediaGenerationId: string
              imageInputType: string  // "IMAGE_INPUT_TYPE_REFERENCE"
            }>
          }
        }
      }
    }
  }>
  captcha?: {                       // Captcha metadata
    service: string                 // "CapSolver" | "AntiCaptcha" | "YesCaptcha" | "CapMonster" | "SolveCaptcha" | "2Captcha" | "EzCaptcha" | "UserProvided"
    taskId?: string
    durationMs: number
    attempts: Array<{
      service: string
      taskId?: string
      durationMs: number
      success: boolean
      error?: string
    }>
  }
  error?: string | {                // Error: string (useapi.net) or object (Google API)
    code: number
    message: string
    status: string
    details: Array<{
      '@type': string
      reason: string
      metadata?: {
          canUpgradeForQuota: boolean
        }
    }>
  }
  // The following siblings appear only on the load-balancer empty-set 429,
  // i.e. when error === "no_eligible_account" (see 429 response tab).
  message?: string                  // Customer-facing explanation
  retryAfter?: string               // ISO-8601 timestamp of earliest retry
  skipReasons?: Array<{             // Per-account filter rationale
    email: string
    reason: string                  // Google 429 reason that triggered the quarantine
    model: string                   // Quarantined model, or "*" for account-wide
  }>
}

Examples

  • curl -X POST \
         -H "Authorization: Bearer YOUR_API_TOKEN" \
         -H "Content-Type: application/json" \
         -d '{
           "prompt": "A serene mountain landscape at sunset with vibrant colors",
           "model": "imagen-4",
           "aspectRatio": "16:9",
           "count": 4,
           "seed": 123456
         }' \
         "https://api.useapi.net/v1/google-flow/images" > response.json
    
    # Download images using fifeUrl
    curl -o image_1.jpg "$(cat response.json | jq -r '.media[0].image.generatedImage.fifeUrl')"
    curl -o image_2.jpg "$(cat response.json | jq -r '.media[1].image.generatedImage.fifeUrl')"
    # Continue for remaining images...
    
  • const token = 'YOUR_API_TOKEN';
    const apiUrl = 'https://api.useapi.net/v1/google-flow/images';
    
    const response = await fetch(apiUrl, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        prompt: 'A serene mountain landscape at sunset with vibrant colors',
        model: 'imagen-4',
        aspectRatio: '16:9',
        count: 4,
        seed: 123456
      })
    });
    
    const result = await response.json();
    console.log('Generated images:', result.media.length);
    
    // Download and save images
    for (const [index, item] of result.media.entries()) {
      const img = item.image.generatedImage;
      console.log(`Image ${index + 1} seed:`, img.seed);
      console.log(`mediaGenerationId:`, img.mediaGenerationId);
    
      // Download image from fifeUrl
      const imageResponse = await fetch(img.fifeUrl);
      const imageBlob = await imageResponse.blob();
    
      // In Node.js with fs:
      // const buffer = Buffer.from(await imageBlob.arrayBuffer());
      // require('fs').writeFileSync(`generated_image_${index + 1}.jpg`, buffer);
    
      // In browser: create download link or display in <img> element
      // const url = URL.createObjectURL(imageBlob);
      // document.querySelector('img').src = url;
    }
    
  • import requests
    
    token = 'YOUR_API_TOKEN'
    api_url = 'https://api.useapi.net/v1/google-flow/images'
    
    headers = {
        'Authorization': f'Bearer {token}',
        'Content-Type': 'application/json'
    }
    
    data = {
        'prompt': 'A serene mountain landscape at sunset with vibrant colors',
        'model': 'imagen-4',
        'aspectRatio': '16:9',
        'count': 4,
        'seed': 123456
    }
    
    response = requests.post(api_url, headers=headers, json=data)
    result = response.json()
    
    print(f"Generated {len(result['media'])} images")
    
    # Download and save images
    for index, item in enumerate(result['media']):
        img = item['image']['generatedImage']
        print(f"Image {index + 1} seed:", img['seed'])
        print(f"mediaGenerationId:", img['mediaGenerationId'])
    
        # Download image from fifeUrl
        image_response = requests.get(img['fifeUrl'])
        with open(f'generated_image_{index + 1}.jpg', 'wb') as f:
            f.write(image_response.content)
    

Try It