Skip to content

Streaming with base64 images inflates input token count #3949

@bogoconic1

Description

@bogoconic1

Bug Description

When using client.messages.stream() with base64 images in message content, the OpenTelemetry span reports inflated input_tokens. Non-streaming client.messages.create() reports correctly.

Reproduction

import base64, io, os
from anthropic import Anthropic
from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
from PIL import Image

AnthropicInstrumentor().instrument()

client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

img = Image.new("RGB", (500, 500), color=(200, 200, 255))
buf = io.BytesIO()
img.save(buf, format="PNG")
b64 = base64.b64encode(buf.getvalue()).decode()

messages = [{
    "role": "user",
    "content": [
        {"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": b64}},
        {"type": "text", "text": "What color is this? One word."},
    ],
}]

# Non-streaming
response = client.messages.create(model="claude-haiku-4-5-20251001", max_tokens=100, messages=messages)
print(f"[CREATE] API usage: input={response.usage.input_tokens}")

# Streaming
with client.messages.stream(model="claude-haiku-4-5-20251001", max_tokens=100, messages=messages) as stream:
    response = stream.get_final_message()
print(f"[STREAM] API usage: input={response.usage.input_tokens}")

Observed Behavior

Method API usage.input_tokens OTel span reported
create() 343 343
stream() 343 1,633

Expected Behavior

OTel span should match the API's usage.input_tokens for both methods.

Environment

  • opentelemetry-instrumentation-anthropic: 0.57.0
  • anthropic: 0.89.0
  • Python 3.11

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions