Nano Banana Pro API: быстрый старт и первая картинка
Пошаговый быстрый старт Nano Banana Pro API: ключ, запрос, статус и результат на curl, Python и JavaScript. Одна сцена в трёх разрешениях.
Редакция RendergridО редакции
Коротко
Нужны ключ API и баланс. Отправьте один запрос POST /images/generate с моделью nano-banana-pro и сохраните id из ответа. Спрашивайте статус через GET /creations/{id} не чаще раза в 5 секунд, а когда он станет completed, сохраните файл по ссылке из result_urls: файлы хранятся сутки. Картинка стоит $0,04 в 1K, $0,04 в 2K и $0,07 в 4K. Неудачный запрос бесплатен: сумма сразу возвращается на баланс.
Что нужно до первого запроса?
Первые шаги такие: создать ключ API, пополнить баланс и отправить запрос. Подойдёт любой язык, который умеет отправлять HTTPS-запросы. В примерах — curl, Python с пакетом requests и Node.js 22+.
Ключ создаётся в личном кабинете. Он состоит из префикса rg_live_ и ещё 40 знаков и показывается целиком один раз, при создании: потерянный ключ восстановить нельзя, можно только создать новый. Положите его в переменную окружения RENDERGRID_API_KEY на сервере, чтобы он не попал в код и в репозиторий. Подробности — в документации о ключах.
Ключ — это пароль от вашего баланса. Не вставляйте его в код сайта или мобильного приложения: запросы к API отправляйте только с сервера.
Баланс пополняется в USDT в кабинете, а у оплаты есть своё окно: оно описано в документации по пополнению. Цена каждой картинки списывается при приёме запроса, поэтому, если на балансе меньше цены, API ответит 402. Начните с небольшой суммы: платить придётся только за картинки, которые получились.
Какие модели доступны вашему аккаунту и по каким ценам, покажет GET /models. Параметры всех моделей — в разделе «Модели и параметры».
Как отправить запрос?
Обязательных полей два: model и prompt. Мы добавляем ещё resolution и aspect_ratio, чтобы разрешение и формат кадра не зависели от значений по умолчанию. Заголовок X-Idempotency-Key защищает от двойного списания: для каждой новой картинки берите новый ключ, а при повторе того же запроса — прежний (о повторах без двойного списания).
Промпт в примерах — сцена, из которой сделаны три картинки ниже: флакон духов на тёмной бумаге.
# Нужны bash, curl и uuidgen. Ключ повтора — один на запрос. IDEMPOTENCY_KEY="$(uuidgen)" || exit 1 curl --fail-with-body --max-time 30 \ -X POST https://api.rendergrid.io/ api/ public/ v1/ images/ generate \ -H "Authorization: Bearer $RENDERGRID_API_KEY" \ -H "Content-Type: application/json" \ -H "X-Idempotency-Key: $IDEMPOTENCY_KEY" \ -d '{ "model": "nano-banana-pro", "prompt": "Янтарный прямоугольный флакон духов стоит на сложенной тёмно-серой бумаге, рядом отдельно лежит округлая крышка. Флакон открыт, горлышко чётко видно. Свет справа сверху создаёт тонкий золотистый блик и тень в бумажном сгибе. Оба предмета целиком, квадратная композиция с широкими полями. Без надписей, логотипов, людей и водяных знаков.", "resolution": "1K", "aspect_ratio": "1:1" }'
import os import uuid import requests API = "https://api.rendergrid.io/ api/ public/ v1" KEY = os.environ["RENDERGRID_API_KEY"] PROMPT = "Янтарный прямоугольный флакон духов стоит на сложенной тёмно-серой бумаге, рядом отдельно лежит округлая крышка. Флакон открыт, горлышко чётко видно. Свет справа сверху создаёт тонкий золотистый блик и тень в бумажном сгибе. Оба предмета целиком, квадратная композиция с широкими полями. Без надписей, логотипов, людей и водяных знаков." response = requests.post( f"{API}/images/generate", headers={ "Authorization": f"Bearer {KEY}", # новый на каждую картинку; при повторе того же запроса — прежний "X-Idempotency-Key": str(uuid.uuid4()), }, json={ "model": "nano-banana-pro", "prompt": PROMPT, "resolution": "1K", "aspect_ratio": "1:1", }, timeout=(10, 120), ) response.raise_for_status() creation = response.json() # 202: {id, status, task_id, cost} print(creation["id"], creation["status"], creation["cost"])
// Node.js 22+, файл .mjs import { randomUUID } from "node:crypto"; const API = "https://api.rendergrid.io/ api/ public/ v1"; const prompt = "Янтарный прямоугольный флакон духов стоит на сложенной тёмно-серой бумаге, рядом отдельно лежит округлая крышка. Флакон открыт, горлышко чётко видно. Свет справа сверху создаёт тонкий золотистый блик и тень в бумажном сгибе. Оба предмета целиком, квадратная композиция с широкими полями. Без надписей, логотипов, людей и водяных знаков."; const response = await fetch(`${API}/images/generate`, { method: "POST", headers: { Authorization: `Bearer ${process.env.RENDERGRID_API_KEY}`, "Content-Type": "application/json", // новый на каждую картинку; при повторе того же запроса — прежний "X-Idempotency-Key": randomUUID(), }, body: JSON.stringify({ model: "nano-banana-pro", prompt, resolution: "1K", aspect_ratio: "1:1", }), signal: AbortSignal.timeout(120_000), }); if (response.status !== 202) { throw new Error(`HTTP ${response.status}: ${await response.text()}`); } // ответ 202: {id, status, task_id, cost} const creation = await response.json(); console.log(creation.id, creation.status, creation.cost);
В ответ придёт 202 Accepted: запрос принят, но картинка ещё не готова. В теле ответа четыре поля: id и task_id — идентификаторы задания (в запрос статуса подставляйте id), status со значением queued и cost — сумма в долларах, которую мы списали за картинку. Сохраните id: по нему вы узнаете результат.
Как узнать статус и забрать результат?
Картинка рисуется в фоне, поэтому после 202 нужно спросить статус: GET /creations/{id} с тем же заголовком Authorization. Подставьте id из ответа на запрос. Задание видно только аккаунту, который его создал: чужой или неизвестный id даст 404.
Статусов четыре:
queued— запрос принят и ждёт своей очереди;processing— картинка рисуется;completed— готово, ссылки на файлы лежат вresult_urls;failed— получить картинку не удалось, причина в поляхerrorиfailure.
completed и failed конечные: опрос можно прекращать. Ответ 200 может нести status: "failed" — это итог задания, а не ошибка самого запроса статуса.
Как часто спрашивать статус
Одно задание одним ключом — не чаще раза в 5 секунд: более частый опрос получит 429. Ограничьте общее время ожидания в коде. Если оно вышло, сохраните id и продолжите позже: тайм-аут вашего клиента задание не отменяет. Заранее обещанного срока нет: он зависит от модели и нагрузки.
Цикл ниже ждёт, пока статус не станет конечным, и сохраняет первый файл. Предел ожидания в нём — настройка примера, а не срок работы модели. Более полный цикл с повторами при обрыве связи, 429 и 5xx — в разделе «Задачи и статусы».
CREATION_ID="5b0214ae-9e39-460a-820a-f6ae3e24400b" # id из ответа на запрос curl --fail-with-body --max-time 20 \ "https://api.rendergrid.io/ api/ public/ v1/ creations/ $CREATION_ID" \ -H "Authorization: Bearer $RENDERGRID_API_KEY" # Повторяйте не чаще раза в 5 секунд, пока status не станет completed или failed. # Затем сохраните файл по первой ссылке из result_urls: RESULT_URL="https:// …" curl --fail-with-body --max-time 60 -L -o result-1k "$RESULT_URL"
import os import time import requests API = "https://api.rendergrid.io/ api/ public/ v1" KEY = os.environ["RENDERGRID_API_KEY"] HEADERS = {"Authorization": f"Bearer {KEY}"} creation_id = "5b0214ae-9e39-460a-820a-f6ae3e24400b" # id из ответа на запрос # предел ожидания — настройка примера, а не срок работы модели deadline = time.monotonic() + 180 while True: if time.monotonic() >= deadline: raise SystemExit(f"Ещё не готово, сохраните id: {creation_id}") time.sleep(5) # чаще раза в 5 секунд спрашивать нельзя r = requests.get(f"{API}/creations/{creation_id}", headers=HEADERS, timeout=(5, 20)) r.raise_for_status() creation = r.json() if creation["status"] in ("completed", "failed"): break if creation["status"] == "failed": raise SystemExit(f"{creation['error']} {creation['failure']}") image = requests.get(creation["result_urls"][0], timeout=(10, 60)) image.raise_for_status() print(image.headers.get("Content-Type")) # по нему определите расширение файла with open("result-1k", "wb") as file: file.write(image.content)
// Node.js 22+, файл .mjs import { writeFile } from "node:fs/promises"; const API = "https://api.rendergrid.io/ api/ public/ v1"; const headers = { Authorization: `Bearer ${process.env.RENDERGRID_API_KEY}` }; const creationId = "5b0214ae-9e39-460a-820a-f6ae3e24400b"; // id из ответа на запрос // предел ожидания — настройка примера, а не срок работы модели const deadline = Date.now() + 180_000; let creation; do { if (Date.now() >= deadline) { throw new Error(`Ещё не готово, сохраните id: ${creationId}`); } // чаще раза в 5 секунд спрашивать нельзя await new Promise((resolve) => setTimeout(resolve, 5000)); const res = await fetch(`${API}/creations/${creationId}`, { headers, signal: AbortSignal.timeout(20_000), }); if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`); creation = await res.json(); } while (["queued", "processing"].includes(creation.status)); if (creation.status === "failed") { throw new Error(`${creation.error} ${JSON.stringify(creation.failure)}`); } const image = await fetch(creation.result_urls[0], { signal: AbortSignal.timeout(60_000) }); if (!image.ok) throw new Error(`HTTP ${image.status}`); console.log(image.headers.get("content-type")); // по нему определите расширение файла await writeFile("result-1k", Buffer.from(await image.arrayBuffer()));
Весь обмен состоит из двух ответов: ответа на запрос и итогового ответа о статусе.
{
"id": "5b0214ae-9e39-460a-820a-f6ae3e24400b",
"status": "queued",
"task_id": "5b0214ae-9e39-460a-820a-f6ae3e24400b",
"cost": 0.04
}
{
"id": "5b0214ae-9e39-460a-820a-f6ae3e24400b",
"status": "completed",
"result_urls": [
"https:// …"
]
}
Как сохранить результат
result_urls — готовые ссылки на файлы. Берите их как есть: не собирайте из id. Формат файла задаёт поле output_format: png или jpg; без него файл приходит в исходном формате модели. Файлы хранятся сутки, а опрос срок не продлевает, поэтому сохраняйте картинку у себя сразу, как получили ссылку.
Вместо опроса можно передать в запросе webhook_url — публичный адрес HTTPS: мы сообщим, когда задание станет completed или failed. Опрос оставьте запасным путём, потому что уведомление может задержаться или не дойти. Подробности — в разделе «Вебхуки».
Как получить ту же сцену в 1K, 2K и 4K?
Разрешение задаёт поле resolution: 1K, 2K или 4K, регистр не важен. Мы отправили один и тот же промпт трижды через публичный API Rendergrid и поменяли только resolution: по одной попытке на каждое разрешение, формат кадра 1:1. Вот что вышло.
Промпт — один для всех разрешений
Янтарный прямоугольный флакон духов стоит на сложенной тёмно-серой бумаге, рядом отдельно лежит округлая крышка. Флакон открыт, горлышко чётко видно. Свет справа сверху создаёт тонкий золотистый блик и тень в бумажном сгибе. Оба предмета целиком, квадратная композиция с широкими полями. Без надписей, логотипов, людей и водяных знаков.
Nano Banana Pro
nano-banana-pro · 1K · 1:1 · $0,04
Nano Banana Pro, 1K, 1:1, одна попытка. Флакон стоит, как в промпте: горлышко с резьбой открыто, крышка лежит отдельно справа, золотистый свет падает из верхнего правого угла, а в сгибе бумаги слева густая тень. Оба предмета целиком. Левая грань флакона слегка волнистая. Читаемых надписей на кадре нет.
Nano Banana Pro
nano-banana-pro · 2K · 1:1 · $0,04
Nano Banana Pro, 2K, 1:1, одна попытка. Сцена отличается от 1K: флакон не стоит, как просит промпт, а лежит на боку горлышком к крышке, которая стоит рядом. Бумага — несколько тёмных диагональных полос, а не один сгиб, по ним идёт золотистая полоса света. Кадр ближе, поля узкие, оба предмета целиком, резьба горлышка и грани стекла видны чётко. Читаемых надписей на кадре нет.
Nano Banana Pro
nano-banana-pro · 4K · 1:1 · $0,07
Nano Banana Pro, 4K, 1:1, одна попытка. Флакон стоит, горлышко открыто, крышка лежит справа на бумаге с диагональным сгибом, по бумаге идут золотистые блики. Вокруг снимка кремовая рамка, которой в промпте нет: там просили широкие поля. Стекло темнее и плотнее, чем на 1K. Читаемых надписей на кадре нет, но у основания флакона на стекле угадываются мелкие неразборчивые отметки.
Это три отдельных запроса, поэтому сцена получилась не одной и той же в трёх размерах, а тремя разными кадрами. На 1K флакон стоит, как в промпте. На 2K он лежит на боку, а бумага разложена полосами вместо одного сгиба. На 4K флакон снова стоит, но весь снимок окружён кремовой рамкой. Не ждите, что 2K и 4K повторят композицию 1K, только крупнее: если вам нужен определённый кадр, проверьте результат в том разрешении, в котором будете им пользоваться.
У этих файлов размер вышел 1 024 × 1 024 пикселей в 1K, 2 048 × 2 048 в 2K и 4 096 × 4 096 в 4K. Но resolution — это уровень размера, а не точное число пикселей: поля width и height не принимаются, а точный размер вы узнаете по полученному файлу.
Если resolution не указать, картинка нарисуется и будет оплачена в 2K: это разрешение по умолчанию у Nano Banana Pro.
aspect_ratio задаёт формат кадра. У Nano Banana Pro это 1:1, 16:9, 9:16, 4:3, 3:4, 2:3, 3:2, 5:4, 4:5, 21:9 и auto. Форматов 1:4, 1:8, 4:1 и 8:1 у этой модели нет: они есть у Nano Banana 2 и Nano Banana 2.1. Про Nano Banana 2.1 есть отдельный быстрый старт. Если поля нет, будет 1:1, а не auto. Значение, которого у модели нет, получит 400 до списания.
Сколько стоит картинка и когда списываются деньги?
Цена зависит от разрешения: $0,04 в 1K, $0,04 в 2K и $0,07 в 4K. Точные цены вашего аккаунта возвращает GET /models.
Сумма списывается при приёме запроса, до начала работы, и приходит в поле cost ответа 202. Если картинка не получилась, списание возвращается само: неудачный запрос бесплатен. Баланс можно проверить запросом GET /balance, но чтение ничего не резервирует, поэтому 402 обрабатывайте всегда, даже если проверка прошла.
Как цена складывается у Google и у Rendergrid — в статье «Nano Banana Pro API: цена за картинку у Google и в Rendergrid». Цены всех моделей — на странице цен.
Что ответит API, если что-то пошло не так?
- 401,
ERR_API_KEY_INVALID. Ключ не передан, неверный, отозван или просрочен. Проверьте, что заголовокAuthorizationдоходит до API, или создайте новый ключ. - 402,
ERR_INSUFFICIENT_BALANCE. На балансе меньше цены картинки либо исчерпан месячный лимит ключа или аккаунта, если он задан. Пополните баланс или поднимите лимит. - 400,
ERR_INVALID_REQUEST. Нетpromptили у модели нет такогоresolutionлибоaspect_ratio. Деньги не списаны: вerror.detailsсказано, что исправить, а вdetails.supportedпридёт список допустимых значений. - 404,
ERR_NOT_FOUND. Такогоidнет, или он принадлежит другому аккаунту. Проверьтеidи убедитесь, что ключ из того же аккаунта. - 429,
ERR_RATE_LIMIT. Статус спросили слишком рано или превышены лимиты аккаунта. Ждите не меньшеdetails.min_interval_secondsи не меньше, чем указано в заголовкеRetry-After. Лимиты описаны в разделе «Лимиты». - 200 со
status: "failed". Задание не удалось. Читайтеfailure.type,failure.codeиfailure.retryable. Сумма за такое задание вернулась на баланс сама.
Причину отказа читайте по error.code и error.details.reason, а не по тексту сообщения. Все коды — в справочнике ошибок.
Где этот гайд не подходит?
- Три картинки — не бенчмарк. Одна попытка на каждое разрешение: по ним нельзя судить, как Nano Banana Pro рисует в среднем.
- Только текст в картинку. Образцы и правку по ним мы здесь не разбираем, они описаны в разделе «Картинки-образцы».
- Одна картинка на запрос. Нужно больше — отправляйте несколько запросов с разными ключами повтора, в пределах лимитов аккаунта.
- Нет замеров времени. Сколько ждать результат, зависит от модели и нагрузки, а три картинки этого не показывают.
Неудачный запрос бесплатен
Повторите запрос со своим промптом
Тот же запрос можно собрать без кода на странице модели: промпт, пропорции и разрешение — в песочнице.
Попробовать модельВопросы и ответы
Как получить первую картинку Nano Banana Pro через API?
POST /images/generate с полем model со значением nano-banana-pro и промптом. Из ответа 202 возьмите id, спрашивайте GET /creations/{id} не чаще раза в 5 секунд, пока статус не станет completed, и сохраните файл по ссылке из result_urls.Какое разрешение, если не указать resolution?
Сколько ждать результат?
id и продолжите позже.Платят ли за неудачный запрос?
Сколько хранится готовая картинка?
result_urls.Можно ли обойтись без опроса?
webhook_url с публичным адресом HTTPS: мы сообщим, когда задание станет completed или failed. Опрос оставьте запасным путём.Источники
- Документация Rendergrid: быстрый стартКлюч, запрос, статус и результат в curl, Python и Node.js.
- Документация Rendergrid: создание картинкиПоля запроса, ответ
202и проверки до списания. - Документация Rendergrid: задачи и статусыСтатусы, частота опроса и срок хранения файлов.
- Документация Rendergrid: модели и параметрыРазрешения, форматы кадра и значения по умолчанию.
- Цены RendergridЦена за картинку для каждой модели и разрешения.
- Три картинки этой статьиПромпт и параметры — в блоке с картинками: по одной попытке на каждое разрешение через API Rendergrid.




