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):
**"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_tokensis required. It caps the reply's length.message.contentis a list of content blocks. Pick the ones withtype == "text"instead of usingcontent[0], because the first block can be a thinking block.stop_reasontells you why Claude stopped:end_turnmeans it finished,max_tokensmeans your cap cut it off.usageshows the tokens you're billed for.- In the stream,
text_streamyields each new piece of text.flush=Truemakes it show up immediately.get_final_message()returns the complete message, so you still getstop_reasonandusage.
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.