Bulk OCR: Image & Scanned PDF to Text from CSV or Google Sheet avatar

Bulk OCR: Image & Scanned PDF to Text from CSV or Google Sheet

Pricing

from $3.50 / 1,000 ocr pages

Go to Apify Store
Bulk OCR: Image & Scanned PDF to Text from CSV or Google Sheet

Bulk OCR: Image & Scanned PDF to Text from CSV or Google Sheet

OCR every image and scanned PDF linked in an Apify dataset, CSV, Excel or Google Sheet, keeping your columns. Inputs: datasetId or fileUrl or fileUrls, urlField, languages. Adds text, confidence and page counts. Tesseract inside the run, no outside service. Charged per page. Agent-ready: x402, MCP.

Pricing

from $3.50 / 1,000 ocr pages

Rating

0.0

(0)

Developer

Adam Pearce

Adam Pearce

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Bulk OCR: text out of every image and scanned PDF in your list

Got a spreadsheet of links to receipts, scanned letters, invoices, screenshots, forms or product photos, and no way to get the words in them into a column?

Point this Actor at an Apify dataset, a CSV or Excel file, or a Google Sheet. For every row it downloads the image or PDF, recognises the text, and hands you back every original column with the text, a confidence score and page counts added alongside. No retyping, no copying out of a viewer, no re-joining results to your own data afterwards.

Every other OCR Actor on the Store takes a typed-in list of image URLs and gives you back a bare list of text. If your links live in a spreadsheet, you have to pull the column out, paste it in, and stitch the answers back together by hand. This one takes the whole sheet, and it takes scanned PDFs as well as images.

What you get per file

FieldWhat it is
textEverything recognised, in reading order, pages separated by a blank line
confidenceThe engine's average confidence in the words it read, 0 to 100
lowConfidenceTrue when that average is under 60, so a bad scan cannot pass as a good one
fileTypeWhat the file really was: pdf, png, jpeg, webp, gif, bmp or tiff
pageCount, pagesRead, pagesTruncatedHow big the file was and whether the per-file cap cut it
ocrPages, textLayerPages, blankPagesHow each page was read, which is also what you were charged for
wordCount, charCountSize of what came back
ocrStatus, statusDetailWhat happened, in plain English, when it did not work
languages, fileSizeKb, resolvedUrl, ocrMsThe settings and facts behind the row
pagesOptional: each page's text, method and confidence separately

Plus every column that was already in your row.

How it reads

  • Images (PNG, JPEG, WebP, GIF, BMP, TIFF) are flattened onto white, enlarged when they are small (small text reads far better doubled) and capped at 4,000 pixels on the longest side, then recognised.
  • Scanned PDFs are rendered page by page at the resolution you choose (200 dpi by default) and recognised page by page, up to your per-file page cap.
  • Born-digital PDFs already contain their text. Those pages are copied exactly rather than recognised, at a fifth of the price, unless you switch usePdfTextLayer off. A mixed document gets the right treatment page by page.

The engine is Tesseract, the open-source OCR engine, running as WebAssembly inside the run. No outside OCR service, no API key, and no third party ever sees your files.

The honest limit

OCR is not magic. Tesseract reads clean scans, screenshots, receipts and printed documents well. It reads photographs of documents less well, small or decorative type worse, and handwriting badly. Rather than hide that, every file carries its confidence, files under 60 are flagged lowConfidence, and the run summary counts them. When results disappoint:

  • set Languages to the document's language (the single biggest factor; English is built in, 100+ others download once at the start of the run),
  • raise PDF render resolution to 300 for small print,
  • switch Page layout to Sparse for screenshots, slides and product photos, or Single column for narrow receipts,
  • use Minimum word confidence to drop the engine's guesses and keep only what it is sure of.

What it costs

  • $0.005 per page read by OCR (an image is one page). A page that produced no words at all is free.
  • $0.001 per PDF page copied from its own text layer.
  • $0.01 per export file, $0.02 per webhook delivery.
  • Bronze, Silver and Gold Store discounts apply from day one.

Never charged: unreachable links, 404s, bot-blocked downloads, HTML pages, HEIC or SVG files, corrupt or password-protected PDFs, files over your size limit, blank cells, and blank pages.

  • 1,000 receipt photos a month: $5.00
  • 200 scanned contracts of 10 pages: $10.00
  • A nightly run over 50 new scanned delivery notes: about $7.50 a month

maxPagesPerFile (default 20) is your ceiling per document: a 300-page scan cannot run up a bill you did not expect.

Inputs

Give it any one of these:

  • Dataset picked from your account, for example a scraper's output with a photo column
  • File or Google Sheet URL: CSV, TSV, Excel, JSON or JSON Lines. A normal Google Sheets link works, shared as "Anyone with the link can view"
  • Image or PDF URLs: a plain list, for a quick one-off
  • Rows: inline JSON

The link column is detected automatically, preferring a column whose values end in .jpg, .png or .pdf over one merely named url. Set urlField if you would rather be explicit. Google Drive and Dropbox share links are converted to direct downloads.

Useful options: languages, dpi, pageSegmentation, maxPagesPerFile, minWordConfidence, includePageText for per-page text you can cite a page from, keep: "problems" to find every broken link in a large list, and keep: "no_text" to find the blank or unreadable files.

Speed

Measured on Apify at the default 2 GB of memory: a receipt or screenshot image takes about 1 to 2 seconds, a scanned A4 page rendered at 200 dpi about 2 to 3 seconds (roughly double at 300 dpi), and a born-digital PDF page copied from its text layer well under a tenth of a second. The default example (four files, four OCR pages, six text-layer pages) finishes in about 8 seconds including start-up. Two files are read at once by default; raise memory before raising concurrency, since each slot runs its own engine.

Exports and pipelines

  • exportFormats writes a real downloadable CSV or Excel file. Per-page text is JSON-encoded into a single cell so it fits a spreadsheet.
  • outputDatasetName appends every run into one named dataset, building a growing text archive. Not charged again.
  • webhookUrl POSTs the run summary to Slack, Zapier, Make, n8n or your own API the moment the run finishes. Charged only on a confirmed 2xx.

FAQ

Does it handle PDFs that already have text? Yes. Those pages are copied from the text layer at the low rate. If all your PDFs are born-digital and you want tables rebuilt too, Dataset PDF Extract is the better tool; it flags the scans it cannot read, and this Actor is where you send them.

Which languages? Any Tesseract language: eng, deu, fra, spa, por, ita, nld, pol, rus, ukr, tur, jpn, kor, chi_sim, chi_tra, ara, hin and about a hundred more. List several for mixed documents. Only English ships inside the Actor; others are fetched once when the run starts.

Handwriting? Expect poor results. Tesseract is a print engine. The confidence score will tell you.

HEIC photos from an iPhone? Not supported, and reported as such without charge. Convert to JPEG first.

Can it read a photo of a receipt? Usually, if the photo is sharp, flat and well lit. Check confidence; try pageSegmentation: "single_column" for narrow receipts.

Can I feed the text straight into an LLM? Yes. Pair it with Dataset AI Enrich to turn the recognised text into typed columns (total, date, supplier) with one plain-English instruction.

Does filtering make a run cheaper? No. The file has to be fetched and read before we know whether it matches, so keep changes what is written, not what is charged.

Is my data safe? The Actor reads the files you point it at and writes the results to your own dataset. Recognition happens inside the run; nothing is sent to an OCR service. If you set a webhook, the run summary goes to the URL you chose and nowhere else.

The rest of the toolkit

Sibling Actors that fit together as a pipeline:

Notes

Recognition uses tesseract.js (Apache-2.0), PDF pages are rendered by Mozilla's pdf.js (Apache-2.0) through unpdf (MIT), and images are decoded by @napi-rs/canvas (MIT). The sample files in the default input are synthetic documents made for this Actor; no real people or businesses.

If this saved you retyping a pile of scans, a review on the Apify Store helps a lot. Found a file it read badly? Open an issue with the link and I will look at it.