Fundamentals

OpenAI vs Anthropic API for Beginners

You have called one large language model API and it worked. Now you keep seeing two names everywhere — OpenAI and Anthropic — and you cannot tell whether they are interchangeable, whether the code is wildly different, or which one you should commit to first. This guide answers all three, fairly, with the same task written in both so you can see the differences with your own eyes instead of taking anyone's word for it.

Both companies do the same core thing: they host a powerful AI model and rent it to you over the internet. Your Python script sends some text, a model on their servers writes a reply, and the reply comes back as data. OpenAI makes the GPT family of models; Anthropic makes the Claude family. Neither is "the AI" and the other a copy — they are two well-funded labs with strong models, and a beginner can do excellent work with either. The real question is not which is better in the abstract, but which fits the task in front of you.

This is one guide in Understanding LLM APIs, written for creators, marketers, founders, and students who can run a Python file but have not shipped production code.

The four differences that actually matter

Strip away the marketing and the practical gap between the two APIs comes down to four things you will touch in your first hour: how you call the model, where you put the system instruction, how you are billed, and what surrounds each API. The diagram below contrasts them on exactly those dimensions, and the rest of the guide expands each one with runnable code.

OpenAI versus Anthropic across four beginner-facing dimensions A comparison matrix with four rows — SDK call shape, system prompt handling, pricing model, and ecosystem — showing how the OpenAI and Anthropic Python APIs differ on each. OpenAI Anthropic SDK call shape chat.completions .create messages.create content blocks System prompt inside messages role: system separate param system=... Pricing model per token in + out priced per token in + out priced Ecosystem extras images, audio embeddings long context agent tooling
The two APIs agree on the big idea and differ in four small, learnable places: the call you write, where the system instruction goes, how tokens are billed, and what each ecosystem adds around the model.

Prerequisites: two keys, two packages

You need Python 3.10 or newer and a virtual environment. If either is missing, the Setting Up Python for AI section covers it. Confirm your version first:

python --version

Each provider gives you a key from its own dashboard, and each has its own SDK. Install both so you can run the side-by-side examples:

python -m venv .venv
source .venv/bin/activate        # Windows: .venv\Scripts\activate
pip install "openai>=1.40" "anthropic>=0.40" "httpx>=0.27" "python-dotenv>=1.0"
pip freeze > requirements.txt

Store both keys in a .env file in your project folder:

OPENAI_API_KEY=sk-your-openai-key-here
ANTHROPIC_API_KEY=sk-ant-your-anthropic-key-here

Immediately add .env to your .gitignore so a credential never lands in a public repository:

echo ".env" >> .gitignore

A key pushed to a repository can be found and billed by strangers within minutes, so this one line matters more than any model choice you will make.

The same task in both SDKs

Here is the identical task — a short, summarised reply with a clear role instruction — written first for OpenAI, then for Anthropic. Read them together and the differences jump out.

OpenAI version

import os
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()  # reads .env; .env is in .gitignore

client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "system", "content": "You are a concise assistant."},
        {"role": "user", "content": "Summarise what an API key is in two sentences."},
    ],
)

print(response.choices[0].message.content)
print("Tokens:", response.usage.total_tokens)

The system instruction is the first item in the messages list, tagged role: "system". The reply lives at response.choices[0].message.content, because OpenAI can return several choices per call. You do not have to set max_tokens; the model uses its default if you leave it off.

Anthropic version

import os
from dotenv import load_dotenv
from anthropic import Anthropic

load_dotenv()  # reads .env; .env is in .gitignore

client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))

response = client.messages.create(
    model="claude-haiku-4-5",
    max_tokens=300,                      # required on every Anthropic call
    system="You are a concise assistant.",
    messages=[
        {"role": "user", "content": "Summarise what an API key is in two sentences."},
    ],
)

print(response.content[0].text)
print("Tokens:", response.usage.input_tokens + response.usage.output_tokens)

Three things changed. The system instruction is a top-level system= parameter, not a message. The max_tokens argument is required — leave it out and Anthropic returns an error. And the reply lives at response.content[0].text, because Anthropic returns a list of content blocks rather than choices. Everything else — the user message, loading the key, the model name — follows the same shape you already know.

That is the whole story of "different code". Two SDK names, one moved parameter, one required argument, and a different path to the reply text. The thinking you do about the task itself is identical.

Message format and system prompts, side by side

The system prompt is the single most useful control you have on either provider — it sets the model's role, tone, and rules before the user ever speaks. The wording you write is fully portable; only its location moves. To go deeper on crafting these, see Write System Prompts that Control Output Format.

ConcernOpenAIAnthropic
Library / installopenai, pip install openaianthropic, pip install anthropic
Client classOpenAI()Anthropic()
Call methodclient.chat.completions.createclient.messages.create
System promptitem in messages, role: "system"top-level system= parameter
max_tokensoptional (defaults applied)required on every call
Reply textresponse.choices[0].message.contentresponse.content[0].text
Token usageusage.prompt_tokens / completion_tokensusage.input_tokens / output_tokens
Beginner modelgpt-4o-miniclaude-haiku-4-5

Keep this table next to you when you port a script from one provider to the other. Nine times out of ten, those eight rows are every change you need to make.

Pricing and the token model

Both providers bill the same way: by the token, a small chunk of text roughly three-quarters of a word. You pay one rate for the tokens you send (input) and a higher rate for the tokens the model writes back (output). That shared model means the cost-control habits you learn on one carry straight to the other: keep prompts tight, cap max_tokens, and log usage on every call.

Where they differ is the per-token price and the model line-up. Each provider offers a cheap small model for everyday work and a pricier large model for hard reasoning. OpenAI's gpt-4o-mini and Anthropic's Claude Haiku tier are the inexpensive entry points; both cost a fraction of a cent for a short reply. The large models — OpenAI's GPT-4-class and Anthropic's Claude Opus tier — cost meaningfully more per token but reason more deeply.

Because per-token prices change, never hard-code a number from a blog post into your budget. Read the live figure from each provider's pricing page, and measure your own usage with the token counts every response returns. If you want to practise without spending at all, Best Free AI APIs for Beginners covers free options, and Groq vs OpenRouter Free Tier compares two fast free endpoints.

Strengths of each, in plain terms

Neither API wins outright, and the honest answer is that both are excellent for a beginner. Their character differs at the edges.

OpenAI's strength is breadth of ecosystem. Alongside text, it offers image generation, speech-to-text and text-to-speech, and embeddings (numeric representations of text used for search), all under one key and one library. If your project mixes media — generate a thumbnail, transcribe a clip, then write a caption — staying inside one provider is convenient, and the sheer volume of tutorials means most beginner questions are already answered somewhere.

Anthropic's strength is long, careful text work. Claude models handle very large inputs in a single request, which suits summarising long documents or working across a whole codebase, and the API is built with agent and tool workflows in mind. Many writers also find Claude's prose steadier for nuanced, long-form tasks. If your work is mostly reading and writing a lot of text reliably, it is a natural fit.

These are tendencies, not walls. You can generate captions with Claude and write long essays with GPT. Pick based on the bulk of your work, not an exception.

When to use which

Use this as a quick decision aid, not a law:

  • Pick OpenAI when your project needs more than text — images, audio, or embeddings — and you want it all under one library and one key.
  • Pick OpenAI when you are brand new and want the largest pool of tutorials, sample code, and community answers to lean on.
  • Pick Anthropic when your task is reading or writing large amounts of text, especially long documents or multi-file context that needs a big input window.
  • Pick Anthropic when you are building an agent or tool-using workflow and want an API designed around that pattern.
  • Pick either for a standard chatbot, a summariser, or a content generator — both do these well, so choose on price, on a model you like the tone of, or simply on which key you already have.

A provider-agnostic wrapper

Once you understand both, you can hide the difference behind one function and switch providers with a single argument. This worked example does exactly that, so the rest of your program never needs to care which model answered.

import os
from dotenv import load_dotenv
from openai import OpenAI
from anthropic import Anthropic

load_dotenv()  # pulls both keys from .env (which is in .gitignore)

openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
anthropic_client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))


def ask(prompt: str, provider: str = "openai", system: str = "You are concise.") -> str:
    """Send one prompt to either provider and return the reply text."""
    if provider == "openai":
        response = openai_client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[
                {"role": "system", "content": system},
                {"role": "user", "content": prompt},
            ],
        )
        usage = response.usage
        print(f"[openai tokens: {usage.total_tokens}]")
        return response.choices[0].message.content

    if provider == "anthropic":
        response = anthropic_client.messages.create(
            model="claude-haiku-4-5",
            max_tokens=300,            # required for Anthropic
            system=system,             # system is a top-level parameter
            messages=[{"role": "user", "content": prompt}],
        )
        usage = response.usage
        print(f"[anthropic tokens: {usage.input_tokens + usage.output_tokens}]")
        return response.content[0].text

    raise ValueError(f"Unknown provider: {provider}")


if __name__ == "__main__":
    question = "Explain what an LLM API does in two sentences."
    print("OpenAI:   ", ask(question, provider="openai"))
    print("Anthropic:", ask(question, provider="anthropic"))

Run it with python compare.py. You will see both providers answer the same question, each printing its own token report. This pattern — one ask function, a provider switch — is exactly how many production apps stay flexible, choosing a provider per task or falling back to the other when one is busy.

A quick decision summary

If you remember one thing: for mixed-media or maximum tutorials, start with OpenAI; for heavy text and big inputs, start with Anthropic; for everything else, pick whichever key you already hold and move on. The code differences are small and the prompt thinking is shared, so the second provider is an afternoon of learning, not a fresh start. Commit to one, ship something, and add the other when a real task asks for it.

Back to Understanding LLM APIs.