- You install both libraries with pip and they work on Python 3.10 or newer.
- Keep the API key in an environment variable or in a .env file outside the repository.
- Besides a correct response, handle connection errors, rate limits and HTTP statuses.
A first model call from Python is a few lines, but from those few lines to code you can put on a server is a longer road. This text shows the two most popular libraries side by side and collects what has to be added: safe storage of the key, error handling and model configuration. The examples come from the libraries’ README files (Anthropic and OpenAI) on the checking date; model identifiers were replaced with those from the makers’ model pages.
Installation and the API key
Both libraries are installed with pip (pip install anthropic and pip install openai) and require Python 3.10 or newer. They read the API key from environment variables, ANTHROPIC_API_KEY and OPENAI_API_KEY respectively, and OpenAI’s README additionally recommends python-dotenv and a .env file so the key does not land in version control. The rule is simple: you do not write the key into code, paste it into a chat or commit it. If it lands in a repository, revoke it with the provider and generate a new one.
The first call
In the Anthropic library a call looks like this:
import os
from anthropic import Anthropic
client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
message = client.messages.create(
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
model="claude-sonnet-5-5",
)
print(message.content)
In the OpenAI library the README names the Responses API as primary:
import os
from openai import OpenAI
client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
response = client.responses.create(
model="gpt-6-luna",
instructions="You are a helpful assistant.",
input="Explain what a token is in one sentence.",
)
print(response.output_text)
| Anthropic | OpenAI | |
|---|---|---|
| Installation | pip install anthropic | pip install openai |
| Python | 3.10 or newer | 3.10 or newer |
| Basic call | client.messages.create | client.responses.create |
| Reading the text | message.content | response.output_text |
| Key | ANTHROPIC_API_KEY | OPENAI_API_KEY |
| Library licence | MIT | See the repository |
Error handling
A correct response is one of several possible outcomes. OpenAI’s README describes that when the library cannot connect to the API, for example because of a network problem or a timeout, it raises a subclass of APIConnectionError, and when the API returns a non-success status code it raises a subclass of APIStatusError with status_code and response properties. For status 429 there is a separate RateLimitError. The Anthropic library has an analogous set of exceptions described in its documentation. In practice handle three cases: a connection error (retry with a delay), a rate limit (slow down and retry) and the remaining statuses (record the request identifier and show the user an understandable message).
import openai
try:
response = client.responses.create(model="gpt-6-luna", input="Hello")
except openai.APIConnectionError:
... # network problem: retry with a delay
except openai.RateLimitError:
... # status 429: slow down
except openai.APIStatusError as e:
print(e.status_code) # other error: record it and show a message
Streaming, async and environments
The first call is synchronous: the program waits for the whole response. According to its README the OpenAI library offers both a synchronous and an asynchronous client, and the latter is useful in web applications serving many users at once, because one wait for the model does not block the others. For long answers it is worth using streaming, so the user sees text as it is produced, and for large non-urgent tasks check whether the provider offers batch processing. Keep separate keys for the test and production environments, with a spending limit on the test one, so that a bug in a loop does not cost a fortune.
Configuration that saves nerves
Keep the model identifier in one place in the configuration. Set a timeout and a number of retries so that a hung connection does not block the application. Log the response length and the tokens used, because that is the basis of cost control, which I describe in the article Task cost in tokens. The Anthropic library can report each call as an OpenTelemetry span if you register a tracer provider, which eases diagnostics. You will find model identifiers on the pages of Anthropic and OpenAI, and I write about choosing them in the text How to choose a model for the task.
- 01KeyAn environment variable, not code.
- 02ClientOne instance with a timeout.
- 03CallThe model from configuration, not code.
- 04ErrorsConnection, limit, status.
- 05LogTokens, time, request identifier.
- 06TestA trial call with a wrong key.
The next step is answers in a fixed format, which I cover in the article Structured data from a model: Pydantic. You will find all materials in the Python and SDKs hub.
Last checked: 20 October 2026. Libraries and model identifiers change; check their documentation before use.

