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.
- 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-flashhas a free tier.gemini-4-argonis 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-flashnow routes to 3.8 Flash, andgemini-3.5-flashroutes 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.
- Open AI Studio. Go to aistudio.google.com and sign in with a Google account.
- Find API Keys. Open the API Keys page and click “Create API key”. Pick a project if asked.
- Copy the key. Since May 28, 2026, new keys are restricted to the Gemini API by default.
- Save it as an environment variable. On macOS or Linux, add
export GEMINI_API_KEY="your-key"to~/.zshrcor~/.bashrc, then reload it. On Windows, add it under Environment Variables and open a new terminal. - Install the SDK. Run
pip install google-genai. Addpydanticfor 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
v1instead ofv1beta. - HTTP client: the default is now
httpx2, and plainhttpxis 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_schemainstead 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 with Google Search
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_chunksto 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 oldgoogle-generativeaipackage. Installgoogle-genaiinstead. - 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. Setapi_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
- Google: What’s new in Gemini 4 Argon (pricing and Dec 1 change)
- Google: Gemini 4 Argon model page
- Google: Gemini 3.8 Flash model page
- Gemini API release notes
- google-genai Python SDK on GitHub
- google-genai changelog (3.0.0)
- Google: Using Gemini API keys
- Google: Rate limits
- Google: Context caching
- Google: File input methods
- cdnping: Gemini API price increase table




