Vision and Multimodal Input
Claude reads pixels the same way it reads text — send it a screenshot, a photo, a chart, or a scanned form alongside your prompt, and it reasons about what's in the image directly.
Imagine describing a comic strip to a friend over the phone versus just handing them the page — talking is slow and you might get details wrong. Giving Claude a photo, screenshot, or scanned document is like handing over the actual page. No describing required: it just looks at the picture and tells you what's there, whether that's a receipt, a dashboard, or a hand-drawn sketch.
How to send an image to Claude
☺ Like you're 10: Talking to Claude with a picture is like handing someone a photo instead of describing it out loud — you just need to say where the picture is (the raw bytes, or a link) and what you want done with it.
Images travel in the same messages array as everything else, as a content block of "type": "image" sitting next to "type": "text" blocks inside a user turn. The block's source object tells Claude where the bytes come from — there are two ways to populate it: inline base64-encoded data, or a URL Claude fetches itself.
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": "<base64-encoded bytes>"
}
},
{
"type": "image",
"source": {
"type": "url",
"url": "https://example.com/dashboard.png"
}
},
{
"type": "text",
"text": "Compare these two dashboards."
}
]
}
Claude's vision input accepts the common web image formats — JPEG, PNG, GIF, and WebP — so you rarely need to convert anything before sending it. Whichever source type you use, the media_type (for base64) should match the actual file, and image blocks can be freely interleaved with text blocks in any order within the content array.
| Source type | When to use it | Trade-offs |
|---|---|---|
Base64 (source.type: "base64") | Local files, screenshots you just captured, anything not already hosted publicly | You read and encode the bytes yourself; the encoded payload adds to your request size |
Image URL (source.type: "url") | Images already hosted at a public URL | No local encoding step, but Claude has to be able to fetch the URL, and — like any externally sourced content — it should be treated as untrusted rather than blindly trusted |
Here's a complete example that reads a local file, base64-encodes it, and asks Claude to summarize a chart:
import anthropic
import base64
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY from env
with open("chart.png", "rb") as f:
image_data = base64.standard_b64encode(f.read()).decode("utf-8")
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": image_data,
},
},
{
"type": "text",
"text": "What trend does this chart show? Summarize in two sentences.",
},
],
}
],
)
for block in message.content:
if block.type == "text":
print(block.text)
import Anthropic from "@anthropic-ai/sdk";
import { readFileSync } from "fs";
const client = new Anthropic(); // reads ANTHROPIC_API_KEY from env
const imageData = readFileSync("chart.png").toString("base64");
const message = await client.messages.create({
model: "claude-sonnet-5",
max_tokens: 1024,
messages: [
{
role: "user",
content: [
{
type: "image",
source: {
type: "base64",
media_type: "image/png",
data: imageData
}
},
{
type: "text",
text: "What trend does this chart show? Summarize in two sentences."
}
]
}
]
});
for (const block of message.content) {
if (block.type === "text") {
console.log(block.text);
}
}
Every current Claude model accepts image input — you don't need a top-tier model just to read a screenshot. Claude Haiku 4.5 is a perfectly capable, cheaper choice for straightforward vision tasks like reading a receipt; reach for Sonnet 5 or Opus 5 when the image needs deeper reasoning alongside it, like cross-referencing a chart against written context.
Practical tips for working with images
A few habits make image prompts noticeably more reliable.
Keep image size reasonable. Very large, high-resolution scans add to your request size and input-token cost without necessarily improving Claude's ability to read them — Claude doesn't need a 20-megapixel TIFF to read a receipt. If you control the capture step (a screenshot tool, a phone camera app), resize or compress before sending; check the current API documentation for exact size and dimension limits, since these are the kind of details that get revised as the platform evolves.
You can send multiple images in one prompt. This is the basis for comparison tasks — before/after screenshots, two product photos, a chart from last quarter next to one from this quarter. Refer to images by their position ("the first image," "the second image") or, more reliably, precede each image with a short text block naming it, so there's no ambiguity about which image an instruction or answer applies to.
Label each image in the surrounding text — "Here is the first image, last month's dashboard:" ... "Here is the second image, this month's dashboard:" — so Claude (and you, reading the transcript later) can unambiguously tell them apart.
Dropping three unlabeled images into one prompt and asking "what changed?" Claude has to guess which one you mean by "the last one," and its answer will be just as hard for you to map back to the right image.
Labeled multi-image prompts look like this — two dashboards, one sent as base64, one as a URL, both introduced by name:
{
"role": "user",
"content": [
{ "type": "text", "text": "Here is the first image, last month's dashboard:" },
{
"type": "image",
"source": { "type": "base64", "media_type": "image/png", "data": "<base64 data>" }
},
{ "type": "text", "text": "Here is the second image, this month's dashboard:" },
{
"type": "image",
"source": { "type": "url", "url": "https://example.com/dashboard-this-month.png" }
},
{ "type": "text", "text": "What changed between the first image and the second image?" }
]
}
Realistic use cases
☺ Like you're 10: It's the same as asking a helpful friend "read this receipt for me," "what changed between these two screenshots," or "what's this chart telling us" — except Claude answers by looking, not by you typing everything out first.
Reading a chart or screenshot
Point Claude at a screenshot of a dashboard, a plotted chart, or a UI mockup and ask it to describe trends, spot anomalies, or explain what a control does. This is a fast way to get a second pair of eyes on visual data without manually transcribing it into text first, and it works well combined with a specific question rather than an open-ended "what do you see?"
Extracting data from a scanned document or receipt
A photographed or scanned receipt, invoice, or form is a classic vision use case: ask Claude to pull out line items, totals, dates, and vendor names, ideally into a structured format like JSON so downstream code can consume it directly.
Anthropic's Usage Policy requires human review by a qualified professional before outputs are relied on in high-risk domains like financial, healthcare, and legal use. Expense-report line items from a coffee receipt are low stakes; a scanned contract, medical form, or insurance claim is exactly the kind of case where a person should verify Claude's reading before it drives a decision.
Comparing two images
Send before/after screenshots, two design variants, or two versions of a scanned document in one prompt and ask Claude to describe the differences. Because it can hold both images in context at once, this is a natural fit for visual regression review, design critique, or spotting what changed between two states of the same screen.
Foxy: So if I show Claude a receipt, that's basically OCR — I can trust every digit it reads, right?
Professor Owl: Not quite. Claude reads the whole image the way a person would, not like a barcode scanner. Tiny, blurry, or handwritten text can still trip it up.
Foxy: And if I ask it exactly where something is in the picture, like "point to the total"?
Professor Owl: Treat that as a well-informed guess, not a ruler measurement — it isn't a specialized object-detection model.
Cami: Which is exactly why I flex my trust level to match the image — crisp screenshot, I take the read at face value; grainy receipt or a coordinate guess, I always get a human to double-check before it drives anything important.
Limitations to keep in mind
☺ Like you're 10: Even a sharp-eyed friend can misread a blurry receipt or misjudge exactly where something sits on a page. Claude's the same — great at the big picture, not a laser measuring tool for tiny text or exact coordinates.
Vision is genuinely useful, but it's worth being precise about what it isn't.
Claude's vision is not a pixel-perfect OCR engine. It can misread dense, small, low-contrast, or heavily stylized text — think tiny footnotes, blurry photos, or handwriting — the same way a person squinting at a bad scan might. For any extraction where a wrong character or digit matters (an account number, a dosage, a legal figure), treat Claude's read as a strong first pass, not ground truth, and verify the critical fields.
Don't assume exact bounding-box or pixel-coordinate precision. If you ask Claude to locate an object or region in an image, treat the answer as an estimate rather than a calibrated measurement — vision-language reasoning is not the same as a specialized object-detection model. Confirm the current API documentation before building pixel-precise automation (like clicking a specific screen coordinate) on top of Claude's coordinate guesses, rather than assuming precision it may not guarantee.
Save a screenshot of a pricing table, dashboard, or receipt to your project folder. Using the Python sample above, ask Claude to extract the contents as JSON with specific fields (e.g., item, price, date). Then take a second, harder image — something with small or dense text — and compare how confident and accurate the extraction is. Finally, ask Claude for the pixel coordinates of one element in the image and see how it hedges its answer.
You should now be able to explain the two ways to get an image into a message (base64 versus URL) and when each fits, why labeling images in a multi-image prompt keeps Claude's answers unambiguous, where vision earns its keep (charts, receipts, before/after comparisons), and why you shouldn't treat its reads or coordinate guesses as ground truth in high-stakes cases. Next up: Streaming and Context, for handling longer responses and bigger conversations.
Check your answers
- What are the two ways to give Claude an image, and when would you pick each? Base64-encoded data inside the
sourceobject, best for local files and screenshots you just captured; or a URL Claude fetches itself, best for images already hosted publicly (treated as untrusted content like any external source). - Why should you label multiple images in one prompt instead of just saying "the last one"? Without a label, Claude has to guess which image you mean, and its answer becomes just as hard for you to map back to the right image — a short text block naming each image ("here is the first image...") removes the ambiguity for both Claude and anyone reading the transcript later.
- What are vision's two main precision limits, and what should you do about them? It isn't pixel-perfect OCR (dense, small, or handwritten text can be misread) and it doesn't give calibrated bounding-box or pixel coordinates (treat locations as estimates). In high-risk domains — financial, healthcare, legal — a qualified human should review the output before it drives a decision.