← Blog

Claude API PDF Text Extraction Workflow Guide

2026-10-24 · 5 min read · SubToAPI Team

Claude API PDF Text Extraction Workflow

If you're searching for a Claude API PDF text extraction workflow, you're probably trying to pull structured data, summaries, or raw text out of invoices, contracts, research papers, or scanned forms without building a custom OCR pipeline. The short answer: Claude's multimodal models can read PDFs directly (as document blocks or rendered images), interpret layout and tables, and return exactly the text or JSON structure you ask for in a single API call.

This matters because traditional PDF extraction tools (PyPDF2, pdfplumber, Tesseract OCR) choke on multi-column layouts, scanned documents, handwriting, and tables that don't follow a clean grid. Claude handles all of these because it's reasoning over the visual and textual content together, not just parsing a byte stream. Below is a practical workflow you can implement today, along with the tradeoffs to watch for.

Why PDF extraction is harder than it looks

Most "just extract the text" requests actually require multiple layered capabilities:

Claude solves all four because it treats the PDF as a document it can reason about, not just a text blob. That's the core reason an LLM-based workflow beats regex-and-library pipelines for anything beyond simple, clean PDFs.

Step 1: Prepare the PDF for the API

Claude's Messages API accepts documents as base64-encoded content blocks. Keep these practical limits in mind:

Step 2: Send the extraction request

A typical request pairs a document content block with a precise instruction. Precision in the prompt is what separates "pretty good" extraction from "production-ready" extraction.

curl -X POST https://api.subtoapi.app/v1/messages \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4",
    "max_tokens": 2048,
    "messages": [
      {
        "role": "user",
        "content": [
          {
            "type": "document",
            "source": {
              "type": "base64",
              "media_type": "application/pdf",
              "data": "<BASE64_PDF_DATA>"
            }
          },
          {
            "type": "text",
            "text": "Extract all line items from this invoice as JSON with fields: description, quantity, unit_price, total. Return only valid JSON, no commentary."
          }
        ]
      }
    ]
  }'

The key design choice here is forcing structured output. If you ask for "the text," you'll get prose. If you ask for a specific JSON schema, you get something your code can parse deterministically.

Step 3: Enforce structure with a schema

For production workflows, don't rely on Claude's free-text JSON — describe the exact shape you want and validate it on the way out.

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-sonnet-4",
    max_tokens: 4096,
    messages: [{
      role: "user",
      content: [
        { type: "document", source: { type: "base64", media_type: "application/pdf", data: pdfBase64 } },
        { type: "text", text: `Extract this document into JSON matching this schema:
{
  "title": string,
  "date": string,
  "parties": string[],
  "key_terms": string[]
}
Return only JSON.` }
      ]
    }]
  })
});

const data = await response.json();
const extracted = JSON.parse(data.content[0].text);

If you need stricter guarantees, pair this with Claude's tool use — define a tool with an input schema and have Claude call it with the extracted fields instead of writing raw text. See /docs/tools for the mechanics.

Step 4: Handle multi-page and multi-document batches

For workflows processing hundreds of PDFs (contract review, invoice processing, research corpora), build a simple pipeline:

  1. Queue incoming PDFs and base64-encode each.
  2. Send one request per document (or per logical section) with a consistent extraction prompt.
  3. Validate the JSON response against your schema before writing to your database.
  4. Retry failed validations with a stricter "return only JSON, no markdown fences" instruction appended.
  5. Log token usage per document so you can forecast cost at scale.

Running this through SubToAPI gives you an HTTPS endpoint with your own sub_live_ key, streaming support for long documents, and usage metadata per call — useful when you need to track cost per document type or per customer in a multi-tenant product. Check /docs/quickstart to get a key issued in minutes, or /pricing if you're evaluating Solo vs. Team seats for a shared extraction pipeline.

Step 5: Add streaming for long documents

For long PDFs where you want partial results as they're generated (useful for progress indicators in a UI), use streaming instead of waiting for the full response:

const stream = 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",
    max_tokens: 4096,
    stream: true,
    messages: [{ role: "user", content: [
      { type: "document", source: { type: "base64", media_type: "application/pdf", data: pdfBase64 } },
      { type: "text", text: "Summarize each section of this document in order." }
    ]}]
  })
});

Details on consuming the event stream are in /docs/streaming.

Common pitfalls

questions

Can Claude extract text from scanned (image-based) PDFs? Yes. Claude reads the visual content of the PDF, including embedded images, so it can OCR scanned pages without a separate OCR tool, though very low-resolution scans reduce accuracy.

How do I get structured JSON instead of plain text? Describe the exact JSON schema you want in your prompt, set max_tokens high enough to avoid truncation, and validate the parsed output before using it — or use tool calls for stricter schema enforcement (/docs/tools).

What's the best way to process hundreds of PDFs at scale? Build a queue that sends one request per document with a consistent prompt, validates each response, retries failures, and tracks token usage per call — SubToAPI's usage metadata (/docs/messages) makes this easy to monitor across a team.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →