Google shipped Nano Banana 2.1 on October 6, 2026, and quietly cut its own image-generation price in half for the second time in a year. The model now costs $0.0336 per 1K-resolution image on standard pricing, down from $0.067 for Nano Banana 2, and batch requests push that figure to just $0.0168 per image. For a developer running hundreds of product shots, character renders, or marketing variants a day, that gap between retail and batch pricing is the difference between a side project and a line item finance actually asks about.
This tutorial walks through building a real batch image generation pipeline on the Nano Banana 2.1 API: getting a key, writing the first call, locking down a consistent character or product across dozens of variations, submitting and polling batch jobs, and capping spend before a bug turns into a surprise invoice. By the end you will have a working Python project, not just a theoretical overview, plus the pitfalls and troubleshooting notes that usually only show up after the third failed batch job.
Don't miss new tech stories on Google
Add Tech Insider once in the Google app and our stories appear in your news suggestions.
What Nano Banana 2.1 Is and Why Batch Generation Matters
“Nano Banana” is Google’s informal nickname for its Gemini image generation and editing line, and the naming has stuck through several generations. Nano Banana 2 corresponds to the Gemini 3.1 Flash Image model and brought what reviewers described as near-Pro quality at Flash-tier speed, according to The AI Rankings’ image generator tracker. Nano Banana 2.1 is the October 6 update to that line, and Google says it improves across the board on visual design, mask-based editing, and keeping subjects consistent between generations, a detail confirmed by TNW’s coverage of the Gemini rollout.
Google’s own human-preference benchmark gives Nano Banana 2.1 with thinking mode enabled a score of 1,050, ahead of Nano Banana 2 at 990 and, somewhat surprisingly, ahead of the heavier Nano Banana Pro at 935. That ordering matters for this tutorial because it means the mid-tier model, not the flagship, is now the better default for most production workloads. It is faster, cheaper, and scores higher on preference tests than its own “Pro” sibling.
Batch generation matters because of how the economics stack. A single 1K image costs $0.0336 at standard pricing. Run 100 of those one request at a time and you pay $3.36. Submit the same 100 prompts as one batch job and the per-image rate drops to $0.0168, bringing the total to $1.68 before input-token charges. At 2K the gap is $5.04 versus $2.52 for 100 images, and at 4K it is $7.56 versus $3.78. None of that requires a different model or a special contract. It is the same API, a different request shape, and roughly 50% off.
The timing also matters. Google shipped this update into a market that moved fast over the summer: xAI’s Grok Imagine Image 2.0 landed in early August, Microsoft pushed a preview of MAI-Image-2.6 days later, and OpenAI followed with two new GPT Image 2.5 variants on October 8. Every major lab refreshed its image model within roughly a 60-day window, which means a pipeline built around whichever model was “current” in July is already running on last quarter’s pricing and quality tier. That is less a reason to chase every release than a reason to build the pipeline itself so the model string, pricing table, and quality thresholds live in one place and can be swapped without touching the rest of the code, a pattern this tutorial uses throughout.
Prerequisites: Accounts, SDKs, and Versions You Need
Before writing any code, get these pieces in place. None of them cost money to set up, though the API calls themselves are billed once you move past the free tier.
- A Google account with access to Google AI Studio (aistudio.google.com) to generate an API key and confirm the current model identifier.
- Python 3.10 or newer. The examples in this tutorial were written against 3.11.
- The google-genai Python package, version 1.x or later (install command in Step 1).
- A billing-enabled Gemini API project if you plan to exceed the free-tier request quota, since batch jobs for anything beyond a handful of test images will need it.
- A character or product reference image (PNG or JPEG, at least 1024 pixels on the long edge) if you plan to follow the consistency workflow in Steps 4 through 6.
- Roughly 90 minutes if you are following every step and letting a real batch job run to completion.
One naming note worth flagging before you start: Google has not published a separate public model string for the 2.1 point release that differs from the Gemini 3.1 Flash Image identifier tied to Nano Banana 2. In practice, the version bump is served through the same image endpoint with internal routing changes on Google’s side, so the exact model ID you will use should always be copied from the “Get Code” panel inside AI Studio rather than hardcoded from a blog post, including this one. The code below uses a constant you set once and reuse everywhere, specifically so a future model-string change does not break your whole pipeline.
Nano Banana 2.1 Pricing: 1K, 2K, 4K, and Batch Rates
Before building anything, it helps to see the full pricing ladder in one place, since this is the number that decides whether your pipeline uses standard or batch requests, and at which resolution. The figures below come from Google’s published API pricing as compiled by BenchLM’s AI media pricing tracker.
| Model | Resolution | Standard price | Batch price |
|---|---|---|---|
| Nano Banana 2.1 | 1K | $0.0336 | $0.0168 |
| Nano Banana 2.1 | 2K | $0.0504 | $0.0252 |
| Nano Banana 2.1 | 4K | $0.0756 | $0.0378 |
| Nano Banana 2 (previous generation) | 1K | $0.067 | n/a |
| Nano Banana Pro | 1K / 2K | $0.134 | n/a |
| Nano Banana Pro | 4K | $0.24 | n/a |
Two things stand out. First, Nano Banana 2.1 at standard pricing already undercuts Nano Banana 2 by roughly half, so even developers who never touch batch mode get a cost cut just by switching model versions. Second, batch pricing is consistently 50% off standard across every resolution tier, which means the decision to use batch mode is really a decision about latency tolerance, not quality. Batch jobs are not real time. If your use case can wait minutes instead of seconds for a result, batch mode is close to a free discount.
These numbers also exclude input-token charges, which apply when you pass a reference image into the request for character or product consistency. A 1024-pixel reference image adds a modest but non-zero token cost on top of the output price, and it is easy to forget that line item when estimating a batch’s total, a mistake covered in the pitfalls section further down.
Steps 1 to 3: Setting Up Your Gemini API Access
Step 1: Create an API key and install the SDK
Sign in to Google AI Studio, open the API keys panel, and generate a new key scoped to a project with billing enabled if you intend to run anything beyond test volume. Store it as an environment variable rather than pasting it into source files. Then install the official SDK.
pip install --upgrade google-genai
Step 2: Initialize the client
Set the model constant from the AI Studio “Get Code” panel rather than guessing at a string. Every example below reuses this one constant.
import os
from google import genai
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
# Copy the exact current model string from AI Studio's "Get Code"
# panel. Google has routed Nano Banana 2.1 through the same
# image endpoint as Nano Banana 2 (Gemini 3.1 Flash Image), so
# confirm which identifier your account sees before hardcoding it.
NANO_BANANA_MODEL = os.environ.get(
"NANO_BANANA_MODEL_ID", "gemini-3.1-flash-image"
)
Step 3: Run a single test call
Before touching batch mode, confirm the key and model work with one simple request. This also lets you inspect what a raw response object looks like, which matters later when you are parsing hundreds of them automatically.
response = client.models.generate_content(
model=NANO_BANANA_MODEL,
contents=["A single red apple on a white background, studio lighting"],
)
for part in response.candidates[0].content.parts:
if part.inline_data:
with open("test_apple.png", "wb") as f:
f.write(part.inline_data.data)
print("Saved test_apple.png")
If this saves a file without errors, your key, billing, and SDK version are all working. Move on. If it does not, skip ahead to the troubleshooting table before continuing, since nearly every later failure traces back to a problem introduced at this stage.
Securing Your API Key Before You Scale
It is worth pausing here, before building anything bigger, to lock down the one credential that controls your entire bill. A Gemini API key with billing enabled can generate real charges the moment it leaks into a public GitHub repository, a client-side bundle, or a support ticket screenshot. Treat it the same way you would treat a database password, not a convenience string you paste into a notebook cell.
Three habits cover most of the risk. First, load the key from an environment variable or a secrets manager, never from a literal string in source control, which is already how every example in this tutorial reads the key. Second, scope a separate API key per environment, so a leaked development key does not expose production billing, and rotate any key the moment you suspect exposure rather than waiting for unusual charges to show up. Third, set a budget alert at the Google Cloud billing level in addition to the per-job spend cap built in Step 10, since the cap only protects jobs that go through your own code. A leaked key used outside your pipeline will not respect it.
import os
def load_api_key():
key = os.environ.get("GEMINI_API_KEY")
if not key:
raise RuntimeError(
"GEMINI_API_KEY is not set. Store it in your shell profile "
"or secrets manager, never hardcode it in source files."
)
return key
client = genai.Client(api_key=load_api_key())
This small wrapper does two useful things in production: it fails loudly and immediately if the key is missing, instead of letting a cryptic authentication error surface three function calls later, and it gives you one place to swap in a real secrets-manager call later without touching every file that currently reads the environment variable directly.
Steps 4 to 6: Building a Consistent Character Workflow
Step 4: Prepare a reusable reference image
Consistency is the feature Google highlighted hardest with this release, and it is also the one most teams actually need: a brand mascot, a game character, a product shot that has to look the same across ten backgrounds. Start with one clean reference image, ideally a front-facing shot with even lighting and no occlusion, saved at 1024 pixels or larger.
Step 5: Write an explicit edit instruction, not a new prompt
The single biggest improvement in how you prompt for consistency is treating the request as an edit instruction attached to the reference image, rather than writing a fresh text-to-image prompt and hoping the model infers continuity. Be explicit about what must stay fixed and what is allowed to change.
from google.genai import types
reference_image = types.Part.from_bytes(
data=open("character_reference.png", "rb").read(),
mime_type="image/png",
)
edit_prompt = (
"Keep this character's face, hairstyle, and outfit exactly the same. "
"Change only the background to a neon-lit city street at night, "
"and change the pose to a confident walk toward the camera."
)
response = client.models.generate_content(
model=NANO_BANANA_MODEL,
contents=[reference_image, edit_prompt],
config=types.GenerateContentConfig(
response_modalities=["IMAGE"],
),
)
Step 6: Use mask-based editing for tighter control
For cases where a text instruction still drifts too much, mask-based editing narrows the model’s freedom to a specific region. Supply an alpha-channel mask alongside the reference image so only the masked area changes, leaving everything outside it untouched pixel for pixel. This is slower to set up per image but produces the most reliable results for product photography, where a logo or label cannot shift even slightly between variants.
Mask quality matters more than prompt wording at this step. A mask with soft, feathered edges tends to bleed changes into areas you wanted preserved, which is one of the most common pitfalls covered later in this guide.
Steps 7 to 9: Submitting and Monitoring Batch Jobs
Step 7: Build the batch request payload
Batch mode takes a list of individual requests and processes them together at the discounted rate shown in the pricing table above. Structure your prompts as a plain list first, then convert them into request objects.
def build_batch_requests(prompts, resolution="1K"):
return [
{
"model": NANO_BANANA_MODEL,
"contents": [prompt],
"config": {"image_config": {"resolution": resolution}},
}
for prompt in prompts
]
prompt_list = [f"Product shot, variant {i}, white background" for i in range(100)]
requests = build_batch_requests(prompt_list, resolution="1K")
Step 8: Submit the job
batch_job = client.batches.create(requests=requests)
print(f"Submitted batch job: {batch_job.name}")
Step 9: Poll for completion
Batch jobs do not return instantly, and polling too aggressively wastes quota without speeding anything up. A 15-second interval is a reasonable default for jobs under a few hundred images.
import time
while True:
status = client.batches.get(name=batch_job.name)
if status.state in ("SUCCEEDED", "FAILED"):
break
print(f"Job state: {status.state}, waiting...")
time.sleep(15)
print(f"Final state: {status.state}")
Steps 10 to 13: Cost Control, Retries, and Quality Passes
Step 10: Estimate and cap spend before submitting
The single most useful guardrail in this entire pipeline is a hard spend cap that runs before the batch job is ever created, not after the invoice arrives. Wire the pricing table directly into code.
BATCH_PRICE_PER_IMAGE = {
"1K": 0.0168,
"2K": 0.0252,
"4K": 0.0378,
}
def estimate_batch_cost(num_images, resolution="1K"):
return round(num_images * BATCH_PRICE_PER_IMAGE[resolution], 4)
def submit_with_cap(prompts, resolution, spend_cap_usd):
estimated = estimate_batch_cost(len(prompts), resolution)
if estimated > spend_cap_usd:
raise ValueError(
f"Estimated cost ${estimated} exceeds cap ${spend_cap_usd}. "
f"Reduce batch size or resolution before resubmitting."
)
print(f"Estimated cost: ${estimated} for {len(prompts)} images at {resolution}")
return client.batches.create(requests=build_batch_requests(prompts, resolution))
Step 11: Add retry handling with backoff
Rate limits and transient errors happen, especially the first time a new API key ramps up request volume. Exponential backoff with a small random jitter keeps retries from hammering the endpoint in lockstep.
import random
def generate_with_retry(prompt, max_retries=3):
for attempt in range(max_retries):
try:
return client.models.generate_content(
model=NANO_BANANA_MODEL, contents=[prompt]
)
except Exception as exc:
if attempt == max_retries - 1:
raise
delay = (2 ** attempt) + random.random()
print(f"Retry {attempt + 1} after error: {exc}. Waiting {delay:.1f}s")
time.sleep(delay)
Step 12: Tag filenames and metadata for traceability
Once you are generating dozens or hundreds of images a day, you will eventually need to answer “which prompt, resolution, and model version produced this exact file.” Write that metadata alongside the image at save time rather than trying to reconstruct it later.
import json
from datetime import datetime
def save_with_metadata(image_bytes, prompt, resolution, out_dir):
timestamp = datetime.utcnow().strftime("%Y%m%dT%H%M%S")
stem = f"{out_dir}/img_{timestamp}"
with open(f"{stem}.png", "wb") as f:
f.write(image_bytes)
with open(f"{stem}.json", "w") as f:
json.dump(
{
"model": NANO_BANANA_MODEL,
"prompt": prompt,
"resolution": resolution,
"generated_at": timestamp,
},
f,
)
Step 13: Run a second pass only on approved images
Resist the urge to generate everything at 4K by default. Generate the full batch at 1K, review or auto-filter the results, and only send the images that pass review through a second-pass upscale or edit call at 2K or 4K. Since 4K batch pricing is $0.0378 per image versus $0.0168 at 1K, skipping this filtering step on a 1,000-image run is the difference between roughly $17 and $38 for the exact same final output count, once rejects are excluded from the higher tier.
Understanding Rate Limits and Quotas Before You Scale
The retry logic in Step 11 treats rate limiting as something to absorb quietly, but it is worth understanding what is actually happening underneath those 429 errors before you push a pipeline to higher volume. Gemini API projects are assigned request-per-minute and token-per-minute quotas that scale with billing tier, and those quotas apply per project, not per API key. Spinning up a second key under the same project will not raise your ceiling. If you are hitting rate limits consistently rather than occasionally, the fix is a quota increase request or a tier upgrade through Google Cloud, not a more aggressive retry loop.
Batch jobs behave differently from synchronous requests in this respect, which is part of why they are priced lower. Because Google can schedule batch work during lower-demand windows rather than serving it instantly, batch quotas tend to be more generous relative to cost than the real-time endpoint used in Steps 1 through 6. A practical pattern is to route anything latency-sensitive, like a live preview a user is waiting on, through the synchronous endpoint with a tight retry budget, and route everything else, including the 100-image example used throughout this tutorial, through batch mode. That split alone resolves most of the rate-limit pressure teams run into once a pipeline moves from a demo to a daily job.
One more detail worth tracking: quota consumption and spend are two different numbers, and a job can exhaust one without touching the other. A burst of small test requests during development can trip a per-minute quota long before it generates a noticeable charge, which is a common source of confusion the first week a new API key is in use. Logging both the HTTP status code and the response body for any failed request, rather than just catching the exception and retrying, makes it obvious within minutes whether you are hitting a quota ceiling or a genuine error.
Nano Banana 2.1 vs GPT Image 2.5 vs Grok Imagine 2.0: Picking an API
Nano Banana 2.1 is not the only image API that shipped an update this quarter. OpenAI released GPT Image 2.5 Sunburst and GPT Image 2.5 Flare on October 8, 2026, two days after Google’s launch, through both the Image API and the Responses API’s image-generation tool, according to OpenAI’s own API changelog. Flare is tuned for speed and volume, Sunburst for precise editing with native transparent backgrounds, and both support new `xhigh` and `max` quality settings. OpenAI prices image output at $30 per million tokens, with image input at $8 per million tokens and cached image input at $2 per million tokens, a token-based model that makes direct per-image comparison trickier than Google’s flat per-image pricing.
Meanwhile xAI’s Grok Imagine Image 2.0 launched August 7, 2026, and Microsoft’s MAI-Image-2.6 arrived as a preview on August 10, both tracked by Capital and Compute’s monthly AI model release log. Neither has published batch pricing comparable to Nano Banana 2.1’s, which currently gives Google’s API the clearest cost-control story for anyone building an automated pipeline rather than a chat-style one-off tool.
| Model | Maker | Launch date | Approx. price per image | Batch mode |
|---|---|---|---|---|
| Nano Banana 2.1 | Oct 6, 2026 | $0.0336 (1K) | Yes, 50% off | |
| GPT Image 2.5 Flare | OpenAI | Oct 8, 2026 | Token-based, ~$30/M output tokens | No published batch rate |
| GPT Image 2.5 Sunburst | OpenAI | Oct 8, 2026 | Token-based, ~$30/M output tokens | No published batch rate |
| Grok Imagine Image 2.0 | xAI | Aug 7, 2026 | Not publicly itemized | Not publicly itemized |
| Imagen 4 (Standard) | 2026 | $0.04 | Varies by tier | |
| FLUX 3 Image | Black Forest Labs | 2026 | ~$0.03–$0.05 | Provider-dependent |
For a batch pipeline specifically, three things push the decision toward Nano Banana 2.1: flat per-image pricing that is easy to forecast, a published batch discount, and a 1,050 human-preference score that now edges out Google’s own higher-priced Pro tier. Teams that need native transparent backgrounds or GPT Image 2.5’s editing precision for one-off creative work may still prefer Sunburst, but that is a different workload than the high-volume use case this tutorial covers.
Midjourney V8.2 and the FLUX 3 and FLUX.2 lineup round out the field, and both sit in a similar price band to Nano Banana 2.1 at roughly $0.03 to $0.05 per image depending on provider and tier. Neither currently publishes the kind of flat batch discount Google does, which keeps Nano Banana 2.1 ahead specifically for cost-sensitive, high-volume pipelines rather than for raw image quality, where the gap between the top models has narrowed enough that prompt engineering and workflow design now matter more than the underlying model choice.
Common Pitfalls When Building a Batch Pipeline
Most of the mistakes teams make with Nano Banana 2.1 are not bugs in the API. They are assumptions baked into the pipeline code that only break once volume goes up, and nearly all of them trace back to code that was written and tested against a handful of requests, then pointed at a thousand without revisiting the assumptions underneath it.
- Forgetting input-token costs. The per-image prices in the pricing table cover output only. Passing a large reference image into every request in a 500-image batch adds a real, often-overlooked line item to the bill.
- Skipping batch mode out of habit. Submitting requests one at a time because the code was written for a quick test, then never refactored, means paying double for every image once volume climbs.
- Hardcoding a model ID string. Google has changed Nano Banana’s underlying identifiers before. Pipelines that store the model string in a config variable, pulled from an environment default, survive these changes without a code deploy.
- Defaulting to 4K for everything. At $0.0378 per batch image versus $0.0168 at 1K, generating final-resolution output before a human or automated filter has approved the composition more than doubles cost for images that may get discarded anyway.
- Running retries without a ceiling. A retry loop with no maximum attempt count and no spend cap will, eventually, turn a transient rate-limit error into an unbounded bill during an unattended overnight run.
- Assuming perfect consistency. Nano Banana 2.1 scores higher on subject consistency than its predecessors, but it is not guaranteed pixel-identical output. A lightweight review step, even a simple similarity check, catches the small percentage of generations that drift.
Troubleshooting the Nano Banana 2.1 API
These are the errors and symptoms that come up most often once a pipeline moves from a single test call to real batch volume. In most cases the response body carries a specific error code and message beyond the generic HTTP status, so log the full body for any failed request during development rather than only the exception text, which often strips the detail you actually need to diagnose the problem on the first try instead of the third.
| Symptom | Likely cause | Fix |
|---|---|---|
| 429 RESOURCE_EXHAUSTED | Request rate exceeds your project’s quota | Add exponential backoff (Step 11) and lower concurrent request count |
| 400 INVALID_ARGUMENT on resolution field | Resolution string does not match the API’s expected enum | Use the exact “1K”, “2K”, “4K” strings from current docs, not custom pixel dimensions |
| Response has no image data | Safety filters blocked the output silently | Inspect response.candidates[0].finish_reason and reword ambiguous prompt language |
| Character identity drifts between images | Reference image resolution too low, or prompt too vague about what to preserve | Use a reference image of at least 1024px and state explicitly what must stay fixed |
| Batch job stuck in PENDING for hours | Large queue depth across your project or region | Split into smaller batches and check status.error for a specific queue message |
| Actual bill higher than the estimate | Input image tokens were excluded from the cost calculation | Add input-token pricing to estimate_batch_cost for any request that includes a reference image |
| AttributeError on SDK method call | Installed google-genai version predates the method used in these examples | Run pip install –upgrade google-genai and re-check the method name in the current SDK reference |
| Mask edit changes areas outside the mask | Mask edges are too soft or feathered | Use a hard-edged alpha mask with no gradient falloff at the boundary |
| Batch job returns fewer images than submitted | A subset of individual requests failed validation or safety checks within the batch | Check each sub-request’s status field in the batch result, not just the top-level job state |
Advanced Tips for Production Pipelines
Once the basic pipeline works, a few refinements separate a demo script from something a team can actually depend on.
- Reserve thinking mode for complex scenes only. The 1,050 preference score for Nano Banana 2.1 applies to runs with thinking enabled, which costs more compute time per image. For simple product shots on a plain background, the non-thinking path is usually fast enough and cheaper. Save thinking mode for multi-subject or multi-constraint prompts.
- Log cost alongside output, not after the fact. Write the estimated cost from Step 10 into the same metadata file as the image, so a monthly cost review is a simple aggregation query instead of a reconstruction project.
- Set an org-level budget alert, not just a per-job cap. A per-batch spend cap stops one runaway job. A daily or monthly alert at the billing-account level catches the case where many small, individually-reasonable jobs add up.
- Route by use case, not by habit. High-volume, cost-sensitive work fits Nano Banana 2.1’s batch pricing well. One-off creative edits with transparent-background requirements may be cheaper and faster through GPT Image 2.5 Sunburst. Comparing the pricing dynamics across Google’s broader model lineup is a useful habit before committing an entire workload to a single vendor.
- Build a lightweight review queue before any second pass. Even a simple web page that shows the 1K batch output and lets a human click “approve” or “reject” prevents the 4K upscale step from running on images nobody wanted.
Output Examples: What a Completed Batch Job Looks Like
Here is a representative console output from Step 9 through Step 13 run against a 100-image batch at 1K resolution, with cost estimation and metadata tagging active.
Estimated cost: $1.68 for 100 images at 1K
Submitted batch job: batches/nb21-7f3a2c1e
Job state: RUNNING, waiting...
Job state: RUNNING, waiting...
Final state: SUCCEEDED
Batch summary:
Total requests: 100
Succeeded: 97
Failed (safety filter): 2
Failed (invalid argument): 1
Output directory: ./output/nb21-7f3a2c1e/
Review queue: 97 images pending approval
Approved for 4K second pass: 41
Estimated 4K upscale cost: $1.55 (41 images x $0.0378)
Total pipeline cost: $3.23
That last line is the number that actually matters day to day. Running everything at 4K from the start would have cost $7.56 for 100 images. Filtering first and upscaling only the approved 41 brought the real total to $3.23, a workflow that pairs naturally with the kind of spend tracking covered in a dedicated API cost-monitoring setup if you are running this across more than one image model.
The Complete Working Project
Here is every piece from this tutorial combined into one runnable script. Save it as nano_banana_batch.py, set the GEMINI_API_KEY environment variable, and adjust the prompt list and spend cap for your own use case.
import os
import time
import json
import random
from datetime import datetime
from google import genai
from google.genai import types
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
NANO_BANANA_MODEL = os.environ.get("NANO_BANANA_MODEL_ID", "gemini-3.1-flash-image")
BATCH_PRICE_PER_IMAGE = {"1K": 0.0168, "2K": 0.0252, "4K": 0.0378}
def estimate_batch_cost(num_images, resolution="1K"):
return round(num_images * BATCH_PRICE_PER_IMAGE[resolution], 4)
def build_batch_requests(prompts, resolution="1K"):
return [
{
"model": NANO_BANANA_MODEL,
"contents": [p],
"config": {"image_config": {"resolution": resolution}},
}
for p in prompts
]
def submit_with_cap(prompts, resolution, spend_cap_usd):
estimated = estimate_batch_cost(len(prompts), resolution)
if estimated > spend_cap_usd:
raise ValueError(f"Estimated cost ${estimated} exceeds cap ${spend_cap_usd}")
print(f"Estimated cost: ${estimated} for {len(prompts)} images at {resolution}")
return client.batches.create(requests=build_batch_requests(prompts, resolution))
def wait_for_batch(batch_job, poll_seconds=15):
while True:
status = client.batches.get(name=batch_job.name)
if status.state in ("SUCCEEDED", "FAILED"):
return status
print(f"Job state: {status.state}, waiting...")
time.sleep(poll_seconds)
def generate_with_retry(prompt, max_retries=3):
for attempt in range(max_retries):
try:
return client.models.generate_content(model=NANO_BANANA_MODEL, contents=[prompt])
except Exception as exc:
if attempt == max_retries - 1:
raise
delay = (2 ** attempt) + random.random()
print(f"Retry {attempt + 1} after error: {exc}. Waiting {delay:.1f}s")
time.sleep(delay)
def save_with_metadata(image_bytes, prompt, resolution, out_dir="./output"):
os.makedirs(out_dir, exist_ok=True)
timestamp = datetime.utcnow().strftime("%Y%m%dT%H%M%S%f")
stem = f"{out_dir}/img_{timestamp}"
with open(f"{stem}.png", "wb") as f:
f.write(image_bytes)
with open(f"{stem}.json", "w") as f:
json.dump(
{"model": NANO_BANANA_MODEL, "prompt": prompt, "resolution": resolution},
f,
)
return stem
if __name__ == "__main__":
prompts = [f"Product shot, variant {i}, white background" for i in range(100)]
job = submit_with_cap(prompts, resolution="1K", spend_cap_usd=2.00)
result = wait_for_batch(job)
print(f"Final state: {result.state}")
This is intentionally a starting point, not a finished product. A real deployment would add structured logging, a database record per generated image instead of flat JSON files, and a web-facing review queue. But every piece needed to generate, cap, retry, and track cost for a batch of Nano Banana 2.1 images is already here and runs as written, assuming a valid API key and a billing-enabled project.
Scaling Beyond the First Batch
Once this pipeline is stable at 100 images, the jump to 1,000 or 10,000 is mostly about queue management rather than new API concepts. Split large runs into multiple batch jobs rather than one giant request, since smaller batches clear faster and a single failed sub-request does not hold up the entire set. Track cost per job in a simple spreadsheet or database table so a sudden spike in average cost per image, which usually signals accidental 4K generation or an unexpectedly high retry rate, shows up immediately rather than at the end of the month.
It is also worth revisiting your model choice periodically. Google updated this model twice within roughly a year, each time cutting price while raising the preference score, and other vendors are moving on similar timelines. A pipeline built around a config-driven model string, rather than a model name scattered across a codebase, makes that kind of switch a one-line change instead of a rewrite. The same discipline applies if you are also generating images through OpenAI’s GPT Image 2.5 API or Microsoft’s Foundry MAI-Image-2.6 for different parts of a workflow, since keeping cost tracking and retry logic consistent across providers saves far more engineering time than optimizing any single call.
For teams specifically chasing photorealistic output rather than stylized or product imagery, the resolution and consistency trade-offs covered here still apply, though prompt structure shifts slightly toward lighting and lens language rather than editing instructions. A dedicated look at building a realistic AI photo pipeline covers that variant in more depth, including the model-specific settings that most affect photorealism.
Frequently Asked Questions
What is Nano Banana 2.1 and how is it different from Nano Banana 2?
Nano Banana 2.1 is Google’s October 6, 2026 update to its Gemini image generation and editing line. It builds on Nano Banana 2 (Gemini 3.1 Flash Image) with improvements to visual design, mask-based editing, and subject consistency, and it costs roughly half as much per image at standard pricing.
How much does the Nano Banana 2.1 API cost per image?
Standard pricing is $0.0336 per 1K-resolution image, $0.0504 at 2K, and $0.0756 at 4K. Batch mode cuts each of those roughly in half, to $0.0168, $0.0252, and $0.0378 respectively, before input-token charges.
Does batch processing really cut the price in half?
Yes, consistently across every published resolution tier. The trade-off is latency: batch jobs process over minutes rather than returning synchronously, so they fit scheduled or offline workloads better than live, user-facing requests.
Can I use Nano Banana 2.1 for free?
Google offers free-tier access through the Gemini app and limited quota in AI Studio and the API, but any meaningful batch volume for a production pipeline will move past free-tier limits and incur the per-image charges covered in this tutorial.
How do I keep a character or product consistent across multiple images?
Pass a clean, high-resolution reference image alongside an explicit edit instruction that states what must stay fixed, such as face, outfit, or logo placement, and what is allowed to change, such as pose or background. For tighter control, use mask-based editing with a hard-edged alpha mask.
What’s the difference between Nano Banana 2.1 and GPT Image 2.5?
Nano Banana 2.1 uses flat per-image pricing with a published batch discount, while GPT Image 2.5 Flare and Sunburst price by token, around $30 per million output tokens. GPT Image 2.5 Sunburst adds native transparent background support that Nano Banana 2.1 does not match in the same way, making it a better fit for certain one-off editing tasks even though it lacks a comparable batch discount.
Why did my batch job return fewer images than I submitted?
Individual requests inside a batch can fail independently due to safety filters or validation errors without failing the whole job. Check each sub-request’s status field in the batch result rather than relying only on the top-level job state.
Is Nano Banana 2.1 available outside the Gemini API?
Yes. Google has rolled it out across the Gemini app, Google AI Studio, the Gemini API, AI Mode in Search, and Flow, giving developers and casual users several different entry points depending on whether they need programmatic access or a simple interface.





