Nano Banana Pro API:Python 调用、改图和价格
一次 POST、一次轮询、一次下载,脚本复制就能跑。

本页内容
Nano Banana Pro 就是 Google 的 gemini-3-pro-image。在 OmniaKey 上一次 POST /v1/media/tasks 就能调。我们跑了三张 3:4 的图,像素分别是 896x1200、1792x2400 和 3584x4800。海报上的字一个都没错。
先说结论
- 模型:
gemini-3-pro-image是 Google 的 GA 模型 ID。Vertex 模型卡写的发布日期是 2026 年 5 月 28 日。 - 调用: 向
POST https://api.omniakey.com/v1/media/tasks发请求,带上Idempotency-Key;轮询GET /v1/media/tasks/{id}到 succeeded,再下载assets[0].url。 - 参数:
parameters.aspect_ratio和parameters.image_size,尺寸值写 1K、2K、4K,K 要大写。 - 请求上限: 整个请求体 1 MiB,内联 Base64 图片也算在里面。
- Google 价格: 1K/2K 每张 $0.134,4K 每张 $0.24,数字来自 Google Gemini API 价格页。
- 我们的 token 数: 三次任务分别报了 1,133、1,225、2,480 个输出 token。按每百万图片 token $120 算,是 $0.136、$0.147、$0.298。
- 改图: 用
operation: "edit",源图放进input.image,格式是{data, mime_type}。
OmniaKey 的 Nano Banana Pro 模型页 也接受 gemini-3-pro-image-preview 这个旧快照 ID,价格一样。
模型 ID 和要准备的东西
代码里写 gemini-3-pro-image。Google 的 Vertex 模型卡 把它列为 GA,发布日期 2026 年 5 月 28 日,支持 1K、2K、4K 输出。
gemini-3-pro-image-preview 指向同一个模型。OmniaKey 的 图片模型表 把它标成“Same model, -preview snapshot id”,按次收费的价格一样。
准备两样东西:
- OmniaKey API key,放进环境变量:
export OMNIAKEY_API_KEY="your-key"。 - Python 3。下面的脚本只用标准库:urllib、json、time、uuid、base64 和 pathlib,不用装 SDK。
Python 脚本怎么跑
三步:创建任务、轮询状态、下载图片。保存为 nano_banana.py,运行 python3 nano_banana.py。
import base64
import json
import os
import time
import urllib.request
import uuid
from pathlib import Path
API = "https://api.omniakey.com/v1/media/tasks"
HEADERS = {
"Authorization": f"Bearer {os.environ['OMNIAKEY_API_KEY']}",
"Content-Type": "application/json",
}
def call(url, payload=None, headers=None, method=None):
body = json.dumps(payload).encode() if payload is not None else None
req = urllib.request.Request(url, data=body, headers=headers or HEADERS, method=method)
with urllib.request.urlopen(req, timeout=60) as resp:
return resp.status, json.loads(resp.read())
def create_task(prompt, aspect_ratio="3:4", image_size="2K", image_path=None):
body = {
"model": "gemini-3-pro-image",
"type": "image",
"operation": "generate" if image_path is None else "edit",
"input": {"prompt": prompt},
"parameters": {"aspect_ratio": aspect_ratio, "image_size": image_size},
}
if image_path:
encoded = base64.b64encode(Path(image_path).read_bytes()).decode("utf-8")
body["input"]["image"] = {"data": encoded, "mime_type": "image/png"}
headers = {**HEADERS, "Idempotency-Key": str(uuid.uuid4())}
status, task = call(API, body, headers, "POST")
print("created", task["id"], "HTTP", status)
return task
def wait(task_id, interval=3, timeout=300):
deadline = time.time() + timeout
while time.time() < deadline:
_, task = call(f"{API}/{task_id}")
print(task["status"], task["progress"]["percent"])
if task["status"] in ("succeeded", "failed", "canceled"):
return task
time.sleep(interval)
# A timeout is not a failure: keep the task id and poll it again.
raise TimeoutError(f"task {task_id} is still running")
def download(task, out_path):
asset = task["assets"][0]
with urllib.request.urlopen(asset["url"], timeout=120) as resp:
Path(out_path).write_bytes(resp.read())
print("saved", out_path, asset["mime_type"], asset["byte_size"], "bytes")
if __name__ == "__main__":
task = create_task(
"A vintage travel poster for the Night Train from Zürich to Milano, "
"departing 21:40 from platform 7. A steam train crosses a stone arch "
"bridge below snowy mountains under a deep blue night sky, with a cream "
"border. Spell every word exactly as written.",
aspect_ratio="3:4",
image_size="2K",
)
task = wait(task["id"])
if task["status"] != "succeeded":
raise SystemExit(f"{task['status']}: {task.get('error')}")
download(task, "night-train.jpg")
image_size 只认 1K、2K、4K。Google 的图片指南写得很明确:“K 必须大写……小写参数(例如 1k)会被拒绝。”写 2K,别写 2k。
Idempotency-Key 是必填项。最简单的做法是每次请求生成一个新的 UUID;只有重试同一个请求体时才复用同一个 key。OmniaKey 用 HTTP 200 返回原来的任务,不会重复扣费;同一个 key 换了请求体则返回 409。
创建任务返回 202 和一个 id。OmniaKey 的 媒体任务文档 写了完整流程。任务完成后,返回的字段就是下面这些:
{
"id": "task_AbMRVqzSnVh0VwBj0S7NuMUxy5sZtfHP",
"status": "succeeded",
"progress": {"percent": 100, "stage": "completed"},
"usage": {"total_tokens": 1133},
"assets": [
{
"kind": "image",
"mime_type": "…",
"url": "https://…signed-url…"
}
]
}
拿到 assets[0].url 就马上下载:签名链接大约一小时过期,任务记录保留 24 小时。格式看 mime_type 字段,Gemini 模型通常返回 JPEG。
同一个脚本换成 1:1、2K,提示词改成中文招牌,得到的是:

怎么改一张现有的图
用 operation: "edit",源图放进 input.image,格式是 {data, mime_type}。上面的脚本只要传 image_path 就会走这条路:
task = create_task(
"Hang this poster in a thin black frame on a warm white wall, with a brass "
"picture light above it, a low wooden cabinet below and a trailing plant on "
"the right. Keep the poster exactly as it is.",
aspect_ratio="1:1",
image_size="2K",
image_path="night-train-2k.png",
)
实际发出去的请求体是这样:
{
"model": "gemini-3-pro-image",
"type": "image",
"operation": "edit",
"input": {
"prompt": "Hang this poster in a thin black frame on a warm white wall…",
"image": {"data": "…base64…", "mime_type": "image/png"}
},
"parameters": {"aspect_ratio": "1:1", "image_size": "2K"}
}
示例源图是 PNG,所以脚本标的是 image/png;换成 JPEG 就改这个值。要放多张参考图,用 input.images,每个元素的格式同样是 {data, mime_type}。Google 的指南写最多 14 张参考图;gemini-3-pro-image 的分配是 6 张物体、5 张人物、3 张风格参考。
请求体要压在 1 MiB 以内。Base64 会让文件大约大三分之一,编码前先把源图缩小或压缩。我们这次改图用的是 2K 海报,海报上的每个字和版式都保住了:

1K、2K、4K 分别买到什么
同一段 3:4 海报提示词,三个尺寸各跑一次。像素和 Google 的 3:4 表完全对得上:1K 是 896x1200,2K 是 1792x2400,4K 是 3584x4800。三档的字都写对了。



尺寸变大,多出来的是细节:
- 1K: 车头挤在一起,车灯、车轮和连杆靠得很近。
- 2K: 右侧山坡出现小村庄和两座尖塔,烟囱冒出一缕浅色烟,石桥能看到 7 个拱洞。
- 4K: 三节车厢和煤水车分得开,砖缝粗细不一。车底机械仍然简化。
耗时也跟着涨:28.4 秒、48.2 秒和 66.9 秒。每个尺寸只跑了一次,这三个数就是单次结果。
Google 按每百万图片 token $120 计费,表里 1K 和 2K 都是 1,120 token,4K 是 2,000 token。按它的数算,就是 Google 自己的估算:
1,120 × $120 ÷ 1,000,000 = $0.134 per 1K image
1,120 × $120 ÷ 1,000,000 = $0.134 per 2K image
2,000 × $120 ÷ 1,000,000 = $0.24 per 4K image
我们的任务报的 token 比 Google 举的例子多。同样的算法用我们的数:
1,133 × $120 ÷ 1,000,000 = $0.136 per 1K image
1,225 × $120 ÷ 1,000,000 = $0.147 per 2K image
2,480 × $120 ÷ 1,000,000 = $0.298 per 4K image
| 尺寸 | 像素(3:4) | 我们的耗时 | 我们的 token | Google 估算 |
|---|---|---|---|---|
| 1K | 896x1200 | 28.4 秒 | 1,133 | $0.134 |
| 2K | 1792x2400 | 48.2 秒 | 1,225 | $0.134 |
| 4K | 3584x4800 | 66.9 秒 | 2,480 | $0.24 |
OmniaKey 按次收费,不看 token 数,所以扣费不随上面的 token 变;当前每次的价格在 模型页,任务失败会退回。充值支持支付宝和微信支付,按人民币直充,一个 key 可以调多家模型。Google 对同样三张图的 token 费率估算是 $0.134、$0.134 和 $0.24。
会碰到哪些报错
这里的失败大多是字段名或文件大小的问题,跟模型本身关系不大。OmniaKey 的媒体文档列了下面这几种:
| HTTP | 错误码或状态 | 什么意思 | 怎么办 |
|---|---|---|---|
| 400 | invalid_request | 请求体格式错、操作不支持或参数不对 | 检查 JSON 和下面的字段名 |
| 503 | no_available_channel | 当前没有渠道服务这个模型 | 换一个模型;重复调用解决不了 |
| — | failed | 任务结束但没有结果 | 看 error.code 和 error.message |
任务 failed 不是 HTTP 错误:创建请求已经成功,所以要轮询任务并读它的 error 对象。失败和取消的任务会自动退款。
原图直接转成 Base64 很容易把请求体推过 1 MiB。先缩图,再看编码后的长度,不要只看文件大小。
Google 的指南会拒绝小写 1k。写 1K、2K 或 4K。
OmniaKey 的图片文档也会拒绝 Gemini 模型上的 size 和顶层的 mime_type。这两个不是 Gemini 的参数。改用 parameters.aspect_ratio 和 parameters.image_size。输出格式从响应的 mime_type 字段读。
常见问题
Nano Banana Pro 的 API 模型 ID 是什么?
gemini-3-pro-image。Google 的 Vertex 模型卡标为 GA,发布日期 2026 年 5 月 28 日,OmniaKey 用同一个 ID。旧的 gemini-3-pro-image-preview 还能用,指向同一个模型。
一张 Nano Banana Pro 图片多少钱?
Google 的估算是 1K/2K 每张 $0.134,4K 每张 $0.24,按每百万图片 token $120 算。我们的任务报了 1,133、1,225、2,480 个 token,按同样费率是 $0.136、$0.147、$0.298。OmniaKey 模型页按次标价。
Nano Banana Pro 能写中文吗?
能。我们那张 2K 招牌回来了三行正确的中文——同福客栈、住宿 餐饮 茶水、010-6789 4321——11 个数字和连字符都对。
1K、2K、4K 选哪个?
像我们这张海报,2K 是比较合适的中间档。三个尺寸都把海报字写对了,4K 多的是细节,比如分开的车厢和砖缝,文字正确率不会更高。只要 896x1200 够用,1K 更省时间。
改图报 400 invalid_request 怎么办?
先看三件事:请求体有没有超过 1 MiB、源图有没有放进 input.image、有没有给 Gemini 模型传 size 或顶层的 mime_type。源图写成 {data, mime_type}。编码后控制在 1 MiB 以内,参数只用 aspect_ratio 和 image_size。
来源
- Google Cloud:Gemini 3 Pro Image 模型卡 — 2026 年 11 月 3 日核对。
- Google:Gemini API 图片生成指南 — 2026 年 11 月 3 日核对。
- Google:Gemini API 价格 — 2026 年 11 月 3 日核对。
- Google:Nano Banana Pro 发布公告 — 2026 年 11 月 3 日核对。
更新记录
- 2026-11-03:第一版,当天通过 OmniaKey 跑了 5 次测试。
