Claude API PDF Parsing and Summarization Guide
Claude can read PDFs natively through the Messages API — no separate OCR step, no third-party parsing library required. You send the file as a base64-encoded document block alongside your prompt, and Claude processes both the text and the visual layout (tables, headers, charts) in one pass. This makes it a solid default choice for extracting structured data from contracts, invoices, research papers, or long reports and turning them into clean summaries.
The short answer to "how do I parse and summarize a PDF with the Claude API" is: encode the file, attach it as a document content block in your message, and ask for the output format you want in the prompt (bullet summary, JSON, table extraction, etc.). Claude handles multi-page documents up to roughly 100 pages and 32MB per file, and it reads scanned or image-heavy PDFs just as well as text-native ones because the model processes pages as images internally.
How Claude's native PDF support works
Unlike older pipelines that required pdftotext, pdfplumber, or an OCR service before anything reached the model, Claude's document understanding happens inside the same request as your prompt. You get:
- Layout awareness — tables, multi-column text, and figures are interpreted in context, not flattened into a text blob.
- One request, two modalities — the model sees both the rendered page and any embedded text layer.
- No pre-processing step — you don't need a separate extraction library in your stack just to get text out of a PDF.
This matters for summarization specifically because a lot of document quality is lost when you strip layout before summarizing. A financial report where numbers live in a table loses meaning if you flatten it to plain text first.
Sending a PDF to the API
A minimal request looks like this:
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-opus-4-20250514",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": [
{
"type": "document",
"source": {
"type": "base64",
"media_type": "application/pdf",
"data": "BASE64_ENCODED_PDF_HERE"
}
},
{
"type": "text",
"text": "Summarize this report in five bullet points, including any key figures from tables."
}
]
}
]
}'
If your app already talks to Claude through SubToAPI, the request shape is identical — you're hitting your own sub_live_... key instead of a raw Anthropic key, so you don't have to change how your document-handling code works:
curl https://api.subtoapi.app/v1/messages \
-H "Authorization: Bearer $SUBTOAPI_KEY" \
-H "content-type: application/json" \
-d '{
"model": "claude-opus-4-20250514",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": [
{ "type": "document", "source": { "type": "base64", "media_type": "application/pdf", "data": "BASE64_ENCODED_PDF_HERE" } },
{ "type": "text", "text": "Summarize this report in five bullet points, including any key figures from tables." }
]
}
]
}'
Full request and response field reference is in /docs/messages, and a working end-to-end setup is in /docs/quickstart.
Getting better summaries, not just shorter text
Dumping a PDF into the model and asking for "a summary" works, but you get noticeably better output by being specific:
- Define the audience. "Summarize for a non-technical stakeholder" vs "summarize for a compliance reviewer" produces very different output from the same document.
- Ask for structure. Request headings, a TL;DR line, or a JSON object with fields like
key_findings,action_items,risks— Claude follows structured formats reliably from PDF input the same way it does from plain text. - Chunk only when necessary. For documents under the page/size limits, send the whole file in one request so Claude retains cross-page context (a conclusion that references a table on page 3). Only split documents that exceed the limit, and in that case summarize each chunk, then run a second pass that summarizes the summaries.
- Combine with tool use for extraction. If you need summarization plus structured data pulled into your own database (invoice line items, contract clauses), define a tool schema and have Claude call it with the extracted fields instead of parsing free text yourself — see /docs/tools.
Streaming long summaries
For large reports, summaries can run long enough that you want tokens as they're generated rather than waiting for the full response. Claude supports server-sent event streaming for this, and it works the same way whether the input includes a PDF or not:
const response = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SUBTOAPI_KEY}`,
"content-type": "application/json",
},
body: JSON.stringify({
model: "claude-opus-4-20250514",
max_tokens: 2048,
stream: true,
messages: [
{
role: "user",
content: [
{ type: "document", source: { type: "base64", media_type: "application/pdf", data: pdfBase64 } },
{ type: "text", text: "Produce a structured summary with headings: Overview, Key Numbers, Risks, Next Steps." },
],
},
],
}),
});
Details on handling the event stream, including partial-token deltas and reconnect behavior, are covered in /docs/streaming.
Why teams route PDF workloads through SubToAPI
Document-heavy summarization tends to be a shared workload — a support team parsing contracts, a finance team summarizing reports, a product team extracting feedback from PDFs. SubToAPI turns your existing Claude access into application-scoped API keys so each use case gets its own sub_live_... key, usage is tracked per key in one dashboard, and team members share seats instead of juggling personal credentials. Plans start at €9/month solo, with Team (€19/seat) and Scale (€49/seat) tiers for shared usage, and every plan includes a free trial — see /pricing or go straight to /signup.
questions
Does Claude need a separate OCR step to read scanned PDFs? No. Claude processes PDF pages as images internally, so scanned documents and image-heavy files are read the same way as text-native PDFs, without a separate OCR pipeline.
What's the maximum PDF size Claude can handle in one request? Roughly 100 pages and 32MB per file. Larger documents should be split into chunks, summarized individually, and then combined with a second summarization pass.
Can I get a structured JSON summary instead of plain text? Yes. Ask for a specific JSON schema in your prompt, or use tool calling to have Claude return extracted fields directly — see /docs/tools for the request format.