Nano Banana 2 vs GPT Image: which one to use for image generation
Both lines share the same endpoint but work differently under the hood. How Nano Banana's reference-to-image differs from GPT Image's edit mode, and when each pays off.
4 min · · Updated · изображения
Update, October 2026. Image generation through Zukko is temporarily unavailable (Nano Banana 2 and GPT Image are currently switched off). Current model list: the Models page or
GET https://api.zukko.pro/v1/models. There's no close replacement among the current models: the catalog now has text models only (Claude, GPT, GLM).
The endpoint is the same for both — /v1/images/generations — the only thing that changes is the model name. That makes comparison tricky: to figure out which line fits your case, you have to look past the shared URL and check what each model actually does.
What each line offers
Nano Banana 2:
nano-banana-2-text-to-image(plus-developerand-lite-*variants) — text to imagenano-banana-2-edit-developer— editing an existing imagenano-banana-2-reference-to-image-developer— generation from a reference: a separate image sets style or composition, the prompt says what should be on it
GPT Image:
openai-gpt-image-2-text-to-image,openai-gpt-image-2-edit— current generationopenai-gpt-image-1.5-text-to-image,openai-gpt-image-1.5-edit— previous one, also used to be in the catalog
The difference that actually matters for picking one
Nano Banana has a third mode that GPT Image doesn't: reference-to-image. If you need "draw it in this style" or "keep the composition, swap the object," there's no dedicated model for that in the GPT Image line — only text-to-image and edit. Edit works well when you're fixing a specific picture by instruction ("make the background white," "remove the person on the left"), not when you're transferring style from one image to another.
If the task is style or composition transfer, test nano-banana-2-reference-to-image-developer first.
The request shape is identical
Both families accept a request with the same structure:
curl https://api.zukko.pro/v1/images/generations \
-H "Authorization: Bearer fetch_your_key" \
-H "Content-Type: application/json" \
-d '{
"model": "nano-banana-2-text-to-image",
"prompt": "Poster for a tech talk, minimalist, blue and white"
}'For GPT Image only model changes:
curl https://api.zukko.pro/v1/images/generations \
-H "Authorization: Bearer fetch_your_key" \
-H "Content-Type: application/json" \
-d '{
"model": "openai-gpt-image-2-text-to-image",
"prompt": "Poster for a tech talk, minimalist, blue and white"
}'Editing in both lines needs an images field with the source picture:
curl https://api.zukko.pro/v1/images/generations \
-H "Authorization: Bearer fetch_your_key" \
-H "Content-Type: application/json" \
-d '{
"model": "openai-gpt-image-2-edit",
"prompt": "Replace the background with solid light gray",
"images": ["https://example.com/source.png"]
}'Pricing and billing
Both lines charge per finished image, not per token in the prompt — a long detailed prompt costs the same as a short one. Exact prices per model change, so check them in the catalog rather than in an article:
curl https://api.zukko.pro/v1/models/infoThat call needs no key and returns current limits and prices. Every generation response also carries an X-Zukko-Cost-Micros header — the exact cost of that specific request in micro-dollars — so you can log real spend per model in your own pipeline instead of relying on approximate numbers.
What to do when the model isn't found
Names in both lines are long and easy to typo in one suffix — writing -dev instead of -developer, for instance. The response looks like this:
{"error": {"message": "The model 'openai-gpt-image-2-edit-dev' does not exist", "code": "model_not_found"}}The current model list without typos lives at /v1/models. If the model is in the catalog but switched off, the response is different: 503 with the model_disabled code (not a 404 and not model_retired) — in that case look for a replacement in the current GET https://api.zukko.pro/v1/models list.
Balance during batch generation
If you're generating images in batches — ten variants in a row for one layout, say — it's convenient to track the remaining balance without a separate call to /v1/balance. Every generation response carries an X-Fetch-Balance-Cents header — the balance left after charging for that image; despite the name it's in microdollars (1,000,000 = $1), and the exact balance in cents comes from GET /v1/balance (the balance_cents field). A script looping through generation only needs to check that header after each call and stop early, instead of hitting a 402 partway through a batch.
Retries without double charging
Network drops happen more often with image generation than with short text requests — generation itself takes longer, and a client timeout can fire before the response arrives. Keep in mind that the gateway's Idempotency-Key only works for POST /v1/chat/completions, /v1/messages and /v1/responses — it doesn't cover /v1/images/generations, so limit automatic generation retries on the client side and check your spend history before retrying, so you don't accidentally pay for the same image twice.
Keeping both lines in the project at once
Since both models go through the same endpoint and differ only in the model field, there's no reason to hard-wire your code to one line. A practical approach is to keep the model name in config or as a parameter to your own backend, and switch between Nano Banana and GPT Image without touching the rest of the pipeline — useful for comparing quality on a new batch of tasks, or reacting to 503 model_disabled if a specific version gets switched off.
Choosing in practice
Running both families on the same prompt and comparing results by eye is the fastest way to tell what fits your case. Test on the cheaper lite/developer variants, run the final pass on the full version, and decide which line you even need based on whether you need the reference mode — it only exists on the Nano Banana side.
zukko
Pay 25×
less
for Claude Code & ChatGPT
One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.
Related articles
- opencode agents: setting up roles, models and toolsA custom agent in opencode is a role, a model and a set of permissions. A working config where a cheap model handles routine work and a stronger one edits code.
- OpenAI API Keys in the Open: Why You Should Not Use ThemWhere free keys on GitHub come from, why using them is dangerous for you and for the owner, and how to protect your own key from the same leak.
- GLM API Errors: Why the Request Fails and How to Fix ItA wrong model id, an overflowing 128K context, the key, the balance, limits: the typical causes of GLM API errors and a quick way to find yours.
- Plan mode in Claude Code: plan first, then edit the codeIn plan mode Claude Code reads your code and proposes a plan but edits nothing until you agree. How to enable it, use it and what it costs.