OCR API: Image to Text & PDF to Text (Scanned PDFs) avatar

OCR API: Image to Text & PDF to Text (Scanned PDFs)

Pricing

from $3.00 / 1,000 pages

Go to Apify Store
OCR API: Image to Text & PDF to Text (Scanned PDFs)

OCR API: Image to Text & PDF to Text (Scanned PDFs)

Image to text and PDF to text with Tesseract OCR in 11 languages. Reads the PDF text layer first, OCR for scans. One row per page with text, confidence and line boxes. Errors are never charged.

Pricing

from $3.00 / 1,000 pages

Rating

0.0

(0)

Developer

Altronite

Altronite

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

a day ago

Last modified

Share

Extract text from images and PDFs with Tesseract OCR. Paste links to PNG, JPEG, WebP, TIFF, BMP or GIF images and to PDF files: image to text, PDF to text, and scanned PDF to text in 11 languages, one row per image or PDF page. PDFs that already contain text are read directly from the text layer, and OCR runs only on pages that need it, such as scans.

Errors are never charged. A broken link, a file that is not an image or PDF, a file that is too large, a password-protected PDF, an OCR failure or a page skipped by a limit gives an error row with the reason, free.

An image and a PDF in, one text row per image or page out

Quick start

Paste this input and run it. It reads Tesseract's own sample image and returns one row of text.

{
"sources": ["https://raw.githubusercontent.com/tesseract-ocr/tessdoc/main/images/eurotext.png"],
"languages": ["eng"],
"pdfMode": "auto",
"maxPagesPerPdf": 50,
"outputFormat": "text"
}

Then replace sources with your own public links to images and PDFs. Download the results from the run's dataset.

Who it's for

  • Finance and operations teams turning scanned invoices, receipts and forms into text.
  • Researchers and archivists digitising scanned documents and old print.
  • AI and automation builders who need text from images and PDFs for search, extraction or an LLM.
  • Developers who want OCR as an API without running Tesseract themselves.

Output

One row per image, and one row per PDF page:

FieldExample
statusok or error
sourceUrlthe link you gave
page, pageCount3, 12 for a PDF page; page is null for an image
methodtext-layer (read from the PDF) or ocr
languages["eng"]; empty for text-layer pages
textthe page text, lines in reading order, blank line between paragraphs
meanConfidencemean word confidence, 0 to 100 (OCR pages only)
wordCount, charCountsize of the text
linesonly with outputFormat: "lines": text, confidence and box per line
reason, erroron error rows only

An example row (text shortened, values illustrative):

{
"status": "ok",
"sourceUrl": "https://raw.githubusercontent.com/tesseract-ocr/tessdoc/main/images/eurotext.png",
"page": null,
"pageCount": 1,
"method": "ocr",
"languages": ["eng"],
"text": "Univers 55 Roman\n\nLorem ipsum dolor sit amet, magna consetetur\nsadipscing elitr, sed diam nonumy eirmod ...",
"meanConfidence": 92.4,
"wordCount": 118,
"charCount": 760,
"scrapedAt": "2026-10-14T08:30:12+00:00"
}

With outputFormat: "lines" each OK row also has lines, for example {"text": "Univers 55 Roman", "confidence": 95.0, "bbox": [12, 18, 326, 36]}. bbox is [left, top, width, height] in pixels of the original image. Lines from a PDF text layer have confidence and bbox set to null.

An error row looks like this:

{ "status": "error", "sourceUrl": "https://example.com/missing.png", "page": null, "reason": "download_failed", "error": "The server answered 404.", "input": "https://example.com/missing.png", "scrapedAt": "2026-10-14T08:30:12+00:00" }

Reasons: invalid_url, blocked_url, download_failed, too_large, unsupported_type, ocr_failed, time_limit, page_limit.

Input

FieldDefaultWhat it does
sourcesrequiredPublic http(s) links to images (PNG, JPEG, WebP, TIFF, BMP, GIF) or PDFs, up to 50 MB each and 1,000 per run. Duplicates are merged; a missing scheme becomes https://. File type is detected from the bytes, not from the link or Content-Type.
languages["eng"]Up to 3 of eng, hin, spa, fra, deu, por, ita, ara, rus, chi_sim, jpn. List every language on the page.
pdfModeautoauto: text layer where a page has at least 10 letters or digits, OCR otherwise. ocr: OCR every page. text: text layer only, no OCR.
maxPagesPerPdf501 to 500. Longer PDFs are cut; the rest is one uncharged page_limit row.
outputFormattextlines adds a lines array: text, confidence and bbox [left, top, width, height] in pixels.

More examples:

Scanned PDFs, forced OCR, English and Hindi:

{ "sources": ["https://example.com/scan.pdf"], "languages": ["eng", "hin"], "pdfMode": "ocr" }

Text layer only, for digital PDFs where you want the exact embedded text:

{ "sources": ["https://example.com/report.pdf"], "pdfMode": "text", "maxPagesPerPdf": 500 }

Line positions for downstream processing:

{ "sources": ["https://example.com/receipt.jpg"], "outputFormat": "lines" }

Use it from code or an AI agent

Run it with the Apify API, the Apify Python or JavaScript clients, or as a tool through the Apify MCP server. Pass the same input JSON through any of these. Check status on each row: ok rows have text, error rows say why not.

Minimal input:

{ "sources": ["https://example.com/scan.pdf"] }

Pricing

Pay per event. You pay for two things:

EventPriceWhen
page$0.003 per pageeach image, and each PDF page, delivered with status ok
apify-actor-start$0.001 per runonce per run, one event per GB of memory with a 1 GB minimum

Examples:

  • One image: $0.003 + $0.001 = $0.004.
  • A 10-page PDF, all pages delivered: 10 x $0.003 + $0.001 = $0.031.
  • 200 single-page images: 200 x $0.003 + $0.001 = $0.601.
  • A 120-page PDF with the default maxPagesPerPdf 50: 50 x $0.003 + $0.001 = $0.151; the remaining pages become one uncharged page_limit row.

Not charged: invalid and blocked links, failed downloads, files over 50 MB, unsupported or password-protected files, OCR failures, pages skipped by the time limit, and the page_limit row. A page with no text on it is still a delivered page and is charged; filter on wordCount afterwards. Reading the PDF text layer (pdfMode: text or auto on a digital PDF) is charged per page like OCR. Prices were read from the Store on 21 Oct 2026; the Pricing tab is the source of truth.

How it works

  • Images are converted to grayscale, contrast is adjusted and small images are enlarged before OCR. Transparent PNGs are placed on a white background.
  • PDFs are read with PDFium. In auto mode a page with at least 10 letters or digits in its text layer is read directly. Other pages are rendered at about 300 DPI and sent to OCR.
  • OCR is Tesseract with one OpenMP thread per process. Pages run in parallel instead.
  • Downloads accept public internet hosts only. Private, loopback, link-local and cloud metadata addresses are refused, redirects are checked at every step (at most 5), and links with embedded credentials are refused.
  • Rows are delivered as pages finish, so a run that reaches its time limit keeps the pages it completed and marks the rest time_limit, uncharged.

Limits

  • Up to 50 MB per file and 1,000 sources per run.
  • Up to 500 pages per PDF (default 50; raise maxPagesPerPdf).
  • 11 languages, up to 3 per run.
  • Public links only. No logins, cookies or custom headers.
  • Password-protected and damaged PDFs return an error row.
  • Handwriting, very low resolution scans and heavily stylised fonts give low meanConfidence. Check it before trusting the text.
  • No layout output beyond lines. Tables come out as lines of text, not cells.
  • Memory defaults to 1 GB and goes up to 4 GB. Raise it for very large page images.

Troubleshooting

reasonMessageFix
invalid_url"Not an http(s) URL with a valid host name." / "URLs with embedded credentials are not supported."Use a plain public http(s) link.
blocked_urlLink points to a private, loopback or internal addressOnly public internet hosts are fetched.
download_failed"The server answered 404." / "Too many redirects (more than 5)." / "The connection failed (...)" / "The host name ... could not be resolved."Check the link opens in a browser without login. 429 and 5xx are retried once.
too_large"The file is N MB; the limit is 50 MB." / "The image has too many pixels to process."Split or downscale the file.
unsupported_type"Not a supported file: expected a PDF or a PNG, JPEG, WebP, TIFF, BMP or GIF image." / "The PDF is password-protected." / "The PDF is damaged or not a readable PDF." / "The image could not be decoded (corrupt or unsupported)."Check the file; a web page answering with an HTML error is rejected even if the link ends in .png.
ocr_failed"OCR failed or timed out (...)." / "Unexpected error (...)."Run again; if it repeats on one page, open an issue with the link.
time_limit"The run reached its time limit before this page ..."Raise the run timeout or split the list. Finished pages are kept.
page_limit"The PDF has N pages; only the first M were processed (maxPagesPerPdf)."Raise maxPagesPerPdf (up to 500).
Low meanConfidenceHandwriting, low resolution or stylised fontsProvide a sharper scan and list every language present.
Run fails with "unsupported language ..."A language code is not in the supported listUse only the codes listed above.

FAQ

How do I extract text from a scanned PDF? Pass the PDF link in sources. In the default auto mode each page without a text layer is OCRed, and you get one row per page.

How do I convert a PDF to text without OCR? Set pdfMode to text. It reads the embedded text layer only and never runs OCR. Pages with no text layer come back with empty text and are still charged as delivered pages.

Does it OCR PDFs that already have text? Not in auto mode. It reads the embedded text directly. Set pdfMode to ocr to force OCR on every page, for example when the embedded text is wrong.

Which languages are supported? English, Hindi, Spanish, French, German, Portuguese, Italian, Arabic, Russian, Simplified Chinese and Japanese. Pick up to 3 per run.

What does meanConfidence mean? The mean of Tesseract's confidence for each recognised word, from 0 to 100. It is set on OCR pages only. Low values usually mean the text has mistakes, so check it before trusting the text.

Can it read handwriting? Handwriting usually gives low meanConfidence, so check it; see Limits.

Why did my image return unsupported_type? The file is not a PDF or a PNG, JPEG, WebP, TIFF, BMP or GIF image, or it is corrupt. The type is read from the file's bytes, so a web page that answers with an HTML error page is rejected even if the link ends in .png.

Can I send a file instead of a link? Not directly. Put the file somewhere reachable by a public link, for example a public Apify key-value store record, and pass that link.

Support

Is a file not reading correctly? Open an issue on the Issues tab with the link and your input.