This page walks you through the absolute minimum: install a library, set up your key securely, and send your first prompt.
OpenRouter is compatible with the standard openai Python library, but it also
has its own Python SDK. In this example we use the dedicated OpenRouter SDK.
pip install openrouter
This gives us a Python client designed specifically for OpenRouter.
Your API key is like a password that controls access to your account and billing. If it leaks, anyone can use your credits — or worse, rack up charges.
Never hard-code your API key in a Python script. If you commit it to Git, it’s exposed forever (even if you delete it later).
Method 1: Environment Variables
Set your key as an environment variable so it stays outside your code:
On macOS / Linux (terminal):
export OPENROUTER_API_KEY="sk-or-v1-your-key-here"
Add this line to your ~/.zshrc or ~/.bashrc to make it permanent. This is simple but assume you will use that variable in every project.
Method 2: Using a .env file (recommended for projects):
Create a file named .env in your project folder:
OPENROUTER_API_KEY=sk-or-v1-your-key-here
Then install python-dotenv to load it automatically:
pip install python-dotenv
Add .env to your .gitignore file immediately:
echo ".env" >> .gitignore
Create a file called hello.py:
import os
from openrouter import OpenRouter
# Load the key from an environment variable
api_key = os.environ.get("OPENROUTER_API_KEY")
if not api_key:
raise RuntimeError("OPENROUTER_API_KEY not set")
# Create an OpenRouter client
with OpenRouter(api_key=api_key) as open_router:
# Send a message
response = open_router.chat.send(
model="openai/gpt-4.1-nano", # cheap and fast for testing
messages=[
{
"role": "system",
"content": "You are a concise assistant. Be accurate, friendly, and brief. Do not use markdown headings. Keep the reply under 80 words. Format your answer to be UNIX terminal friendly (new lines, ascii art if needed)"
},
{
"role": "user",
"content": "Say hello, tell me what model you are, and give one surprisingly useful Python tip."
}
],
stream=False,
)
# Print the reply
print(response.choices[0].message.content)
Run it:
python hello.py
Expected output (exact wording will vary):
hello!
I am ChatGPT, based on the GPT-4 model.
Python tip: Use `_` as a throwaway variable for unused values in unpacking.
Example:
a, _, c = (1, 2, 3) # Ignore the second value
OpenRouter returns usage information with the response. This includes token counts and the cost of the call in OpenRouter credits.
Add this inside the with OpenRouter(...) block, after printing the reply:
if response.usage:
print("\nUsage:")
print(f"Prompt tokens: {response.usage.prompt_tokens}")
print(f"Completion tokens: {response.usage.completion_tokens}")
print(f"Total tokens: {response.usage.total_tokens}")
cost = getattr(response.usage, "cost", None)
if isinstance(cost, (int, float)):
print(f"Cost: {cost:.8f} credits")
Token count is useful because most models charge based on how many tokens
you send and receive. A token is roughly a word fragment, not exactly a word.
Inside the same OpenRouter client, you can also fetch usage using the generation ID. This is useful if you want to audit a call later:
generation = open_router.generations.get_generation(id=response.id)
print("Generation ID:", generation.data.id)
print("Model:", generation.data.model)
print("Prompt tokens:", generation.data.tokens_prompt)
print("Completion tokens:", generation.data.tokens_completion)
print("Total cost (credits):", generation.data.total_cost)
For a single script, response.usage is usually enough. The generation endpoint
is useful when you want to audit previous calls or log costs more carefully.
You can also monitor spending in your OpenRouter account dashboard.
Check the models available (and their cost) from openrouter.ai/models
One of the best things about OpenRouter: switch models by changing one string.
# Try Claude instead — everything else stays the same
response = open_router.chat.send(
model="anthropic/claude-3.5-haiku", # only this line changed
messages=[
{"role": "user", "content": "Say hello and tell me what model you are."}
],
stream=False,
)
Available models you can try (check openrouter.ai/models for the full, up-to-date list):
| Model string | Provider | Cost (approx.) |
|---|---|---|
openai/gpt-4.1-nano |
OpenAI | Very cheap |
openai/gpt-4o |
OpenAI | Moderate |
anthropic/claude-3.5-haiku |
Anthropic | Cheap |
anthropic/claude-sonnet-4-20250514 |
Anthropic | Moderate |
google/gemini-2.5-flash |
Free tier available | |
meta-llama/llama-4-maverick |
Meta | Cheap |
deepseek/deepseek-chat |
DeepSeek | Very cheap |
For testing and development, start with openai/gpt-4.1-nano or
google/gemini-2.5-flash — they cost fractions of a cent per call.
python-dotenv (Recommended Approach)If you installed python-dotenv, your script can load the .env file automatically,
so you don’t need to set environment variables manually:
import os
from dotenv import load_dotenv
from openrouter import OpenRouter
load_dotenv() # loads .env from the current directory
with OpenRouter(api_key=os.environ["OPENROUTER_API_KEY"]) as open_router:
response = open_router.chat.send(
model="openai/gpt-4.1-nano",
messages=[
{"role": "user", "content": "Say hello from a .env file."}
],
stream=False,
)
print(response.choices[0].message.content)
This is a convenient approach for small projects and notebooks.
Now that you can send a single prompt, the next page shows you how to build something genuinely useful: batch-processing images into an HTML gallery with AI-generated descriptions.