Side-by-side comparison of the Claude API (Anthropic) vs OpenAI API: pricing, context window, tool use, streaming, and migration. With Python code examples.
Switching from OpenAI to Claude (or evaluating both)? Here's a practical comparison with real migration code, not marketing copy.
| Feature | Claude API (Anthropic) | OpenAI API |
|---|---|---|
| Python SDK | pip install anthropic | pip install openai |
| Best general model | claude-sonnet-4-6 ($3/$15) | gpt-4o ($2.50/$10) |
| Fast/cheap model | claude-haiku-4-5 ($0.80/$4) | gpt-4o-mini ($0.15/$0.60) |
| Max context window | 200K tokens | 128K tokens |
| Streaming | Yes (server-sent events) | Yes (server-sent events) |
| Tool / function calling | Yes (tools param) | Yes (tools param) |
| Vision / image input | Yes (URL or base64) | Yes (URL or base64) |
| JSON mode | Prompt-based or tool use | Native JSON mode flag |
| Prompt caching | Yes (native, significant savings) | No native caching |
| Batch API | Yes (50% discount, async) | Yes (50% discount, async) |
# BEFORE (OpenAI)
from openai import OpenAI
client = OpenAI() # reads OPENAI_API_KEY
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Summarize this text in 3 bullet points."}
]
)
print(response.choices[0].message.content)
# AFTER (Claude / Anthropic)
import anthropic
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system="You are a helpful assistant.", # ← top-level, not in messages[]
messages=[
{"role": "user", "content": "Summarize this text in 3 bullet points."}
]
)
print(response.content[0].text)
system as a top-level parameter, not inside messages[].response.content[0].text; OpenAI returns response.choices[0].message.content.tools list with JSON Schema), but Claude calls it tool_use in the response, not tool_calls.# BEFORE (OpenAI function calling)
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "What is the weather in Paris?"}],
tools=[{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}
}]
)
tool_call = response.choices[0].message.tool_calls[0]
print(tool_call.function.name, tool_call.function.arguments)
# AFTER (Claude tool use)
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "What is the weather in Paris?"}],
tools=[{
"name": "get_weather",
"description": "Get current weather for a city",
"input_schema": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}]
)
for block in response.content:
if block.type == "tool_use":
print(block.name, block.input) # {"city": "Paris"}
Use the Claude Cost Calculator to estimate API costs for your specific usage pattern. See Python quickstart to get started immediately.