Docs / How Agents Talk to Models / Images & multimodal
Images & multimodal
A message's
content can be an array mixing text blocks and image blocks. Images — base64 or URL — are billed as input tokens, scaled by resolution: a typical screenshot adds ~1,500–3,200 tokens, as much as a page of text. The cost model (rate per Mtok) doesn't change; only the input-token count does.Every content value so far has been a plain string. The API also accepts an array of typed blocks, which is how you mix text and images in one turn. In our running example, the agent might be handed a screenshot of the failing CI run rather than raw terminal text — the PNG goes directly into the request alongside the user's question:
json
{
"model": "claude-haiku-4-5",
"max_tokens": 1024,
"messages": [{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64", // or "url" → { "url": "https://…" }
"media_type": "image/png",
"data": "iVBORw0KGgo…" // base64-encoded PNG
}
},
{
"type": "text",
"text": "The CI run ended with this screenshot. What's wrong in orders.py?"
}
]
}]
}Under the hood Images are billed as input tokens using a tile model: the image is resized to fit within a bounding box (2048 px on the long edge, 768 px on the short), then divided into 512×512 px tiles. Each tile costs a fixed token budget, plus a small base cost. A 1080×800 screenshot typically lands around 1,500 tokens — the same as a 300-line Python file. High-resolution images (4K screenshots, multi-page PDFs rendered as images) can exceed 3,000 tokens each.
Common mistake Sending images doesn't change the rate you're charged per token — it changes how many input tokens you consume. An agent that routinely attaches screenshots pays the same per-Mtok price but reads a much larger input on every call. Proxies like Firstpass treat
has_images as a routing signal for exactly this reason: a vision-capable cheap model that can handle the image skips the expensive escalation.Images land in
content as typed blocks with a source (base64 or URL); they're billed as input tokens proportional to resolution — the rate stays flat, the count jumps, and has_images is a real routing signal.