Google shut off Imagen 4 inside the Gemini API on August 17, 2026. Any app still calling imagen-4.0-generate-001, imagen-4.0-fast-generate-001, or imagen-4.0-ultra-generate-001 now gets a hard failure instead of a picture. The replacement, Nano Banana 2 (officially Gemini 3.1 Flash Image), uses a different endpoint, a different method name, and a different response shape, so a find-and-replace on the model string will not save you.
This tutorial walks through the full migration: auditing old Imagen calls, wiring up Nano Banana 2 in Python and Node, handling the new imageConfig resolution and aspect-ratio controls, building multi-image reference editing, estimating per-image cost from token counts, and shipping a small production service with retry logic. By the end you will have a working product-photo editor built entirely on the new API, plus a troubleshooting list for the errors developers are already hitting in the first weeks after the Imagen shutdown.
Why Imagen 4’s Shutdown Forces This Migration Right Now
Google had been warning developers about this for months before pulling the trigger. The Gemini API documentation now states flatly that Imagen is Google’s legacy image generation model and that it is now shut down and no longer available in the Gemini API. That is not a soft deprecation notice with a vague future date. Calls to any Imagen 4 model ID made after August 17, 2026 return an error, which means a meaningful share of production image-generation pipelines broke overnight unless someone had already migrated.
The timing matters because the two events are offset. Gemini 3.1 Flash Image, the model nicknamed Nano Banana 2, actually reached general availability on May 28, 2026, about three months before Imagen 4 went dark, according to Google Cloud’s model documentation. Teams that waited for the shutdown deadline instead of migrating early lost that cushion. If your app, a SaaS tool, an internal content pipeline, or a side project still points at an Imagen model ID today, October 3, 2026, it is already broken in production, not just scheduled to break.
There is also a cost angle. Nano Banana 2 is not simply Imagen 4 renamed. It is a native Gemini multimodal model that happens to output images as content parts alongside text, which changes both the request format and how Google bills you. Getting the migration right the first time avoids a second rewrite later, and understanding the new pricing model up front prevents surprise bills once a feature that used to cost a fixed per-image rate suddenly scales with resolution and token counts instead.
Imagen 4 vs Nano Banana 2: What Actually Changed
Before touching any code, it helps to see the full picture of what moved. Imagen was a dedicated image-generation API with its own endpoint and response object. Nano Banana 2 is accessed through Gemini’s general-purpose generateContent endpoint, the same one used for text and chat completions, with image output requested as one of several possible response modalities. The table below lines up the two generations side by side using the same categories.
| Category | Imagen 4 (shut down) | Nano Banana 2 (current) |
|---|---|---|
| Model IDs | imagen-4.0-generate-001, imagen-4.0-fast-generate-001, imagen-4.0-ultra-generate-001 |
gemini-3.1-flash-image (plus gemini-3-pro-image for the Pro tier) |
| SDK method | generate_images() |
generate_content() |
| Response shape | Dedicated image object | candidates[].content.parts[] with inlineData |
| Resolution control | Fixed per model variant | imageConfig.imageSize: 512, 1K, 2K, 4K |
| Max output tokens | Not applicable (image-only) | 32,768 |
| Status | Shut down August 17, 2026 | Stable GA since May 28, 2026 |
Google’s own image-generation documentation now describes Nano Banana as the generalist model family for “all tasks,” pairing speed with 4K output, broader world knowledge, and more reliable text rendering inside images than the old Imagen line offered. Nano Banana 2 sits as the mainstream, high-efficiency option, while a separate model, Nano Banana Pro (gemini-3-pro-image), targets the heavier editing jobs that used to go to Imagen 4 Ultra. There is also a cheaper Nano Banana 2 Lite variant (gemini-3.1-flash-lite-image), which reached GA on June 23, 2026, for high-volume, lower-stakes generation.
Where Nano Banana 2 Fits in Google’s Image Model Lineup
Before you pick a model ID and move on, it is worth understanding that “Nano Banana” is now a family name, not a single model, the same way “Imagen 4” used to cover standard, fast, and ultra variants under one umbrella. Picking the wrong family member for your workload is a quieter mistake than calling a dead Imagen endpoint, but it still shows up later as either an overpaying production bill or a model that is not quite capable enough for the job.
| Product name | API model ID | Release status | Best fit |
|---|---|---|---|
| Nano Banana 1 | gemini-2.5-flash-image |
Earlier generation, still callable | Legacy code you have not migrated yet; not recommended for new work |
| Nano Banana 2 | gemini-3.1-flash-image |
Stable GA since May 28, 2026 | General-purpose generation and editing, the default choice for most apps |
| Nano Banana 2 Lite | gemini-3.1-flash-lite-image |
GA since June 23, 2026 | High-volume, cost-sensitive generation where peak fidelity does not matter |
| Nano Banana Pro | gemini-3-pro-image |
GA alongside Nano Banana 2 | Complex multi-reference edits, the direct successor to Imagen 4 Ultra |
A reasonable default for a brand-new integration is to start on Nano Banana 2, measure quality and cost against your real traffic, and only move specific endpoints down to Lite or up to Pro once you have data showing the standard tier is either overkill or insufficient for that particular feature. Resist the temptation to default straight to Pro because it sounds like the premium option. It costs more, and for most text-to-image and single-edit use cases the difference in output quality over standard Nano Banana 2 is not large enough to justify the extra spend.
Prerequisites: Versions, Accounts, and Tools You Need
You do not need much to follow along, but a few pieces have to be current. Older guides built around Imagen will reference an SDK method that no longer resolves to anything useful, so confirm these versions before starting.
- A Google AI Studio or Google Cloud account with a Gemini API key and billing enabled (the free tier works for testing, but production image generation needs a billed project)
- Python 3.10 or newer, or Node.js 18 or newer, depending on which half of this tutorial you follow
- The current
google-genaiPython package (installed via pip; this replaced the oldergoogle-generativeaipackage family used in Imagen-era tutorials) - The
@google/genainpm package for the Node.js section - A terminal, an editor, and roughly 90 minutes if you are migrating a real codebase rather than just testing the new API cold
- Any existing Imagen 4 integration code you want to port, so you can diff the before-and-after side by side
One more prerequisite that is easy to skip: read through the official Imagen-to-Gemini migration notes once before you start rewriting, even if you plan to follow this tutorial’s code directly. Google updates model IDs and parameter names more often than most REST APIs, and that page is the canonical source if anything in this article drifts out of date after publication.
Steps 1-3: Audit Your Code, Get API Access, and Install the SDK
Step 1: Audit every Imagen call in your codebase
Search your repository for the three dead model IDs and for the method name that no longer works. A simple grep catches almost everything:
grep -rn "imagen-4.0|imagen-3.0|generate_images|generateImages" --include="*.py" --include="*.js" --include="*.ts" .
Make a list of every call site, the model variant it used (standard, fast, or ultra), and whether it relied on any Imagen-specific parameter such as sampleCount, negativePrompt, or personGeneration. Those parameter names do not carry over cleanly, and you will need to decide a Gemini-equivalent behavior for each one during Step 4.
Step 2: Get a Gemini API key and confirm billing
If your Imagen integration already used a Gemini API key, you likely do not need a new one, since Nano Banana 2 is accessed through the same key and the same base endpoint. Generate or confirm a key in Google AI Studio, then export it as an environment variable rather than hardcoding it:
export GEMINI_API_KEY="your-key-here"
Check the current Gemini Developer API pricing page for your project tier before you push anything to production. Image-output billing changed meaningfully from the old flat-rate Imagen pricing to a token-based model, covered in detail in Step 10.
Step 3: Install the current SDK
Remove any legacy Imagen-only client library and install the unified google-genai package, which covers text, chat, and image generation through one client object:
pip install --upgrade google-genai
npm install @google/genai
Run pip show google-genai afterward and confirm the install actually completed. This is the single most common point where old tutorials go stale: several Imagen-era blog posts still reference an older, now-superseded package name, and mixing the two in one virtual environment produces confusing import errors that look like authentication problems but are not.
Steps 4-5: Map Old Models and Rewrite the Core Generation Call
Step 4: Map each Imagen model ID to its Nano Banana replacement
Google’s migration guidance gives a direct mapping from each retired Imagen variant to a Gemini image model and, where relevant, a thinking-level setting that approximates the old quality tier. Use this table as your conversion key for every call site found in Step 1.
| Former Imagen model | Recommended Gemini replacement | Notes |
|---|---|---|
imagen-4.0-fast-generate-001 |
gemini-3.1-flash-image |
Set thinking level to MINIMAL for the closest speed match |
imagen-4.0-generate-001 |
gemini-3.1-flash-image |
Set thinking level to HIGH for closer quality parity |
imagen-4.0-ultra-generate-001 |
gemini-3-pro-image |
The Ultra tier maps to the Pro-series model, not Flash |
imagen-3.0-capability-001 |
gemini-3.1-flash-image |
Older Imagen 3 capability features are reworked as conversational editing |
Notice that the Ultra tier does not map to a higher setting on the same Flash model. It maps to an entirely different model family, Gemini 3 Pro Image, which costs more and runs slower in exchange for better fidelity on complex edits. If your app offered an Imagen 4 Ultra option as a premium tier, keep that distinction in your own pricing by routing those requests to gemini-3-pro-image rather than trying to simulate it with Flash.
Step 5: Rewrite generate_images() as generate_content()
This is the change that breaks the most code, because it is not a parameter rename, it is a different method on a different object. Here is the shape of a typical Imagen 4 call next to its Nano Banana 2 replacement.
# Old Imagen 4 call (no longer works after August 17, 2026)
response = client.models.generate_images(
model="imagen-4.0-generate-001",
prompt="A cinematic product photo of a red bicycle in a studio",
)
image = response.generated_images[0]
image.image.save("output.png")
# New Nano Banana 2 call
from google import genai
from google.genai import types
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
response = client.models.generate_content(
model="gemini-3.1-flash-image",
contents="A cinematic product photo of a red bicycle in a studio",
config=types.GenerateContentConfig(
response_modalities=["TEXT", "IMAGE"],
image_config=types.ImageConfig(
aspect_ratio="16:9",
image_size="2K",
),
),
)
for part in response.candidates[0].content.parts:
if part.text:
print(part.text)
elif part.inline_data:
part.as_image().save("output.png")
Two details trip up almost everyone on the first pass. First, you must explicitly ask for image output through response_modalities, since Gemini’s default behavior assumes you might only want text back. Second, the image no longer arrives as a dedicated field on the response. It shows up as one part among potentially several in candidates[0].content.parts, so your parsing loop has to check each part’s type instead of assuming a fixed shape.
Steps 6-7: Set Response Modalities and Parse the New Response Shape
Step 6: Choose the right response_modalities for your use case
Imagen only ever returned images. Nano Banana 2 can return text, an image, or both in the same call, which is genuinely useful but requires a decision on your end. If your UI wants a caption or a short explanation alongside the picture, request both:
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"]
}
If you just need the image and want to keep the response payload small, drop it to ["IMAGE"] alone. Leaving this field out entirely is the single most common cause of “it returned text but no image” bug reports in early Nano Banana 2 migrations, since omitting it does not reliably default to image output the way developers coming from Imagen tend to assume.
Step 7: Parse candidates, content, and parts correctly
Build a small helper rather than inlining the parsing logic everywhere you call the model. It pays off the first time a response comes back with only text, which happens if the model declines an unsafe prompt or needs clarification.
def extract_image_and_text(response):
text_out = None
image_bytes = None
candidate = response.candidates[0]
for part in candidate.content.parts:
if getattr(part, "text", None):
text_out = part.text
elif getattr(part, "inline_data", None):
image_bytes = part.inline_data.data
return text_out, image_bytes
Treat a missing inline_data part as a normal, expected outcome in your error handling, not an exception. Prompts that trip a safety filter, or requests where the model decided text alone answered the question, will legitimately come back with no image part at all.
Check candidate.finish_reason alongside the parts array rather than relying only on the presence or absence of inline_data. A finish reason of SAFETY tells you the request was declined on content grounds and retrying with the same prompt will just burn another call. A finish reason tied to a length or token limit instead suggests the prompt or reference images pushed the request past a usable size, which is a different fix entirely, usually trimming the instruction text or compressing a reference image before resubmitting. Logging the finish reason alongside your cost estimator gives you a single place to spot whether declines are a prompt-wording problem or a genuine policy mismatch for your product.
Step 8: Control Aspect Ratio and Resolution (512 / 1K / 2K / 4K)
Imagen handled resolution largely through which model variant you called. Nano Banana 2 exposes it directly as a request parameter, which gives you more control but means you now have to pick a value explicitly instead of relying on a model-level default tuned by Google.
The imageConfig.aspectRatio field accepts standard ratios including 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, and 21:9. The imageConfig.imageSize field accepts 512, 1K, 2K, or 4K. Each resolution tier consumes a different number of output tokens, which directly drives your bill, so resolution is now a cost decision as much as a quality one.
config = types.GenerateContentConfig(
response_modalities=["IMAGE"],
image_config=types.ImageConfig(
aspect_ratio="4:5",
image_size="1K",
),
)
If your product previously offered a fixed set of sizes tied to Imagen’s standard, fast, and ultra variants, map each of those tiers to an explicit imageSize value in your own code rather than letting it default. Defaults can and do shift between SDK versions, and a silent resolution change is the kind of bug that shows up as a support ticket from a confused user rather than a failed test.
Step 9: Build Multi-Image Reference Editing
One of the real upgrades over Imagen is native support for multi-image conversational editing, meaning you can hand the model two or more reference images plus an instruction in a single request and get a composited result back. Imagen required separate, more rigid editing endpoints for anything like this. Nano Banana 2 handles it through the same contents array you already use for text prompts, just with image parts added before the instruction.
import base64
def load_image_part(path, mime_type):
with open(path, "rb") as f:
data = base64.b64encode(f.read()).decode("utf-8")
return {"inlineData": {"mimeType": mime_type, "data": data}}
response = client.models.generate_content(
model="gemini-3.1-flash-image",
contents=[
{
"role": "user",
"parts": [
load_image_part("model_reference.jpg", "image/jpeg"),
load_image_part("outfit_reference.png", "image/png"),
{"text": "Combine these into one editorial fashion photo. "
"Keep the person's identity from the first image "
"and use the clothing from the second."},
],
}
],
config=types.GenerateContentConfig(
response_modalities=["IMAGE"],
image_config=types.ImageConfig(aspect_ratio="4:5", image_size="2K"),
),
)
Keep each reference image under a reasonable file size before encoding it to base64, since inline image data counts against the request payload and against your input token bill at roughly 1,120 tokens per input image regardless of its original file size. For anything beyond a handful of reference images per call, resize them client-side first rather than sending full-resolution originals.
Step 10: Add a Token-Based Cost Estimator
Imagen billed per image at a flat rate per variant, which made cost forecasting trivial. Nano Banana 2 bills by tokens, with input priced separately from output and output scaling by resolution. According to Google’s published Gemini Developer API rates, text and image input cost $0.50 per million tokens, text and thinking output costs $3 per million tokens, and image output costs $60 per million tokens. Translated into per-image terms using Google’s own token counts, a 512-class image runs about $0.045, a 1K image about $0.067, a 2K image about $0.101, and a 4K image about $0.151.
| Output resolution | Approximate output tokens | Approximate cost per image |
|---|---|---|
| 512 (roughly 0.25MP) | 747 tokens | $0.045 |
| 1K (roughly 1MP) | 1,120 tokens | $0.067 |
| 2K | 1,680 tokens | $0.101 |
| 4K | 2,520 tokens | $0.151 |
Build this into your own request wrapper so you can log and cap spend before it surprises anyone. The rates above come straight from Google’s published pricing documentation, but confirm them against the live pricing page before hardcoding anything into a billing dashboard, since Google has adjusted image-model pricing more than once this year.
INPUT_RATE_PER_TOKEN = 0.50 / 1_000_000
OUTPUT_IMAGE_RATE_PER_TOKEN = 60.0 / 1_000_000
OUTPUT_TOKENS_BY_SIZE = {
"512": 747,
"1K": 1120,
"2K": 1680,
"4K": 2520,
}
def estimate_cost(num_input_images, output_size):
input_cost = num_input_images * 1120 * INPUT_RATE_PER_TOKEN
output_tokens = OUTPUT_TOKENS_BY_SIZE[output_size]
output_cost = output_tokens * OUTPUT_IMAGE_RATE_PER_TOKEN
return round(input_cost + output_cost, 4)
print(estimate_cost(num_input_images=2, output_size="2K"))
For context on where that leaves you competitively, a September 2026 pricing comparison from teamday.ai put GPT Image 2.5’s Sunburst tier at roughly $0.014 per token-billed image under its own measurement, while independent per-generation testing from OpenRouter found a 22x spread in per-image cost across the 20 image models it benchmarked that month. Nano Banana 2 sits in the middle of that range at 1K and toward the upper half at 4K, which is worth knowing before you pick a default resolution for a high-volume feature.
Step 11: Port the Workflow to Node.js
If your stack is JavaScript or TypeScript rather than Python, the same migration applies through the @google/genai package. The method name and config shape mirror the Python SDK closely enough that porting is mostly mechanical once you understand the Python version above.
import { GoogleGenAI } from "@google/genai";
import fs from "node:fs";
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const response = await ai.models.generateContent({
model: "gemini-3.1-flash-image",
contents: "A cinematic product photo of a red bicycle in a studio",
config: {
responseModalities: ["TEXT", "IMAGE"],
imageConfig: {
aspectRatio: "16:9",
imageSize: "2K",
},
},
});
for (const part of response.candidates?.[0]?.content?.parts ?? []) {
if (part.text) {
console.log(part.text);
}
if (part.inlineData) {
fs.writeFileSync("output.png", Buffer.from(part.inlineData.data, "base64"));
}
}
The optional chaining on response.candidates?.[0]?.content?.parts is not defensive paranoia. Candidates can come back with an empty parts array when a prompt is rejected, and crashing a Node service on an unguarded array access over a rejected prompt is an avoidable production incident.
Steps 12-13: Test, Benchmark, and Deploy With Retry Logic
Step 12: Run the same prompt set through both resolutions and models
Before cutting over fully, run your 10 to 20 most common production prompts through gemini-3.1-flash-image at the resolution you plan to default to, and compare output quality and latency against what Imagen 4 used to produce for the same prompts. Google’s own documentation does not publish an independent benchmark pitting Nano Banana 2 against GPT Image 2.5, Seedream, or FLUX.2, and no credible third-party test currently controls for identical prompts, seeds, and resolution across all of those models at once. Treat any specific win-rate number you see quoted online skeptically unless the source discloses its exact test methodology, and rely on your own side-by-side comparison against your own prompts instead.
Build this comparison into an actual script rather than eyeballing a handful of outputs in a notebook. Loop through your prompt list, record wall-clock latency for each call, save every output image to a labeled folder, and log the estimated cost from Step 10 next to each result. Within a day of production traffic you will usually find that a handful of prompt categories, like close-up text rendering or anything involving hands, behave differently between models, and that is far more useful information for your specific product than a generic leaderboard score pulled from someone else’s test set.
Step 13: Add retry logic and deploy
Rate limits and transient errors do not disappear just because you migrated models. Wrap the call in exponential backoff before you ship it, since a bare try/except around a single call will fail hard the first time you hit a quota blip during a traffic spike.
import time
def generate_with_retry(client, model, contents, config, max_attempts=4):
for attempt in range(max_attempts):
try:
return client.models.generate_content(
model=model, contents=contents, config=config
)
except Exception as exc:
if attempt == max_attempts - 1:
raise
wait = 2 ** attempt
print(f"Attempt {attempt + 1} failed ({exc}), retrying in {wait}s")
time.sleep(wait)
Deploy behind a feature flag if you can, route a small percentage of traffic to the new path first, and watch your cost estimator numbers against your actual billing dashboard for a few days before sending everything through Nano Banana 2.
The Complete Working Project: A Product-Photo Editing Microservice
Putting every step together, here is a minimal but complete Flask-style service that accepts a product photo and a text instruction, edits it with Nano Banana 2, logs the estimated cost, and returns the result. This mirrors the kind of e-commerce image-editing feature that commonly ran on Imagen 4 before the shutdown.
import base64
import os
from flask import Flask, request, send_file, jsonify
from google import genai
from google.genai import types
app = Flask(__name__)
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
OUTPUT_TOKENS_BY_SIZE = {"512": 747, "1K": 1120, "2K": 1680, "4K": 2520}
def estimate_cost(num_input_images, output_size):
input_cost = num_input_images * 1120 * (0.50 / 1_000_000)
output_cost = OUTPUT_TOKENS_BY_SIZE[output_size] * (60.0 / 1_000_000)
return round(input_cost + output_cost, 4)
@app.route("/edit-product-photo", methods=["POST"])
def edit_product_photo():
image_file = request.files["image"]
instruction = request.form.get("instruction", "Enhance lighting and remove background clutter")
output_size = request.form.get("size", "1K")
image_data = base64.b64encode(image_file.read()).decode("utf-8")
response = client.models.generate_content(
model="gemini-3.1-flash-image",
contents=[
{
"role": "user",
"parts": [
{"inlineData": {"mimeType": "image/jpeg", "data": image_data}},
{"text": instruction},
],
}
],
config=types.GenerateContentConfig(
response_modalities=["IMAGE"],
image_config=types.ImageConfig(aspect_ratio="1:1", image_size=output_size),
),
)
for part in response.candidates[0].content.parts:
if part.inline_data:
part.as_image().save("/tmp/edited_output.png")
cost = estimate_cost(num_input_images=1, output_size=output_size)
return send_file("/tmp/edited_output.png", mimetype="image/png")
return jsonify({"error": "No image returned, prompt may have been declined"}), 422
if __name__ == "__main__":
app.run(port=8080)
This handles the full round trip: accept an upload, read the edit instruction, send both to Nano Banana 2 with an explicit resolution, parse the response the way Step 7 described, and fail gracefully with a readable error instead of a stack trace when the model returns text only. Extend it with the retry wrapper from Step 13 and the cost logger from Step 10 before putting it anywhere near real traffic.
Common Pitfalls and Troubleshooting: 13 Issues You’ll Hit
Common pitfalls
- Assuming generate_images() still exists. It does not route to Nano Banana. Every Imagen-era call site needs the full rewrite to
generate_content(), not a parameter patch. - Forgetting response_modalities. Without explicitly requesting
IMAGE, you can get a text-only response back and spend an hour debugging a “missing image” bug that is really a missing config field. - Hardcoding the preview model ID.
gemini-3.1-flash-image-previewandgemini-3.1-flash-imageare not the same model, and preview IDs can change behavior or disappear without the stability guarantees of the GA model. - Copying Imagen’s sampleCount or numberOfImages field. Nano Banana does not document a stable equivalent for generating multiple images in a single call. Loop separate requests instead of assuming the old field still works.
- Ignoring resolution’s effect on cost. Defaulting every request to 4K because it looks nicer in a demo can roughly triple your per-image bill compared to 1K, with no cost ceiling unless you add one yourself.
Troubleshooting checklist
| Symptom | Likely cause | Fix |
|---|---|---|
| Request fails immediately with a model-not-found style error | Still calling an Imagen 4 model ID | Replace with gemini-3.1-flash-image or gemini-3-pro-image per the mapping table in Step 4 |
| Response contains text but no image | response_modalities omitted or set to ["TEXT"] only |
Set response_modalities to ["IMAGE"] or ["TEXT", "IMAGE"] |
| AttributeError on response.generated_images | Old Imagen response parsing left in place | Switch to iterating candidates[0].content.parts as shown in Step 7 |
| Images come back smaller or larger than expected | No explicit imageSize set |
Set imageConfig.imageSize explicitly rather than relying on a default |
| Bill spikes after migration | All requests defaulting to 4K output | Audit resolution per feature and cap high-cost tiers behind a plan or quota |
| Multi-image edit ignores one of the reference images | Image parts ordered after the text instruction | Place all image parts before the text instruction in the parts array |
| Intermittent 429 or quota errors under load | No retry/backoff on transient rate limits | Add exponential backoff as shown in Step 13 |
| SDK import errors referencing an unknown module | Legacy Imagen-only client package still installed alongside google-genai |
Uninstall the old package and reinstall a clean google-genai environment |
Advanced Tips for Production Nano Banana 2 Deployments
Once the basic migration works, a few refinements separate a demo from something that survives real traffic. Cache input images by hash before re-encoding them to base64 on every retry, since re-encoding a large reference image repeatedly wastes CPU without changing the token cost. Set a hard resolution ceiling per subscription tier in your own application logic rather than trusting client-supplied parameters, since nothing stops a request from asking for 4K on every call if your API does not enforce a cap server-side.
Preserve whatever provenance or metadata Google attaches to generated images rather than stripping it during post-processing. Google’s documentation frames Nano Banana output as carrying Google’s own safety and provenance controls, which likely includes some form of SynthID-style watermarking signal, though the exact mandatory behavior across every API surface is not fully spelled out in current public docs. If your application resizes or re-encodes images after generation, test whether that process destroys embedded provenance data, and flag that explicitly to your legal or trust-and-safety team if your product has disclosure obligations around AI-generated imagery.
Watch concurrency as closely as you watch cost. Gemini’s image models publish a maximum output token count of 32,768 per response, and a burst of simultaneous 4K-resolution requests from a single worker process can saturate your available throughput faster than a text-only workload would, since each image response carries far more output tokens than a typical chat completion. If you run a job queue for batch image generation, cap concurrent in-flight requests explicitly rather than firing every job at once, and separate your retry backoff counters per worker so one failing batch does not starve the rest of the queue while it waits out its exponential delay.
Add a dashboard panel, even a basic one, that tracks three numbers over time: average cost per generated image, the ratio of declined-to-successful requests, and the split of traffic across resolution tiers. Those three numbers together catch almost every regression this migration can introduce, from a UI bug that silently defaults every request to 4K, to a prompt template change that starts tripping the safety filter more often than before.
Finally, keep an eye on the Gemini API changelog rather than assuming today’s model IDs are permanent. Google has already retired an entire model family once this year. Building a single config constant for your active model ID, rather than scattering the string literal across your codebase, is the cheapest insurance against doing this whole migration again from scratch the next time Google ships a Nano Banana 3.
For comparison shopping across the broader image-model field, our breakdown of GPT Image 2 vs Nano Banana Pro covers how the higher-end tiers stack up, and our GPT Image 2.5 API setup guide walks through OpenAI’s competing Flare and Sunburst models using the same step format as this article. If you would rather self-host than call a hosted API at all, see our guide to self-hosting Qwen-Image-2.1.
Frequently Asked Questions
Is Imagen 4 completely gone from the Gemini API?
Yes. Google’s documentation states Imagen models are shut down and no longer available in the Gemini API, with the retirement taking effect August 17, 2026 for the standard, fast, and ultra variants.
What is the exact model ID I should call for Nano Banana 2?
Use gemini-3.1-flash-image for the stable, generally available version. A preview variant, gemini-3.1-flash-image-preview, also exists but should not be hardcoded into production code. If you need a Gemini API key first, our step-by-step key setup guide covers that from scratch.
Does Nano Banana 2 cost more than Imagen 4 did?
It depends entirely on resolution. Nano Banana 2 bills by output tokens, which works out to roughly $0.045 per 512-class image up to about $0.151 per 4K image based on Google’s published per-million-token rates. Compare that against your specific Imagen 4 variant’s old flat rate for your typical output size before assuming either direction.
Can I still generate multiple images from a single API call, like Imagen’s sampleCount did?
There is no publicly documented, stable equivalent field for the Gemini API as of this writing. The safer approach is issuing separate requests for each image rather than assuming an undocumented parameter will work.
What happened to Imagen 4 Ultra specifically?
Google’s migration mapping routes former Imagen 4 Ultra workloads to gemini-3-pro-image (Nano Banana Pro) rather than to the Flash-tier Nano Banana 2, since Ultra was the higher-fidelity, higher-cost tier.
Do I need a different API key for Nano Banana 2 than I used for Imagen?
No. Both are accessed through the same Gemini API key and billing project. The change is in the endpoint, method name, and request structure, not the authentication layer.
How does Nano Banana 2 compare to GPT Image 2.5 or FLUX.2 on quality?
There is no independently verified, controlled benchmark covering all of these models with identical prompts and settings as of October 2026. Treat vendor-published rankings as directional at best, and run your own prompts through each candidate model before committing to one for a production feature. Our own Gemini 3.8 Flash API tutorial uses the same testing approach if you want a template for building that comparison yourself.
What is the single most common migration mistake developers report?
Leaving response_modalities unset or set to text-only, which produces a response that looks successful (no error is thrown) but contains no image at all. It is worth adding an explicit check for a missing inline_data part in your integration tests specifically to catch this.
Should I use gemini-3.1-flash-image or gemini-3.1-flash-image-preview?
Use the stable, non-preview model ID, gemini-3.1-flash-image, for anything in production. The preview ID exists for testing upcoming behavior changes and does not carry the same stability expectations.
Will I need to migrate again soon after finishing this?
Possibly, though not on any announced timeline as of October 2026. Google has already replaced one image-model generation this year, so isolating your model ID behind a single config constant, as described in the Advanced Tips section, is worth the small extra effort even if the current migration feels like enough work on its own.