Nano Banana Pro API:Python で呼ぶ手順と画像編集、料金
POST を 1 回、ポーリングを 1 回、ダウンロードを 1 回。そのまま動くスクリプトです。

このページの内容
Nano Banana Pro は Google の gemini-3-pro-image です。OmniaKey なら POST /v1/media/tasks を 1 回投げるだけで呼べます。3:4 で 3 枚試したところ、返ってきたのは 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 が 1 枚 $0.134、4K が 1 枚 $0.24 です。Google の Gemini API 料金ページの数字です。
- 実際のトークン数: 3 つのタスクは 1,133、1,225、2,480 の出力トークンを報告しました。画像トークン 100 万あたり $120 で計算すると、$0.136、$0.147、$0.298 になります。
- 編集:
operation: "edit"を指定し、元画像をinput.imageに{data, mime_type}の形で入れます。
OmniaKey の Nano Banana Pro モデルページ では、旧スナップショット ID の gemini-3-pro-image-preview も同じ料金で使えます。
モデル ID と用意するもの
コードに書くのは gemini-3-pro-image です。Google の Vertex モデルカード では GA として掲載され、公開日は 2026 年 5 月 28 日、1K・2K・4K の出力に対応します。
gemini-3-pro-image-preview は同じモデルを指す ID です。OmniaKey の 画像モデルの表 でも "Same model, -preview snapshot id" と書かれ、1 回あたりの料金も同じです。
用意するものは 2 つです。
- OmniaKey の API キー。環境変数に入れておきます:
export OMNIAKEY_API_KEY="your-key"。 - Python 3。下のスクリプトは標準ライブラリだけで動きます。urllib、json、time、uuid、base64、pathlib を使い、SDK のインストールは不要です。
Python スクリプトの動かし方
手順は 3 つです。タスクを作り、状態をポーリングし、画像をダウンロードします。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 を振るのがいちばん簡単です。同じキーを使い回すのは、まったく同じボディを再送するときだけにしてください。OmniaKey は元のタスクを HTTP 200 で返すので二重課金になりません。同じキーでボディが違う場合は 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 を読んだら、その場でダウンロードします。署名付きリンクの有効期限は 1 時間ほどで、タスクの記録は 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 にするとファイルは 3 割ほど大きくなるので、エンコードの前に元画像を縮小するか圧縮してください。今回の編集では 2K のポスターを使い、文字もレイアウトもそのまま残りました。

1K・2K・4K で何が変わるか
同じ 3:4 のポスターのプロンプトを、3 つのサイズで 1 回ずつ実行しました。画素数は Google の 3:4 の表とぴったり一致しました。1K が 896x1200、2K が 1792x2400、4K が 3584x4800 です。ポスターの文字はどのサイズでも正しく出ました。



サイズで変わるのは細部で、文字の正確さは同じです。
- 1K: 機関車の正面が込み合います。ランプ、車輪、連接棒が近寄って並びます。
- 2K: 右の斜面に村と 2 本の尖塔が出て、煙突から淡い煙が上がり、石橋にはアーチが 7 つ見えます。
- 4K: 客車 3 両と炭水車が分かれて描かれ、石積みの目地にも太さの差が出ます。機関車の下の機械は単純なままです。
時間もサイズに比例して伸びました。28.4 秒、48.2 秒、66.9 秒です。各サイズ 1 回だけの実行なので、この秒数は 1 回分の結果として読んでください。
Google は画像出力を 100 万トークンあたり $120 で計算し、表では 1K と 2K が 1,120 トークン、4K が 2,000 トークンです。これが 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
こちらのタスクは 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) | 実測の時間 | 実測トークン | 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 は画像 1 回につき定額で、トークンでは課金しません。だから上のトークン数が増えても請求額は変わりません。現在の 1 回あたりの料金は モデルページ にあり、失敗したタスクは返金されます。同じ 3 枚を Google のトークン単価で見積もると $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 を受け付けます。旧 ID の gemini-3-pro-image-preview も OmniaKey では使えて、同じモデルを指します。
Nano Banana Pro の画像 1 枚はいくら?
Google の見積もりは 1K/2K が $0.134、4K が $0.24 です。画像トークン 100 万あたり $120 で計算しています。こちらのタスクは 1,133、1,225、2,480 トークンだったので、同じ単価なら $0.136、$0.147、$0.298 です。OmniaKey はモデルページに 1 回あたりの料金を出しています。
Nano Banana Pro は中国語の文字も描けますか?
描けます。2K の看板は中国語 3 行が正しく返ってきました。同福客栈、住宿 餐饮 茶水、010-6789 4321 で、11 桁の数字とハイフンも合っています。
1K・2K・4K のどれを選べばいい?
今回のようなポスターなら、2K が使いやすい真ん中です。3 サイズとも文字は正しく出たので、4K で増えるのは細部(客車が分かれる、れんがの目地が見える)で、文字の正確さではありません。896x1200 で足りる下書きなら 1K が速いです。
編集で 400 invalid_request が返るときは?
ボディが 1 MiB を超えていないか、元画像が正しいフィールドに入っているか、Gemini モデルに size やトップレベルの mime_type を送っていないかを確認します。画像は input.image に {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 回のテスト実行。
この記事で紹介しているモデル
関連記事
Nano Banana 2.1:API料金とOmniaKeyでの利用
Nano Banana 2.1とNano Banana 2を比較し、対応するNano Banana画像タスクをOmniaKeyで直接作成します。
Nano Banana 商品画像の作り方:8つのプロンプト検証
8つのプロンプト、22回の編集、2つのモデル。ラベルの文字が残ったのはどの画像か、靴がどこで鏡像になったか、作業ごとにどちらを選ぶかをまとめます。
Seedream 5.0 Pro vs Nano Banana Pro:同じプロンプトで比べた結果と料金
5つの共通プロンプトを2つのモデルで試し、時間を実測して、2K画像1枚の料金を出しました。
