Skip to content
, ,

Gemini API Python Tutorial (google-genai 3.0): From Free Key to Tools

9–13 minutes
Winking red-haired woman in a violet sweater in a blue-lit tech office holding a card with the Gemini logo, hook text: Prices double, Gemini API

The Gemini API lets you add Google’s models to any Python app with one small library, google-genai. Version 3.0.0 landed on November 6, 2026, and two model prices double in the next two months.

This tutorial takes you from a free API key to text, streaming, JSON output, tools, files, caching, Google Search and error handling. Every code block uses current model IDs.

TLDR

  • Install: pip install google-genai (v3.0.0 needs Python 3.11 or newer).
  • Key: free from Google AI Studio. Save it as GEMINI_API_KEY.
  • Models: gemini-3.8-flash has a free tier. gemini-4-argon is paid only.
  • Price rises: Argon doubles on Dec 1, 2026. 3.8 Flash doubles on Jan 1, 2027.
  • Errors: 429 means a rate limit. Free daily quotas reset at midnight Pacific time.

Which Gemini Model to Use (November 2026)

Two models cover most projects. Pick Flash for speed and cost, and Argon for the hardest reasoning tasks.

Model ID Free tier Price now (per 1M tokens) New price
gemini-3.8-flash Yes $0.75 in / $3.75 out $1.50 in / $7.50 out from Jan 1, 2027
gemini-4-argon No $2.00 in / $10.00 out $4.00 in / $20.00 out from Dec 1, 2026
  • Context: both models take about 1 million tokens (1,048,576) of input.
  • Output: both return up to 65,536 tokens by default. Argon can go higher with long decode.
  • Inputs: text, images, video, audio and PDF. Output is text only.
  • Retired names: gemini-3.7-flash now routes to 3.8 Flash, and gemini-3.5-flash routes to 3.6 Flash.

Warning: Budget for the new prices now. Output on Argon goes from $10 to $20 per million tokens on December 1. See the full breakdown in our Gemini API pricing and free tier guide.

Get a Free API Key and Install the SDK

The key is free and takes about a minute. New AI Studio users get a default Google Cloud project and key automatically.

  1. Open AI Studio. Go to aistudio.google.com and sign in with a Google account.
  2. Find API Keys. Open the API Keys page and click “Create API key”. Pick a project if asked.
  3. Copy the key. Since May 28, 2026, new keys are restricted to the Gemini API by default.
  4. Save it as an environment variable. On macOS or Linux, add export GEMINI_API_KEY="your-key" to ~/.zshrc or ~/.bashrc, then reload it. On Windows, add it under Environment Variables and open a new terminal.
  5. Install the SDK. Run pip install google-genai. Add pydantic for the JSON example.

Note: The SDK reads GEMINI_API_KEY or GOOGLE_API_KEY. If both are set, GOOGLE_API_KEY wins, so set only one.

What changed in google-genai 3.0.0

  • API version: the client now defaults to v1 instead of v1beta.
  • HTTP client: the default is now httpx2, and plain httpx is no longer installed.
  • Python: the release needs Python 3.11 or newer.
  • Video: GenerateVideos was disabled for the Gemini API in this release.

If a beta-only feature fails after upgrading, pin the old API version in code:

from google import genai
from google.genai import types

client = genai.Client(
    http_options=types.HttpOptions(api_version="v1beta")
)

Your First Text Request

Create a client, call generate_content, and print response.text. The client finds your key on its own.

from google import genai
from google.genai import types

client = genai.Client()

response = client.models.generate_content(
    model="gemini-3.8-flash",
    contents="Explain what an API key is in two sentences.",
    config=types.GenerateContentConfig(
        system_instruction="You are a patient teacher for beginners.",
        max_output_tokens=400,
    ),
)
print(response.text)

Control thinking to save money

Thinking tokens are billed as output. Both models support low, medium and high thinking levels, and Argon defaults to medium.

config = types.GenerateContentConfig(
    thinking_config=types.ThinkingConfig(thinking_level="low"),
)

Tip: 3.8 Flash does not support the minimal level and returns an error. Start with low, and only raise it if answers are weak.

Multi-turn chat

chat = client.chats.create(model="gemini-3.8-flash")
print(chat.send_message("My name is Sam.").text)
print(chat.send_message("What is my name?").text)

Streaming Responses

Streaming prints words as they arrive, so users are not staring at a blank screen. Swap generate_content for generate_content_stream.

for chunk in client.models.generate_content_stream(
    model="gemini-3.8-flash",
    contents="Write a 200-word story about a robot gardener.",
):
    print(chunk.text, end="", flush=True)

Chats stream the same way with chat.send_message_stream(). For async apps, use client.aio with the same method names.

Structured JSON Output

Structured output forces Gemini to reply in valid JSON that matches your schema. A Pydantic model is the easiest way to write that schema.

from pydantic import BaseModel

class Recipe(BaseModel):
    name: str
    minutes: int
    ingredients: list[str]

response = client.models.generate_content(
    model="gemini-3.8-flash",
    contents="Give me one quick pasta recipe.",
    config=types.GenerateContentConfig(
        response_mime_type="application/json",
        response_json_schema=Recipe.model_json_schema(),
    ),
)

recipe = Recipe.model_validate_json(response.text)
print(recipe.name, recipe.minutes)
  • Do not repeat the schema: Google warns that copying the schema or sample JSON into your prompt can lower quality.
  • Plain JSON Schema works too: pass a dict to response_json_schema instead of a Pydantic model.
  • Validate anyway: parse with Pydantic so bad data fails loudly in your code.

Function Calling

Function calling lets Gemini ask your code to run a function, such as a database lookup. With the Python SDK you can pass a normal function and it is called for you.

def get_order_status(order_id: str) -> str:
    """Returns the shipping status for an order.

    Args:
        order_id: The order number, for example A123.
    """
    return "Shipped on Nov 5"

response = client.models.generate_content(
    model="gemini-3.8-flash",
    contents="Where is my order A123?",
    config=types.GenerateContentConfig(tools=[get_order_status]),
)
print(response.text)

The docstring and type hints become the tool description, so write them clearly. To approve calls yourself, turn off the automatic mode and read response.function_calls.

config = types.GenerateContentConfig(
    tools=[get_order_status],
    automatic_function_calling=types.AutomaticFunctionCallingConfig(
        disable=True
    ),
)
response = client.models.generate_content(
    model="gemini-3.8-flash",
    contents="Where is my order A123?",
    config=config,
)
for call in response.function_calls or []:
    print(call.name, call.args)

Note: The SDK README warns that a future major version will move automatic function calling out of direct generate_content calls and into the Chats module. Using client.chats for tool loops is the safer long-term choice.

Images, Video and PDF Input

Gemini reads images, audio, video and PDFs in the same request as your text. Small files can go inline, and bigger ones go through the Files API.

Send an image inline

with open("receipt.jpg", "rb") as f:
    image_bytes = f.read()

response = client.models.generate_content(
    model="gemini-3.8-flash",
    contents=[
        types.Part.from_bytes(data=image_bytes, mime_type="image/jpeg"),
        "List every item and price on this receipt.",
    ],
)
print(response.text)

Upload a PDF or video with the Files API

pdf = client.files.upload(file="report.pdf")
video = client.files.upload(file="demo.mp4")

response = client.models.generate_content(
    model="gemini-3.8-flash",
    contents=[pdf, "Summarize this report in five bullet points."],
)
print(response.text)

response = client.models.generate_content(
    model="gemini-3.8-flash",
    contents=[video, "What happens at the one minute mark?"],
)
print(response.text)
Method Max size Kept for
Inline bytes 100 MB request (50 MB for PDFs) Not stored
Files API upload 2 GB per file, 20 GB per project 48 hours
Public URL 15 MB per file Not stored

Large videos may still be processing right after upload. If you get an error, wait a few seconds and check the file with client.files.get(name=video.name).

Context Caching

Caching cuts cost when you send the same big prompt again and again, such as a long manual. Gemini has two kinds.

  • Implicit caching: on by default for Gemini 2.5 and newer. Repeated prompts of at least 4,096 tokens on Argon and 3.8 Flash get a discount automatically.
  • Explicit caching: you create a cache object and reuse it. It works on supported Gemini 3 and 2.5 models through generate_content.
  • Not on Argon: explicit caching is not available for Gemini 4 Argon or in the Interactions API.
manual = client.files.upload(file="manual.pdf")

cache = client.caches.create(
    model="gemini-3.8-flash",
    config=types.CreateCachedContentConfig(
        contents=[manual],
        system_instruction="Answer only from the attached manual.",
        display_name="product-manual",
        ttl="3600s",
    ),
)

response = client.models.generate_content(
    model="gemini-3.8-flash",
    contents="How do I reset the device?",
    config=types.GenerateContentConfig(cached_content=cache.name),
)
print(response.text)
print(response.usage_metadata.cached_content_token_count)

Explicit caches also charge storage per hour, so keep the ttl short and delete caches you no longer need. Our prompt caching guide compares this with Claude and OpenAI.

Grounding lets Gemini search Google before it answers, which helps with news and fresh facts. Add the search tool to your config.

response = client.models.generate_content(
    model="gemini-3.8-flash",
    contents="What did Google announce for Gemini this week?",
    config=types.GenerateContentConfig(
        tools=[types.Tool(google_search=types.GoogleSearch())],
    ),
)
print(response.text)

meta = response.candidates[0].grounding_metadata
if meta:
    print(meta.web_search_queries)
    for chunk in meta.grounding_chunks or []:
        print(chunk.web.title, chunk.web.uri)
  • Free allowance: Gemini 3 and newer models share 5,000 grounded prompts a month on paid projects.
  • After that: $14 per 1,000 search queries. One prompt can trigger more than one search.
  • Show sources: display the links from grounding_chunks to your users.

The New Interactions API

Since June 2026, Google calls the Interactions API its default interface and labels generateContent as legacy. Legacy still works, and it is the only route for explicit caching.

first = client.interactions.create(
    model="gemini-3.8-flash",
    input="Hi, my name is Priya.",
)
print(first.output_text)

second = client.interactions.create(
    model="gemini-3.8-flash",
    input="What is my name?",
    previous_interaction_id=first.id,
)
print(second.output_text)

The server keeps the conversation state, so you only pass the last ID. Built-in tools use simple dicts, such as tools=[{"type": "google_search"}].

stream = client.interactions.create(
    model="gemini-3.8-flash",
    input="Count from 1 to 10.",
    stream=True,
)
for event in stream:
    if event.event_type == "step.delta" and event.delta.type == "text":
        print(event.delta.text, end="", flush=True)

Note: From October 26, 2026, new paid projects store Generate Content requests by default. You can opt out per request or in the logging settings.

Handling Errors and the 429 Free Tier Limit

All API errors raise errors.APIError, with ClientError for 4xx codes and ServerError for 5xx codes. Check e.code to decide what to do.

Code Meaning Fix
400 Bad request or unsupported setting Check model ID, thinking level and schema
403 Key blocked or not allowed Use a restricted key or create a new one
404 Model or file not found Check the model name and that the file is under 48 hours old
429 RESOURCE_EXHAUSTED: rate limit hit Back off and retry, or enable billing
500 / 503 Server busy or error Retry with backoff

Retry 429s automatically

A 429 fires when you pass any one of requests per minute, tokens per minute or requests per day. The SDK can retry for you.

from google import genai
from google.genai import errors, types

client = genai.Client(
    http_options=types.HttpOptions(
        retry_options=types.HttpRetryOptions(
            attempts=5,
            initial_delay=2.0,
            max_delay=60.0,
            http_status_codes=[429, 500, 503],
        )
    )
)

try:
    response = client.models.generate_content(
        model="gemini-3.8-flash",
        contents="Hello",
    )
    print(response.text)
except errors.APIError as e:
    print(e.code, e.message)
  • Daily reset: requests-per-day quotas reset at midnight Pacific time.
  • Check your limits: the AI Studio rate limit page shows your current numbers per model.
  • Tier 1: link a billing account in AI Studio. It usually applies right away.
  • Tiers 2 and 3: need $100 spent plus 3 days, or $1,000 plus 30 days.

Warning: On the free tier, Google may use your prompts and responses to improve its products. Do not send private customer data on a free key.

Troubleshooting: Common Problems and Fixes

  • ImportError on from google import genai: you installed the old google-generativeai package. Install google-genai instead.
  • pip will not install 3.0.0: your Python is older than 3.11. Upgrade Python or pin google-genai<3.
  • “API key not valid”: the variable is not set in this terminal. Open a new terminal or pass api_key= to test.
  • Key shows “Blocked”: long-dormant unrestricted keys were blocked from May 7, 2026. Create a new restricted key.
  • Feature works in AI Studio but not in code: 3.0.0 now defaults to v1. Set api_version="v1beta".
  • Argon returns 429 or a billing error on a free key: Argon has no free tier. Enable billing or use 3.8 Flash.
  • Temperature has no effect on Argon: Google says to remove temperature, top_p and top_k for Argon; they are ignored.
  • Explicit cache fails on Argon: Argon only supports implicit caching. Use 3.8 Flash for explicit caches.

Coming from another provider? Our DeepSeek API Python tutorial follows the same steps, and the AI API pricing comparison shows where Gemini sits on cost.

Frequently Asked Questions

Is the Gemini API free?

Yes, for some models. Gemini 3.8 Flash has a free tier with rate limits, while Gemini 4 Argon is paid only.

Which Python package should I use for Gemini?

Use google-genai, imported as from google import genai. Version 3.0.0 was released on November 6, 2026.

When do Gemini API prices go up?

Gemini 4 Argon doubles to $4 input and $20 output per million tokens on December 1, 2026. Gemini 3.8 Flash doubles to $1.50 and $7.50 on January 1, 2027.

Should I use generate_content or the Interactions API?

Google recommends the Interactions API for new projects. Use generate_content when you need explicit context caching or have existing code.

What does error 429 RESOURCE_EXHAUSTED mean?

You passed a rate limit for requests per minute, tokens per minute or requests per day. Retry with backoff, wait for the midnight Pacific reset, or enable billing.

Can Gemini read PDFs and videos from Python?

Yes. Upload them with client.files.upload(), which accepts files up to 2 GB and keeps them for 48 hours.

How do I make Gemini return JSON?

Set response_mime_type="application/json" and pass a schema in response_json_schema, such as a Pydantic model’s JSON schema.

Sources

Free weekly email

Get new AI guides every week

One short weekly email with our newest local AI, ComfyUI and AI tool guides. No spam, no pop-ups, just the good stuff.

Free. Unsubscribe anytime in one click. We only use your email to send this newsletter. See our privacy policy.

Winking red-haired woman in a violet sweater in a blue-lit tech office holding a card with the Gemini logo, hook text: Prices double, Gemini API