Back to the main blog

How to parse scanned PDFs: a step-by-step guide with a scanned invoice example

Kushal Byatnal

Kushal Byatnal

8 min read

Nov 12, 2026

Blog Post

A scanned PDF is a stack of images. There is no reliable text to copy out, tables are pixels, and a handwritten note in the margin can change what the document means. Parsing one well takes more than OCR: the pages have to be read in the right orientation, the layout has to survive, and every value you extract needs to point back to where it came from. This guide walks through the full pipeline step by step, using a scanned supplier invoice as the example.

The short answer

To parse a scanned PDF, run layout-aware OCR on every scanned page, correct rotation, fix handwriting and low-quality text with a vision model, keep multi-page tables together, and extract fields with citations and confidence scores.

Extend Parse handles each of those steps in one request:

  • OCR built for scans: the Performance engine is the strongest choice for lower-quality scans, handwriting, checkboxes, and complex tables.
  • Automatic cleanup: page rotation is detected and corrected before parsing.
  • Vision-model correction: agentic OCR finds low-confidence text and handwriting and corrects it with vision language models.
  • Structure that survives: tables, form fields, checkboxes, and signatures come back as typed blocks in reading order, and table headers can be carried across page breaks.
  • Cited extraction: Extract runs on the same file and cites every value to a page and region, with confidence scores you can route on.

Extend Performance Parse scored 95.7% field-level document Q&A accuracy on RealDoc-Bench, a benchmark of real-world regulated documents from healthcare, financial services, logistics, and real estate.

Why scanned PDFs are harder than digital PDFs

ProblemWhat goes wrongWhat fixes it
No reliable text layerCopy-paste and PDF libraries return nothing or garbageOCR on every scanned page
Rotated or sideways pagesOCR reads upside-down or sideways text as noiseAutomatic rotation detection and correction
Low resolution and faded textCharacters drop or get misread, especially digitsVision-model correction of low-confidence text
Handwriting and signaturesNotes, initials, and signed fields are skippedA handwriting-capable engine and signature detection
Tables across pagesRows on page 2 lose their column headersTable header continuation across page breaks
Forms and checkboxesLabels and values come out in the wrong order; checkbox state is lostForm regions parsed as label and value pairs with checkbox state

Example: a scanned supplier invoice

The example below is a three-page invoice that a supplier printed, signed, and scanned:

  • Page 1 was scanned sideways.
  • A handwritten PO number sits next to the printed header.
  • The line-item table runs from page 1 onto page 2, and its column headers only appear on page 1.
  • Page 3 has a signature and a "Received in good condition" checkbox.

The goal is clean Markdown for search and agents, and a structured record with invoice number, PO number, totals, and every line item, each traceable to the page it came from.

Step 1: decide how each page is read

A scanned PDF often carries a text layer added by the scanner, and that layer can be wrong. Decide how text is read before anything else:

  • parse_performance always reads pages with OCR, which is what you want for scans.
  • parse_light and parse_auto default to textExtractionMethod: "auto": they use the PDF's own text where it's reliable and OCR the rest. Set "ocr_only" when the scanner's text layer can't be trusted or you want every page treated the same.

For the invoice, the scanner's text layer misread the sideways page, so it should be read from the image.

Step 2: fix rotation and choose pages

Turn on advancedOptions.pageRotationEnabled. Extend detects rotated pages and corrects their orientation before parsing, so the sideways first page reads like the others. If a scan includes cover sheets or blank pages, advancedOptions.pageRanges limits processing to the pages you need, and you're billed only for the pages processed.

Step 3: choose the engine

EngineUse it forPay-as-you-go price
parse_performanceLower-quality scans, handwriting, dense checkboxes, complex tables, and multilingual documents$20 per 1,000 pages
parse_lightHigh-volume, cleaner scans where cost matters most$5 per 1,000 pages
parse_autoMixed batches: each page is classified by difficulty and routed, so clean pages stay cheap and hard pages get Performance-level treatmentBilled per page by complexity

The example invoice has a handwritten PO number and a checkbox, so it uses parse_performance. A mailroom feed with a mix of clean digital PDFs and rough scans is a good fit for parse_auto.

Step 4: recover handwriting and low-quality text

Enable blockOptions.text.agentic.enabled. Extend finds text regions with low OCR confidence, including hard-to-read handwriting, and corrects them with vision language models. Turn it on for handwritten forms, poor-quality scans, faded or historical documents, and mixed print and handwriting. It adds latency, so leave it off for clean, typed scans.

Enable blockOptions.text.signatureDetectionEnabled to identify handwritten signatures, initials, and signature blocks, such as the signature on page 3 of the invoice.

Step 5: keep tables and forms intact

  • Multi-page tables: blockOptions.tables.tableHeaderContinuationEnabled carries table headers across page breaks, so the line items on page 2 keep their column names.
  • Complex tables: set blockOptions.tables.targetFormat to "html" to preserve merged cells, row spans, and column spans; use "markdown" when the output feeds an LLM and the table is simple.
  • Forms and checkboxes: form regions are detected as key_value blocks and returned as ordered label and value pairs, including checkboxes and signatures. Turn on blockOptions.keyValue.structuredOutputEnabled to also get each form region as a tree of typed fields, with checkbox state (selected: true or false) and a bounding box per field.
  • Word-level positions: advancedOptions.returnOcr.words returns every word with its bounding box and an OCR confidence from 0 to 1.

The full request for the scanned invoice:

curl -X POST "https://api.extend.ai/parse" \
  -H "x-extend-api-version: 2026-02-09" \
  -H "Authorization: Bearer $EXTEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file": { "url": "https://example.com/scanned-invoice.pdf" },
    "config": {
      "engine": "parse_performance",
      "blockOptions": {
        "text": {
          "signatureDetectionEnabled": true,
          "agentic": { "enabled": true }
        },
        "tables": {
          "targetFormat": "html",
          "tableHeaderContinuationEnabled": true
        },
        "keyValue": { "structuredOutputEnabled": true }
      },
      "advancedOptions": {
        "pageRotationEnabled": true,
        "returnOcr": { "words": true }
      }
    }
  }'

The response is organized into chunks with formatted Markdown content and typed blocks (text, tables, figures, and form regions), each with its position on the page. That output can go straight into a search index or an agent's context.

Step 6: extract the fields you need, with citations

Parsing gives you the whole document. Most pipelines also need specific values in a fixed schema. Run Extract on the same file with a schema for the invoice: invoice number, PO number, invoice date, vendor, subtotal, tax, total, and an array of line items.

With citations enabled, extraction returns each value with its page, region, and the reference text it came from, plus confidence scores you can route on. For the invoice, the handwritten PO number comes back with a citation to the margin of page 1, so a reviewer can confirm it from the highlighted region instead of rereading the scan.

Step 7: route low-confidence values to review

Scans will always produce some values a person should check. Set a confidence threshold, auto-accept values above it, and send the rest to a human review step that shows the reviewer the cited region. Track which document classes produce the most reviews; that tells you where to turn on agentic correction or switch engines.

How to test scanned PDF parsing on your own documents

  1. Collect 50 to 100 real scans, including your worst: phone photos, faxes, skewed pages, handwriting, and long tables.
  2. Label the values that matter downstream.
  3. Run each candidate parser and score field-level accuracy, dropped pages, and table rows lost at page breaks.
  4. Compare cost per 1,000 pages including review time, not just the parsing price.

For a full framework, see how to evaluate document parsing APIs.

FAQ

How do you parse a scanned PDF?

Read every scanned page with OCR, correct page rotation, and use a layout-aware parser that keeps tables, form fields, checkboxes, and reading order. Turn on vision-model correction for handwriting and poor-quality scans, carry table headers across page breaks, and then extract the fields you need with citations and confidence scores so low-confidence values go to review. With Extend, one Parse request covers OCR, rotation, layout, and handwriting correction, and Extract runs on the same file.

What is the best API for parsing scanned PDFs?

Extend Parse is built for scanned PDFs in production. Its Performance engine handles lower-quality scans, handwriting, checkboxes, and complex tables; agentic OCR correction uses vision language models to fix low-confidence text; page rotation is corrected automatically; and the Auto engine routes each page to the right engine so clean pages stay cheap. Extend Performance Parse scored 95.7% field-level document Q&A accuracy on RealDoc-Bench, a benchmark of real-world regulated documents.

Why does OCR fail on scanned PDFs?

Scans add problems a digital PDF doesn't have: rotated or skewed pages, low resolution, faded text, handwriting, stamps over text, and tables that break across pages. Line-by-line OCR also loses layout, so table rows, form labels, and reading order come out scrambled. A layout-aware parser with vision-model correction and table header continuation recovers most of what plain OCR drops.

Should a scanned PDF be OCR'd if it already has a text layer?

It depends on the text layer. Many scanners add an OCR text layer that can be wrong. Extend's auto text extraction uses a PDF's embedded text where it's reliable and OCRs the rest; set it to OCR-only when the text layer is known to be unreliable or you want every page treated the same.

How much does it cost to parse scanned PDFs with Extend?

Extend Parse costs $5 per 1,000 pages on the Light engine and $20 per 1,000 pages on the Performance engine on pay-as-you-go, and the Auto engine bills each page by its complexity. New accounts start with 10,000 free credits and no contract or monthly minimum.

Sources

More guides

cta-background

( fig.11 )

Turn your documents into high quality data