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 가격 페이지의 값입니다.
- 실제 토큰 수: 세 작업은 출력 토큰을 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"로 적혀 있고 호출당 요금도 같습니다.
준비할 것은 두 가지입니다.
- OmniaKey API 키를 환경 변수에 넣습니다:
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를 만드는 것이 가장 간단합니다. 키를 다시 쓰는 경우는 똑같은 본문을 재시도할 때뿐입니다. 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을 읽었으면 바로 내려받으십시오. 서명 링크는 한 시간쯤이면 만료되고 작업 기록은 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: 오른쪽 비탈에 마을과 첨탑 두 개가 나타나고, 굴뚝에서는 옅은 연기가 올라가며, 돌다리에 아치가 일곱 개 보입니다.
- 4K: 객차 세 량과 석탄차가 따로 그려지고 석조의 줄눈 두께도 달라집니다. 기관차 아래 기계는 여전히 단순합니다.
속도는 크기를 따라 늘었습니다. 28.4초, 48.2초, 66.9초입니다. 크기마다 한 번씩만 돌렸으므로 이 초는 한 번의 결과로 읽으십시오.
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는 이미지 호출을 정액으로 청구하고 토큰으로 계산하지 않으므로 위 토큰 수에 따라 요금이 달라지지 않습니다. 현재 호출당 요금은 모델 페이지에 있고 실패한 작업은 환불됩니다. 같은 세 장을 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 이미지 한 장은 얼마인가요?
Google 추정치는 1K/2K가 $0.134, 4K가 $0.24입니다. 이미지 토큰 100만 개당 $120으로 계산한 값입니다. 우리 작업은 1,133, 1,225, 2,480 토큰이었고 같은 단가로는 $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를 넘었는지, 원본이 맞는 필드에 들어갔는지, 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로 테스트 다섯 번 실행.
이 글에서 다루는 모델
관련 글
Nano Banana 2.1: API 접근, 가격과 마이그레이션
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개를 두 모델로 실행하고 시간을 재서 2K 이미지 한 장의 가격을 냈습니다.
