Vision, PDFs, Files, Citations and Structured Outputs
Claude understands images and PDFs along with text. To make output reliable there are structured outputs (JSON schema), and for verifiable answers there are citations.
8.1 Image and PDF input
import base64
pdf = base64.standard_b64encode(open("invoice.pdf", "rb").read()).decode()
r = client.messages.create(
model="claude-opus-5-5", max_tokens=4000,
messages=[{"role": "user", "content": [
{"type": "document",
"source": {"type": "base64", "media_type": "application/pdf", "data": pdf}},
{"type": "image",
"source": {"type": "url", "url": "https://example.com/chart.png"}},
{"type": "text", "text": "Tell me the invoice total and the chart trend."},
]}],
)- Images: JPEG, PNG, GIF, WebP. You can provide them as base64, a URL or through the Files API. Put the image before the text.
- PDF: both the text and an image of every page are understood (tables and charts too). Limit: 32 MB request, 600 pages (100 on 200K-context models).
- Claude does not generate images — it can create visuals through SVG/HTML/code.
8.2 Files API
Instead of uploading the same file again and again, upload it once, get a file_id, then reference it in requests.
f = client.files.upload(file=open("policy.pdf", "rb"))
r = client.messages.create(model="claude-opus-5-5", max_tokens=4000, messages=[{
"role": "user", "content": [
{"type": "document", "source": {"type": "file", "file_id": f.id}},
{"type": "text", "text": "Summarize the leave policy"}]}])8.3 Citations
Set citations: {enabled: true} on the document block. The response text blocks then carry a citations array with cited_text and a location (page number for PDFs) — the user can verify where the answer came from.
8.4 Structured outputs
When a program has to parse the output, provide a JSON schema. The response is guaranteed to be schema-valid.
from pydantic import BaseModel
class Lead(BaseModel):
name: str
email: str
plan: str
r = client.messages.parse(
model="claude-opus-5-5", max_tokens=2000,
messages=[{"role": "user", "content": "Extract: Amit (amit@x.com) wants the Enterprise plan"}],
output_format=Lead,
)
print(r.parsed_output.email) # validated Pydantic object