Claude API: Summarize PDF Documents Programmatically
Can the Claude API summarize PDF documents?
Yes. Claude's API accepts PDF files directly as document content blocks, so you can send a PDF (or its extracted text) to the model and ask it to produce a summary, extract key points, or answer questions about it. This works for contracts, research papers, financial reports, meeting transcripts exported as PDF, and similar documents — no separate OCR step is required for text-based PDFs, since Claude handles the parsing internally.
The practical question most developers are actually trying to answer is: how do I build a reliable pipeline that takes a PDF upload, sends it to Claude, and returns a clean summary — without hitting token limits, losing formatting, or paying for redundant re-processing. That's what this article covers: the request structure, chunking for large PDFs, and the operational details that matter once you move from a demo script to a production feature.
Sending a PDF to Claude for summarization
Claude's Messages API supports a document content type alongside text and images. You base64-encode the PDF and include it in the same message as your summarization instruction:
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-sonnet-4-5",
"max_tokens": 1024,
"messages": [{
"role": "user",
"content": [
{
"type": "document",
"source": {
"type": "base64",
"media_type": "application/pdf",
"data": "<base64-encoded-pdf>"
}
},
{
"type": "text",
"text": "Summarize this document in 5 bullet points, focusing on action items."
}
]
}]
}'
This same pattern works whether you're calling Anthropic's API directly or through a proxy like SubToAPI. If your app already consumes an API key rather than a raw Claude subscription, the request looks nearly identical — see the Messages docs for the exact payload shape SubToAPI expects.
Handling large PDFs
PDFs with many pages or dense text can exceed the model's effective context window once combined with your prompt and the desired output length. A few strategies:
- Page-range chunking: Split the PDF into logical sections (chapters, pages 1–20, pages 21–40) and summarize each chunk separately, then run a second pass that summarizes the summaries.
- Pre-extraction: Use a library like
pdf-parse(Node) orPyPDF2to pull raw text first, strip boilerplate (headers, page numbers, repeated footers), and send clean text instead of the raw PDF bytes. This reduces token usage significantly for scanned-but-text-based PDFs. - Targeted prompts: Instead of "summarize this," ask for structured output — "list the five key risks mentioned in this contract" — which tends to produce shorter, more useful responses and reduces output token cost.
A simple two-pass map-reduce summarization in JavaScript:
async function summarizeChunk(chunkText) {
const res = 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-sonnet-4-5",
max_tokens: 512,
messages: [{
role: "user",
content: `Summarize the key points in 3-4 sentences:\n\n${chunkText}`
}]
})
});
const data = await res.json();
return data.content[0].text;
}
async function summarizeDocument(chunks) {
const partialSummaries = await Promise.all(chunks.map(summarizeChunk));
return summarizeChunk(partialSummaries.join("\n\n"));
}
This pattern scales to documents of almost any length because each chunk stays well within context limits, and the final reduce step produces a cohesive summary from the partial ones.
Streaming summaries for long documents
If you're summarizing a large PDF in a user-facing tool, streaming the response improves perceived latency — users see the summary forming instead of staring at a spinner for 15-20 seconds. Claude's API supports server-sent events for this via "stream": true, and SubToAPI passes these through unchanged. See streaming docs for the exact event format if you're building a frontend that renders tokens as they arrive.
Common pitfalls
- Sending scanned image PDFs without OCR: If the PDF is a scanned image with no embedded text layer, Claude may struggle to extract content reliably. Run OCR (Tesseract, or a cloud OCR service) first and send the extracted text instead.
- Ignoring page limits: Very long PDFs (100+ pages) sent as a single document block can produce truncated or shallow summaries. Chunk first.
- Re-summarizing unchanged documents: If users repeatedly request summaries of the same PDF, cache the result keyed by a content hash rather than calling the API every time — this is the single biggest cost reduction available for PDF summarization features.
- Not instructing the output format: Asking for "a summary" gives you prose. Asking for "5 bullet points, each under 20 words, no preamble" gives you something you can render directly in a UI without post-processing.
Why route PDF summarization through an API key instead of a chat subscription
If your product needs to summarize PDFs on behalf of multiple users — a SaaS feature, an internal tool, a Slack bot — you need programmatic access with proper authentication, not a personal Claude subscription shared across a team. SubToAPI converts your existing Claude access into a standard HTTPS API with sub_live_... keys, usage metadata per request, and team seats, so you can build a PDF summarization endpoint without managing separate billing per developer. Check pricing for Solo, Team, and Scale plans, or jump straight to the quickstart to get a key in a few minutes.
questions
Does the Claude API support PDF files natively, or do I need to extract text first? Claude accepts PDFs directly as base64-encoded document blocks for text-based PDFs. For scanned image PDFs without an embedded text layer, run OCR first and send extracted text instead.
What's the best way to summarize a 100-page PDF without hitting context limits? Split the document into chunks (by page range or section), summarize each chunk independently, then run a second summarization pass over the combined partial summaries — a standard map-reduce approach.
How do I avoid paying to re-summarize the same PDF repeatedly? Hash the PDF content and cache the summary result against that hash. Only call the API again if the document actually changes, which cuts redundant costs significantly for repeat-access documents.