Scanned PDF OCR to Page Text avatar

Scanned PDF OCR to Page Text

Pricing

from $2.28 / 1,000 ocr page with texts

Go to Apify Store
Scanned PDF OCR to Page Text

Scanned PDF OCR to Page Text

Recognize English text from public scanned PDFs and export page-numbered OCR text, language, status and document provenance for indexing.

Pricing

from $2.28 / 1,000 ocr page with texts

Rating

0.0

(0)

Developer

Automation Lab

Automation Lab

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

Categories

Share

Turn image-only PDF pages into searchable English text. This scanned PDF OCR Actor downloads anonymous public PDF URLs, renders pages with PDFium and recognizes text locally with Tesseract. It returns one row per processed page, with page number, source URL, document hash, language model and status.

Use it for recurring document indexing, searchable archives and RAG ingestion. No external OCR account or AI subscription is needed. It does not create searchable PDF files or edit the original documents.

Who is it for?

  • Search engineers indexing scanned manuals and reports.
  • Archive operators importing recurring public document collections.
  • Automation builders who need page-level provenance alongside recognized text.

Why use it?

Text-layer extractors cannot read a scan that contains only page images. This Actor actually renders and recognizes those pages. Document hashes let your downstream pipeline identify changed source bytes. Explicit blank and failure rows distinguish an empty page from a download failure.

The output is plain OCR text, not a promise of perfect layout, transcription accuracy, proofreading or table reconstruction.

Getting started

  1. Supply a direct public PDF URL under Public PDF URLs.
  2. Choose a global output-record cap and a page cap per PDF.
  3. Start the Actor and wait for completion.
  4. Open OCR pages in the output dataset.
  5. Export JSON, CSV or Excel using Apify dataset exports.

Example input (a public scanned product brochure used by the OCRmyPDF test suite):

{
"startUrls": [{"url": "https://raw.githubusercontent.com/ocrmypdf/OCRmyPDF/main/tests/resources/linn.pdf"}],
"maxItems": 20,
"maxPagesPerDocument": 10
}

The example PDF has one page; output volume follows the actual source, not the requested cap.

Inputs and limits

InputDefaultMeaning
startUrlsRequired1–20 unique anonymous HTTP(S) PDF URLs
maxItems20Global dataset-row cap, 1–200; includes blank/error rows
maxPagesPerDocument10First 1–50 pages of each PDF

Documents and pages are processed sequentially in input order. Both limits apply together. Later pages or documents are intentionally skipped when either cap is reached. There is no zero/unlimited setting. Runtime and spending limits can stop collection earlier; inspect the completion counters in the run log.

Each URL entry accepts only url and optional method: "GET". Other methods, headers, payload and userData are rejected rather than silently ignored.

Each PDF is limited to 20 MB. Responses must have PDF or binary content type and start with the PDF signature. At most five redirects are followed, with public-destination checks at every hop. Transient transfers receive at most two retries; permanent access errors are not retried. Each transfer has a 30-second deadline. Page rendering and OCR have a 90-second parent deadline, including a 60-second OCR deadline.

Pages are rasterized at up to 200 DPI, with the longest side capped at 2500 pixels. PDF page dimensions above 14,400 points are rejected. These bounds control resource use but may lose small-print detail.

Extracted data

FieldMeaning
sourceUrlOriginal supplied PDF URL
documentIndexOne-based input position
documentSha256Hash of downloaded PDF bytes; null before download succeeds
pageNumberOne-based PDF page; null for document errors
pageCountFull source page count, including pages skipped by limits
textRecognized page text; null on blank or failed pages
languageAlways eng, the OCR model; not detected language
statussucceeded, no_text or failed
errorBounded explanation on failure, otherwise null
processedAtUTC processing timestamp

The default dataset contains all output. A document download/parse error produces one diagnostic row with no page number. A blank page produces no_text. Mixed batches retain successful results; a run with failures and no useful page fails instead of pretending extraction succeeded. An entirely blank, valid document can complete with only no_text rows.

Output example

The example PDF begins with this recognized text (abbreviated here; the dataset retains the full OCR text):

{
"sourceUrl": "https://raw.githubusercontent.com/ocrmypdf/OCRmyPDF/main/tests/resources/linn.pdf",
"documentIndex": 1,
"pageNumber": 1,
"pageCount": 1,
"language": "eng",
"status": "succeeded",
"text": "The LinnSequencer\n32 Track MIDI Sequence Recorder",
"error": null
}

Production rows also include the document hash and processing timestamp described above.

How much does it cost to recognize scanned PDF pages?

Pay-per-event pricing includes one start event per run and one item event per page that produces nonempty OCR text. Blank and failed pages have no item charge; the start fee still applies. Spending caps are checked before work and before accepting each paid page. A capped run may return only partial results.

The start fee is $0.001 per run. Per nonempty OCR page: FREE $0.00437; BRONZE $0.0038; SILVER $0.002964; GOLD, PLATINUM and DIAMOND $0.00228. Spend tiers follow qualifying aggregate monthly Apify Store spend, not the number of pages in this Actor.

BRONZE estimated run totals (start fee included): $0.0048 for 1 useful page; $0.039 for 10; $0.381 for 100. Blank/error diagnostic rows add no per-page fee. These examples assume completed useful output and no spending-cap interruption.

Integrations

  • RAG ingestion: store documentSha256, pageNumber and sourceUrl beside chunks in your vector database.
  • Search indexes: index only rows whose status is succeeded; route failure rows to an operational queue.
  • n8n and Make: schedule the same public URLs, fetch the default dataset after completion, then deduplicate hashes downstream.
  • Spreadsheets: export page text and statuses to CSV or Excel for review.

Scheduling is supplied by Apify or your orchestration system. This Actor does not discover new PDFs, compare past runs, monitor changes or send alerts itself.

API usage

Start a run once, retain the returned run and dataset IDs, and retrieve results after successful completion. Do not restart a run just to check its status.

curl -X POST 'https://api.apify.com/v2/acts/automation-lab~scanned-pdf-ocr-text/runs' \
-H "Authorization: Bearer $APIFY_TOKEN" -H 'Content-Type: application/json' \
-d '{"startUrls":[{"url":"https://example.org/scan.pdf"}],"maxItems":20}'

JavaScript with apify-client:

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/scanned-pdf-ocr-text').call({
startUrls: [{ url: 'https://example.org/scan.pdf' }], maxItems: 20
});
const { items } = await client.dataset(run.defaultDatasetId).listItems({ limit: 20 });

Python with apify-client:

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/scanned-pdf-ocr-text').call(
run_input={'startUrls': [{'url': 'https://example.org/scan.pdf'}], 'maxItems': 20})
items = client.dataset(run['defaultDatasetId']).list_items(limit=20).items

Replace the illustrative URL with a real public PDF you are permitted to process. Import ApifyClient from apify-client in your JavaScript application.

MCP use

Use the stable Actor-specific hosted endpoint:

$claude mcp add --transport http apify "https://mcp.apify.com?tools=automation-lab/scanned-pdf-ocr-text"

Claude Desktop and Cursor: use this configuration in an HTTP-compatible MCP client. VS Code: add the same Actor URL under its MCP HTTP server configuration.

Equivalent configuration for compatible HTTP clients:

{"mcpServers":{"apify":{"url":"https://mcp.apify.com?tools=automation-lab/scanned-pdf-ocr-text"}}}

Authenticate using your client's supported Apify authorization flow. Discover actual tool names and argument schemas with tools/list; selecting an Actor also exposes run and storage tools, not exactly one tool.

Example prompts: “Recognize the first page of this public scan” or “Export page text with source provenance.”

Example request: “Read the first two scanned pages from this public PDF and return the text with page provenance.” Only execute after authorizing the invocation. Start once and keep its run ID. If nonterminal, check that same run with bounded backoff (2, 4, 8 seconds, capped at 10) and a 120-second consumer deadline. On deadline report pending, not success; never restart just to poll.

After success, retrieve dataset pages with explicit offset, limit and required fields. An example consumer budget is 20 rows per page, at most 100 source rows and 64 KiB serialized UTF-8 content admitted to model context. Enforce bytes host-side and disclose omitted/oversized content. Without interception do not claim a hard byte guarantee. Report continuation offset and truncation; keep full exports outside model context. Run/storage IDs are metadata, not OCR results. No universal token-saving claim is made.

Accuracy and limitations

English machine-printed text is supported. Handwriting, poor contrast, rotation, damaged scans, dense tables, columns, small print and unusual fonts may reduce accuracy or change reading order. No confidence score, bounding boxes, translation, detected language, tables, Markdown, DOCX or searchable PDF artifact is produced.

Digital PDFs are rasterized and OCRed too, rather than using their text layer. For precise existing text-layer extraction use our related PDF Text Extractor. Password-protected/encrypted files and private destinations are unsupported. No proxy, login, cookies, authenticated URLs or upload mode is provided.

Legality and responsible use

Only process documents you are authorized to download and analyze. Public availability does not grant permission to republish copyrighted text or personal information. You control dataset access and retention in Apify.

PDF bytes and page images are temporary and removed after each document. OCR runs locally inside the Actor; no external recognition API receives page content. Failed operations send sanitized diagnostic input, exceptions and actor/build/run IDs to our private GlitchTip service for repair; secret fields and URL queries are removed and reports are retained for 30 days. Source URL inputs are additionally redacted from telemetry. Your dataset still contains supplied source URLs and extracted text.

FAQ and troubleshooting

Why did it return no text? A valid blank page returns no_text; a low-quality or non-English scan may also have no recognizable English text. Inspect the original scan before interpreting empty output as missing content.

Why did downloading fail? Use a direct anonymous PDF URL, not a sign-in page or viewer. Check the 20 MB limit, MIME type, encryption and public-address requirements. Protected sites are not bypassed automatically.

Why are pages missing? Check both input caps, spending cap and runtime. Compare the returned pageCount with processed pageNumber values. Partial output is not a claim of full-document completion.

Can I edit or proofread a PDF? No. The Actor produces machine-recognized plain text and provenance, not a human-guaranteed transcription or redesigned document.

  • PDF Text Extractor: extract a PDF's existing text layer instead of recognizing its page images.
  • Batch Image Text OCR: use image inputs and richer block output rather than native PDF page ingestion.