> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runbridge.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Use Nano Banana image models

> Call Gemini image models (Nano Banana 2 / Pro) on RunBridge AI using the Google Gen AI SDK for text-to-image, image-to-image, and multi-image composition.

Use Nano Banana 2 and Nano Banana Pro through RunBridge AI with the **Google Gen AI SDK** and the Gemini `generateContent` API. This guide covers:

* Text-to-image generation
* Image-to-image editing
* Multi-image composition
* Saving generated images

The examples use `gemini-3.1-flash-image` for Nano Banana 2. The [API reference](/api/image/gemini/gemini-generates-image) also includes separate Nano Banana Pro and Lite examples.

<Info>
  * **Base URL:** `https://api.runbridge.ai`
  * Install the SDK: `pip install google-genai` (Python) or `npm install @google/genai` (Node.js)
</Info>

***

## Setup

Initialize the client with RunBridge AI's base URL:

<CodeGroup>
  ```python Python theme={null}
  from google import genai
  from google.genai import types
  import os

  RUNBRIDGE_API_KEY = os.environ["RUNBRIDGE_API_KEY"]

  client = genai.Client(
      http_options={"api_version": "v1beta", "base_url": "https://api.runbridge.ai"},
      api_key=RUNBRIDGE_API_KEY,
  )
  ```

  ```javascript Node.js theme={null}
  import { GoogleGenAI } from "@google/genai";

  const RUNBRIDGE_API_KEY = process.env.RUNBRIDGE_API_KEY;

  const ai = new GoogleGenAI({
    apiKey: RUNBRIDGE_API_KEY,
    httpOptions: { apiVersion: "v1beta", baseUrl: "https://api.runbridge.ai" },
  });
  ```

  ```go Go theme={null}
  package main

  import (
  	"context"
  	"os"
  	"google.golang.org/genai"
  )

  func main() {
  	ctx := context.Background()
  	apiKey := os.Getenv("RUNBRIDGE_API_KEY")

  	client, _ := genai.NewClient(ctx, &genai.ClientConfig{
  		APIKey:  apiKey,
  		Backend: genai.BackendGeminiAPI,
  		HTTPOptions: genai.HTTPOptions{
  			BaseURL: "https://api.runbridge.ai",
  		},
  	})
  	// use client below...
  }
  ```
</CodeGroup>

***

## Text-to-image generation

Generate an image from a text prompt and save it to a file.

<CodeGroup>
  ```python Python theme={null}
  from pathlib import Path
  from google import genai
  from google.genai import types
  import os

  client = genai.Client(
      http_options={"api_version": "v1beta", "base_url": "https://api.runbridge.ai"},
      api_key=os.environ["RUNBRIDGE_API_KEY"],
  )

  response = client.models.generate_content(
      model="gemini-3.1-flash-image",
      contents="Create a picture of a nano banana dish in a fancy restaurant with a Gemini theme",
      config=types.GenerateContentConfig(
          response_modalities=["TEXT", "IMAGE"],
      ),
  )

  final_image = None
  for part in response.parts:
      if getattr(part, "thought", False):
          continue
      if part.text is not None:
          print(part.text)
      elif part.inline_data is not None:
          final_image = part.inline_data

  if final_image:
      extension = {
          "image/jpeg": "jpg",
          "image/png": "png",
          "image/webp": "webp",
      }.get(final_image.mime_type)
      if not extension:
          raise ValueError(f"Unsupported image MIME type: {final_image.mime_type}")
      filename = f"generated_image.{extension}"
      Path(filename).write_bytes(final_image.data)
      print(f"Image saved to {filename}")
  ```

  ```javascript Node.js theme={null}
  import { GoogleGenAI } from "@google/genai";
  import * as fs from "fs";

  const ai = new GoogleGenAI({
    apiKey: process.env.RUNBRIDGE_API_KEY,
    httpOptions: { apiVersion: "v1beta", baseUrl: "https://api.runbridge.ai" },
  });

  const response = await ai.models.generateContent({
    model: "gemini-3.1-flash-image",
    contents: "Create a picture of a nano banana dish in a fancy restaurant with a Gemini theme",
    config: { responseModalities: ["TEXT", "IMAGE"] },
  });

  let finalImagePart;
  for (const part of response.candidates[0].content.parts) {
    if (part.thought === true) {
      continue;
    }
    if (part.text) {
      console.log(part.text);
    }
    if (part.inlineData) {
      finalImagePart = part;
    }
  }

  if (finalImagePart) {
    const mimeType = finalImagePart.inlineData.mimeType;
    const extension = {
      "image/jpeg": "jpg",
      "image/png": "png",
      "image/webp": "webp",
    }[mimeType];
    if (!extension) {
      throw new Error(`Unsupported image MIME type: ${mimeType}`);
    }
    const filename = `generated_image.${extension}`;
    fs.writeFileSync(filename, Buffer.from(finalImagePart.inlineData.data, "base64"));
    console.log(`Image saved to ${filename}`);
  }
  ```

  ```bash Shell theme={null}
  curl -s -X POST \
    "https://api.runbridge.ai/v1beta/models/gemini-3.1-flash-image:generateContent" \
    -H "Authorization: Bearer $RUNBRIDGE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "contents": [{
        "parts": [{"text": "Create a picture of a nano banana dish in a fancy restaurant with a Gemini theme"}]
      }],
      "generationConfig": {
        "responseModalities": ["TEXT", "IMAGE"]
      }
    }'
  ```
</CodeGroup>

**Save the final image part:**

The image data is in `candidates[0].content.parts`, which can contain text and/or image parts. Gemini image models can also return intermediate thought parts before the final image, especially when you request both text and images or explicitly enable thinking output. Do not save the first `inlineData` blindly; skip parts where `thought` is `true`, then save the last remaining image part. Read its `mimeType` and use the matching file extension: `.jpg` for `image/jpeg`, `.png` for `image/png`, or `.webp` for `image/webp`. The examples write the returned bytes directly without converting the image format.

Typical response with only the final image:

```json theme={null}
{
  "candidates": [{
    "content": {
      "parts": [
        { "text": "Here is your image..." },
        {
          "inlineData": {
            "mimeType": "image/jpeg",
            "data": "<base64-encoded-jpeg>"
          }
        }
      ]
    }
  }]
}
```

Response with a text part, an intermediate thought image, and the final image:

```json theme={null}
{
  "candidates": [{
    "content": {
      "role": "model",
      "parts": [
        { "text": "Here is your image..." },
        {
          "inlineData": {
            "mimeType": "image/jpeg",
            "data": "<base64-encoded-intermediate-image>"
          },
          "thought": true
        },
        {
          "inlineData": {
            "mimeType": "image/jpeg",
            "data": "<base64-encoded-final-image>"
          },
          "thought": false,
          "thoughtSignature": "<signature>"
        }
      ]
    },
    "finishReason": "STOP"
  }]
}
```

Use this parsing rule for every Gemini image response:

```javascript theme={null}
const imageParts = response.candidates[0].content.parts.filter(
  (part) => part.inlineData && part.thought !== true,
);
const finalImagePart = imageParts.at(-1);
```

***

## Image-to-image generation

Save a JPEG input as `source.jpg` in your working directory, then transform it with a text prompt. The Shell example prepares the Base64 JSON body locally before sending one API request.

<CodeGroup>
  ```python Python theme={null}
  from pathlib import Path
  from google import genai
  from google.genai import types
  from PIL import Image
  import os

  client = genai.Client(
      http_options={"api_version": "v1beta", "base_url": "https://api.runbridge.ai"},
      api_key=os.environ["RUNBRIDGE_API_KEY"],
  )

  # Load the source image
  source_image = Image.open("source.jpg")

  response = client.models.generate_content(
      model="gemini-3.1-flash-image",
      contents=["Transform this into a watercolor painting", source_image],
      config=types.GenerateContentConfig(
          response_modalities=["TEXT", "IMAGE"],
      ),
  )

  final_image = None
  for part in response.parts:
      if getattr(part, "thought", False):
          continue
      if part.text is not None:
          print(part.text)
      elif part.inline_data is not None:
          final_image = part.inline_data

  if final_image:
      extension = {
          "image/jpeg": "jpg",
          "image/png": "png",
          "image/webp": "webp",
      }.get(final_image.mime_type)
      if not extension:
          raise ValueError(f"Unsupported image MIME type: {final_image.mime_type}")
      filename = f"watercolor_output.{extension}"
      Path(filename).write_bytes(final_image.data)
  ```

  ```javascript Node.js theme={null}
  import { GoogleGenAI } from "@google/genai";
  import * as fs from "fs";

  const ai = new GoogleGenAI({
    apiKey: process.env.RUNBRIDGE_API_KEY,
    httpOptions: { apiVersion: "v1beta", baseUrl: "https://api.runbridge.ai" },
  });

  const imageData = fs.readFileSync("source.jpg").toString("base64");

  const response = await ai.models.generateContent({
    model: "gemini-3.1-flash-image",
    contents: [
      { text: "Transform this into a watercolor painting" },
      { inlineData: { mimeType: "image/jpeg", data: imageData } },
    ],
    config: { responseModalities: ["TEXT", "IMAGE"] },
  });

  const imageParts = response.candidates[0].content.parts.filter(
    (part) => part.inlineData && part.thought !== true,
  );
  const finalImagePart = imageParts.at(-1);

  if (finalImagePart) {
    const mimeType = finalImagePart.inlineData.mimeType;
    const extension = {
      "image/jpeg": "jpg",
      "image/png": "png",
      "image/webp": "webp",
    }[mimeType];
    if (!extension) {
      throw new Error(`Unsupported image MIME type: ${mimeType}`);
    }
    const filename = `watercolor_output.${extension}`;
    fs.writeFileSync(filename, Buffer.from(finalImagePart.inlineData.data, "base64"));
  }
  ```

  ```bash Shell theme={null}
  python3 - <<'PYTHON'
  import base64
  import json
  from pathlib import Path

  parts = [{"text": "Transform this into a watercolor painting"}]
  for filename in ('source.jpg',):
      image_data = base64.b64encode(Path(filename).read_bytes()).decode("ascii")
      parts.append({
          "inlineData": {"mimeType": "image/jpeg", "data": image_data}
      })

  request = {
      "contents": [{"role": "user", "parts": parts}],
      "generationConfig": {"responseModalities": ["TEXT", "IMAGE"]},
  }
  Path("nano-banana-request.json").write_text(json.dumps(request))
  PYTHON

  curl -s -X POST \
    "https://api.runbridge.ai/v1beta/models/gemini-3.1-flash-image:generateContent" \
    -H "x-goog-api-key: $RUNBRIDGE_API_KEY" \
    -H "Content-Type: application/json" \
    --data-binary @nano-banana-request.json
  ```
</CodeGroup>

<Note>
  * The Python SDK accepts `PIL.Image` objects directly — no manual Base64 encoding needed.
  * Do **not** include the `data:image/jpeg;base64,` prefix when passing raw Base64 strings.
</Note>

***

## Multi-image composition

Generate a new image from multiple input images. RunBridge AI supports two approaches:

### Method 1: Single collage image

Combine the source images into `collage.jpg` in your working directory, then describe the desired output.

<Frame>
  <img src="https://mintcdn.com/runbridge/1ZaM6YsDnAPeVaRb/images/image/gemini/6100640_569419.png?fit=max&auto=format&n=1ZaM6YsDnAPeVaRb&q=85&s=1256b5f4196d0b0e4a572401c320ef8d" alt="Input collage example" width="1200" height="754" data-path="images/image/gemini/6100640_569419.png" />
</Frame>

<Frame>
  <img src="https://mintcdn.com/runbridge/1ZaM6YsDnAPeVaRb/images/image/gemini/6100640_569420.png?fit=max&auto=format&n=1ZaM6YsDnAPeVaRb&q=85&s=fb22252f5fe49cf4e1b7d7aa94a133b3" alt="Generated output" width="1200" height="733" data-path="images/image/gemini/6100640_569420.png" />
</Frame>

<CodeGroup>
  ```python Python theme={null}
  from pathlib import Path
  from google import genai
  from google.genai import types
  from PIL import Image
  import os

  client = genai.Client(
      http_options={"api_version": "v1beta", "base_url": "https://api.runbridge.ai"},
      api_key=os.environ["RUNBRIDGE_API_KEY"],
  )

  collage = Image.open("collage.jpg")

  response = client.models.generate_content(
      model="gemini-3.1-flash-image",
      contents=[
          "A model is posing and leaning against a pink BMW with a green alien keychain attached to a pink handbag, a pink parrot on her shoulder, and a pug wearing a pink collar and gold headphones",
          collage,
      ],
      config=types.GenerateContentConfig(
          response_modalities=["TEXT", "IMAGE"],
      ),
  )

  final_image = None
  for part in response.parts:
      if getattr(part, "thought", False):
          continue
      if part.inline_data is not None:
          final_image = part.inline_data

  if final_image:
      extension = {
          "image/jpeg": "jpg",
          "image/png": "png",
          "image/webp": "webp",
      }.get(final_image.mime_type)
      if not extension:
          raise ValueError(f"Unsupported image MIME type: {final_image.mime_type}")
      filename = f"composition_output.{extension}"
      Path(filename).write_bytes(final_image.data)
  ```

  ```bash Shell theme={null}
  python3 - <<'PYTHON'
  import base64
  import json
  from pathlib import Path

  parts = [{"text": "A model is posing and leaning against a pink BMW with a green alien keychain attached to a pink handbag, a pink parrot on her shoulder, and a pug wearing a pink collar and gold headphones"}]
  for filename in ('collage.jpg',):
      image_data = base64.b64encode(Path(filename).read_bytes()).decode("ascii")
      parts.append({
          "inlineData": {"mimeType": "image/jpeg", "data": image_data}
      })

  request = {
      "contents": [{"role": "user", "parts": parts}],
      "generationConfig": {"responseModalities": ["TEXT", "IMAGE"]},
  }
  Path("nano-banana-request.json").write_text(json.dumps(request))
  PYTHON

  curl -s -X POST \
    "https://api.runbridge.ai/v1beta/models/gemini-3.1-flash-image:generateContent" \
    -H "x-goog-api-key: $RUNBRIDGE_API_KEY" \
    -H "Content-Type: application/json" \
    --data-binary @nano-banana-request.json
  ```
</CodeGroup>

### Method 2: Multiple separate images (up to 14)

Pass multiple images directly. Save three JPEG inputs as `image1.jpg`, `image2.jpg`, and `image3.jpg` in your working directory. Nano Banana 2 and Pro support up to 14 reference images:

<CodeGroup>
  ```python Python theme={null}
  from pathlib import Path
  from google import genai
  from google.genai import types
  from PIL import Image
  import os

  client = genai.Client(
      http_options={"api_version": "v1beta", "base_url": "https://api.runbridge.ai"},
      api_key=os.environ["RUNBRIDGE_API_KEY"],
  )

  image1 = Image.open("image1.jpg")
  image2 = Image.open("image2.jpg")
  image3 = Image.open("image3.jpg")

  response = client.models.generate_content(
      model="gemini-3.1-flash-image",
      contents=["Merge the three images", image1, image2, image3],
      config=types.GenerateContentConfig(
          response_modalities=["TEXT", "IMAGE"],
      ),
  )

  final_image = None
  for part in response.parts:
      if getattr(part, "thought", False):
          continue
      if part.inline_data is not None:
          final_image = part.inline_data

  if final_image:
      extension = {
          "image/jpeg": "jpg",
          "image/png": "png",
          "image/webp": "webp",
      }.get(final_image.mime_type)
      if not extension:
          raise ValueError(f"Unsupported image MIME type: {final_image.mime_type}")
      filename = f"merged_output.{extension}"
      Path(filename).write_bytes(final_image.data)
  ```

  ```bash Shell theme={null}
  python3 - <<'PYTHON'
  import base64
  import json
  from pathlib import Path

  parts = [{"text": "Merge the three images"}]
  for filename in ('image1.jpg', 'image2.jpg', 'image3.jpg'):
      image_data = base64.b64encode(Path(filename).read_bytes()).decode("ascii")
      parts.append({
          "inlineData": {"mimeType": "image/jpeg", "data": image_data}
      })

  request = {
      "contents": [{"role": "user", "parts": parts}],
      "generationConfig": {"responseModalities": ["TEXT", "IMAGE"]},
  }
  Path("nano-banana-request.json").write_text(json.dumps(request))
  PYTHON

  curl -s -X POST \
    "https://api.runbridge.ai/v1beta/models/gemini-3.1-flash-image:generateContent" \
    -H "x-goog-api-key: $RUNBRIDGE_API_KEY" \
    -H "Content-Type: application/json" \
    --data-binary @nano-banana-request.json
  ```
</CodeGroup>

<Frame>
  <img src="https://mintcdn.com/runbridge/1ZaM6YsDnAPeVaRb/images/image/gemini/6100640_569429.png?fit=max&auto=format&n=1ZaM6YsDnAPeVaRb&q=85&s=ebcea0525d66bc15182b445e26742d2c" alt="Multi-image generation result" width="1248" height="832" data-path="images/image/gemini/6100640_569429.png" />
</Frame>

***

## 4K image generation

Specify `image_config` with `aspect_ratio` and `image_size` for high-resolution output:

<CodeGroup>
  ```python Python theme={null}
  from pathlib import Path
  from google import genai
  from google.genai import types
  import os

  client = genai.Client(
      http_options={"api_version": "v1beta", "base_url": "https://api.runbridge.ai"},
      api_key=os.environ["RUNBRIDGE_API_KEY"],
  )

  response = client.models.generate_content(
      model="gemini-3.1-flash-image",
      contents="Da Vinci style anatomical sketch of a Monarch butterfly on textured parchment",
      config=types.GenerateContentConfig(
          response_modalities=["TEXT", "IMAGE"],
          image_config=types.ImageConfig(
              aspect_ratio="1:1",
              image_size="4K",
          ),
      ),
  )

  final_image = None
  for part in response.parts:
      if getattr(part, "thought", False):
          continue
      if part.text is not None:
          print(part.text)
      elif part.inline_data is not None:
          final_image = part.inline_data

  if final_image:
      extension = {
          "image/jpeg": "jpg",
          "image/png": "png",
          "image/webp": "webp",
      }.get(final_image.mime_type)
      if not extension:
          raise ValueError(f"Unsupported image MIME type: {final_image.mime_type}")
      filename = f"butterfly_4k.{extension}"
      Path(filename).write_bytes(final_image.data)
  ```

  ```javascript Node.js theme={null}
  import { GoogleGenAI } from "@google/genai";
  import * as fs from "fs";

  const ai = new GoogleGenAI({
    apiKey: process.env.RUNBRIDGE_API_KEY,
    httpOptions: { apiVersion: "v1beta", baseUrl: "https://api.runbridge.ai" },
  });

  const response = await ai.models.generateContent({
    model: "gemini-3.1-flash-image",
    contents: "Da Vinci style anatomical sketch of a Monarch butterfly on textured parchment",
    config: {
      responseModalities: ["TEXT", "IMAGE"],
      imageConfig: { aspectRatio: "1:1", imageSize: "4K" },
    },
  });

  const imageParts = response.candidates[0].content.parts.filter(
    (part) => part.inlineData && part.thought !== true,
  );
  const finalImagePart = imageParts.at(-1);

  if (finalImagePart) {
    const mimeType = finalImagePart.inlineData.mimeType;
    const extension = {
      "image/jpeg": "jpg",
      "image/png": "png",
      "image/webp": "webp",
    }[mimeType];
    if (!extension) {
      throw new Error(`Unsupported image MIME type: ${mimeType}`);
    }
    const filename = `butterfly_4k.${extension}`;
    fs.writeFileSync(filename, Buffer.from(finalImagePart.inlineData.data, "base64"));
  }
  ```

  ```bash Shell theme={null}
  curl -s -X POST \
    "https://api.runbridge.ai/v1beta/models/gemini-3.1-flash-image:generateContent" \
    -H "Authorization: Bearer $RUNBRIDGE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "contents": [{"parts": [{"text": "Da Vinci style anatomical sketch of a Monarch butterfly on textured parchment"}]}],
      "generationConfig": {
        "responseModalities": ["TEXT", "IMAGE"],
        "imageConfig": {"aspectRatio": "1:1", "imageSize": "4K"}
      }
    }'
  ```
</CodeGroup>

<Note>
  For high-resolution requests, judge the output by the final non-thought image part. If your integration saves the first `inlineData` part, it may save an intermediate thought image that is lower resolution than the requested `imageSize`.
</Note>

***

## Multi-turn image editing (chat)

Use the SDK's chat feature to iteratively refine images:

<CodeGroup>
  ```python Python theme={null}
  from pathlib import Path
  from google import genai
  from google.genai import types
  import os

  client = genai.Client(
      http_options={"api_version": "v1beta", "base_url": "https://api.runbridge.ai"},
      api_key=os.environ["RUNBRIDGE_API_KEY"],
  )

  chat = client.chats.create(
      model="gemini-3.1-flash-image",
      config=types.GenerateContentConfig(
          response_modalities=["TEXT", "IMAGE"],
      ),
  )

  ## First turn: Generate
  response = chat.send_message(
      "Create a vibrant infographic explaining photosynthesis as a recipe, styled like a colorful kids cookbook"
  )

  final_image = None
  for part in response.parts:
      if getattr(part, "thought", False):
          continue
      if part.text is not None:
          print(part.text)
      elif part.inline_data is not None:
          final_image = part.inline_data

  if final_image:
      extension = {
          "image/jpeg": "jpg",
          "image/png": "png",
          "image/webp": "webp",
      }.get(final_image.mime_type)
      if not extension:
          raise ValueError(f"Unsupported image MIME type: {final_image.mime_type}")
      filename = f"v1.{extension}"
      Path(filename).write_bytes(final_image.data)

  ## Second turn: Refine
  response = chat.send_message("Update this infographic to be in Spanish. Do not change any other elements.")

  final_image = None
  for part in response.parts:
      if getattr(part, "thought", False):
          continue
      if part.text is not None:
          print(part.text)
      elif part.inline_data is not None:
          final_image = part.inline_data

  if final_image:
      extension = {
          "image/jpeg": "jpg",
          "image/png": "png",
          "image/webp": "webp",
      }.get(final_image.mime_type)
      if not extension:
          raise ValueError(f"Unsupported image MIME type: {final_image.mime_type}")
      filename = f"v2.{extension}"
      Path(filename).write_bytes(final_image.data)
  ```

  ```javascript Node.js theme={null}
  import { GoogleGenAI } from "@google/genai";
  import * as fs from "fs";

  const ai = new GoogleGenAI({
    apiKey: process.env.RUNBRIDGE_API_KEY,
    httpOptions: { apiVersion: "v1beta", baseUrl: "https://api.runbridge.ai" },
  });

  const chat = ai.chats.create({
    model: "gemini-3.1-flash-image",
    config: { responseModalities: ["TEXT", "IMAGE"] },
  });

  // First turn: generate
  const response1 = await chat.sendMessage({
    message: "Create a vibrant infographic explaining photosynthesis as a recipe, styled like a colorful kids cookbook",
  });
  const imageParts1 = response1.candidates[0].content.parts.filter(
    (part) => part.inlineData && part.thought !== true,
  );
  const finalImagePart1 = imageParts1.at(-1);
  if (finalImagePart1) {
    const mimeType = finalImagePart1.inlineData.mimeType;
    const extension = {
      "image/jpeg": "jpg",
      "image/png": "png",
      "image/webp": "webp",
    }[mimeType];
    if (!extension) {
      throw new Error(`Unsupported image MIME type: ${mimeType}`);
    }
    const filename = `v1.${extension}`;
    fs.writeFileSync(filename, Buffer.from(finalImagePart1.inlineData.data, "base64"));
  }

  // Second turn: refine
  const response2 = await chat.sendMessage({
    message: "Update this infographic to be in Spanish. Do not change any other elements.",
  });
  const imageParts2 = response2.candidates[0].content.parts.filter(
    (part) => part.inlineData && part.thought !== true,
  );
  const finalImagePart2 = imageParts2.at(-1);
  if (finalImagePart2) {
    const mimeType = finalImagePart2.inlineData.mimeType;
    const extension = {
      "image/jpeg": "jpg",
      "image/png": "png",
      "image/webp": "webp",
    }[mimeType];
    if (!extension) {
      throw new Error(`Unsupported image MIME type: ${mimeType}`);
    }
    const filename = `v2.${extension}`;
    fs.writeFileSync(filename, Buffer.from(finalImagePart2.inlineData.data, "base64"));
  }
  ```
</CodeGroup>

***

## Tips

<AccordionGroup>
  <Accordion title="Write the prompt">
    Specify style keywords (e.g., "cyberpunk, film grain, low contrast"), aspect ratio, subject, background, lighting, and detail level.
  </Accordion>

  <Accordion title="Send Base64 image data">
    When using raw HTTP, do not include `data:image/png;base64,` prefix — use only the raw Base64 string. The Python SDK handles this automatically with `PIL.Image` objects.
  </Accordion>

  <Accordion title="Request image output">
    Set `"responseModalities"` to `["IMAGE"]` to request image-only output.
  </Accordion>

  <Accordion title="Why is my image blurry or lower resolution?">
    Check whether your code saved an intermediate thought image. Gemini image responses may include image parts where `thought` is `true`; these are not the final output. Skip `thought: true` parts and save the last image part where `inlineData` exists and `thought` is not `true`. If you do not need text output, request `"responseModalities": ["IMAGE"]` to reduce mixed text/image response handling.
  </Accordion>
</AccordionGroup>

For more details, see the [API Reference](/api/image/gemini/gemini-generates-image).

**Official documentation:** [Nano Banana image generation](https://ai.google.dev/gemini-api/docs/image-generation)

* [Gemini Image Understanding](https://ai.google.dev/gemini-api/docs/image-understanding)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.