Skip to content

How to Call the Claude API from Python with Streaming

October 27, 2026 · 2 min read

Call client.messages.create(...) to get a whole reply, or client.messages.stream(...) to receive it piece by piece as Claude writes it. Both take the same arguments, and both give you the stop reason and token usage.

First message, then streaming

Install the SDK with pip install anthropic, set ANTHROPIC_API_KEY, and save this as app.py:

import anthropic

client = anthropic.Anthropic()  # reads ANTHROPIC_API_KEY

# 1. A first message
message = client.messages.create(
    model="claude-haiku-5-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Suggest one name for a dark-roast coffee blend."}],
)
for block in message.content:
    if block.type == "text":
        print(block.text)
print("Stop reason:", message.stop_reason)
print("Tokens in/out:", message.usage.input_tokens, message.usage.output_tokens)

# 2. The same kind of request, streamed
print("--- streaming ---")
with client.messages.stream(
    model="claude-haiku-5-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Write a 2-line welcome for a coffee newsletter."}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
    final = stream.get_final_message()

print()
print("Stop reason:", final.stop_reason)
print("Output tokens:", final.usage.output_tokens)

Output from one real run (your text and counts will differ):

Output
**"Midnight Ember"**
Stop reason: end_turn
Tokens in/out: 27 13
--- streaming ---
Welcome to the grind! Every issue brings you fresh brewing tips, bean discoveries, and café stories to fuel your daily cup.
Stop reason: end_turn
Output tokens: 48

What each part does

  • anthropic.Anthropic() creates a client that holds your key. Make one and reuse it.
  • max_tokens is required. It caps the reply's length.
  • message.content is a list of content blocks. Pick the ones with type == "text" instead of using content[0], because the first block can be a thinking block.
  • stop_reason tells you why Claude stopped: end_turn means it finished, max_tokens means your cap cut it off.
  • usage shows the tokens you're billed for.
  • In the stream, text_stream yields each new piece of text. flush=True makes it show up immediately. get_final_message() returns the complete message, so you still get stop_reason and usage.

Common mistake

Reading message.content[0].text. If Claude thinks first, the first block is a thinking block and you get AttributeError: 'ThinkingBlock' object has no attribute 'text'. Loop over the blocks and check block.type, as above.

Also check stop_reason: if it's max_tokens, the reply stops mid-sentence. Raise max_tokens.

Takeaway

Use create for a complete reply and stream when a person is watching. In both cases, pick text blocks by type and check stop_reason and usage.

More on AI & LLMs