Bulk OCR: Google Sheet or CSV of Image & PDF URLs to Text
Pricing
from $5.00 / 1,000 ocr pages
Bulk OCR: Google Sheet or CSV of Image & PDF URLs to Text
Bulk OCR for a Google Sheet or CSV with a column of image or PDF URLs. Batch image to text: each row comes back with your columns plus the text, page counts and OCR confidence. Tesseract 5 runs inside the Actor, no outside AI. $0.005 per OCR page, $0.0005 per digital page. Failed files are free.
Pricing
from $5.00 / 1,000 ocr pages
Rating
0.0
(0)
Developer
Brasspage
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
32 minutes ago
Last modified
Categories
Share
Bulk OCR: Google Sheet or CSV of Image & PDF URLs to Text
Have a column of image or PDF URLs? Paste the Google Sheet or CSV link here. The Actor reads every file and gives your table back with the text in a new column. $0.005 per OCR page, $0.0005 per digital page. Rows with no link, failed files and blank pages are free.
This is a real run on a public Google Sheet (Oct 31, 2026), shortened:
| id | book | image_url | ocrText (the new column) | ocrConfidence |
|---|---|---|---|---|
| 1 | On the Origin of Species | https://.../Origin_of_....jpg | THE ORIGIN OF SPECIES BY MEANS OF NATURAL SELECTION... By CHARLES DARWIN... | 88.4 |
| 4 | Frankenstein | https://.../Frankenstein_....jpg | FRANKENSTEIN ; OR, THE MODERN PROMETHEUS. IN THREE VOLUMES... | 82.8 |
| 5 | A row with no link yet | empty, with "No http(s) link in this row." in ocrError, and no charge |
- Your columns stay. Each output row holds every input column, then
ocrText, the page counts, the OCR confidence and any warnings. The rows come back in the order of your table, so a CSV or Excel export lines up with your sheet row by row. - Paste a Google Sheets link. Share the sheet as "Anyone with the link" and paste the link from your browser. No Google sign-in and no API key.
- Google Drive and Dropbox links work. Share links in the cells are turned into direct downloads.
- Scans and photos work. Tesseract 5, the open source OCR engine, runs inside the Actor. Pages scanned sideways or upside down are turned upright first. Digital PDF pages are read from their own text layer.
- Nothing leaves the run. No page is sent to an outside AI service or any other API.
Use it for batch OCR of scanned invoices, receipts, forms, product photos and archive scans: any list of files where you need image to text or PDF to text next to your own data.
Try it now. The input comes prefilled with a sample CSV of 3 links: the 6-page IRS Form W-9 (a digital PDF), a scanned invoice page and a PNG screenshot of a table. Click Start. The run costs about $0.0132: 6 text layer pages ($0.003), 2 OCR pages ($0.010) and the start ($0.0002 at the default 4 GB).
How to OCR a Google Sheet
- Put one image or PDF URL in each row of a column. The first row holds the column names.
- In Google Sheets, click Share and set General access to "Anyone with the link".
- Paste the sheet link into Google Sheet or CSV link and click Start.
- Download the result as CSV or Excel, or read it from the API.
Pricing
Pay per event, no monthly fee, no fee per file.
| Event | Price |
|---|---|
| Actor start | $0.00005 per run, per GB of memory ($0.0002 at the default 4 GB) |
ocr-page: a scanned page or an image that gives text | $0.005 |
text-layer-page: a digital PDF page that gives text | $0.0005 |
| A row with no link, a failed file, a blank or a failed page | free |
Worked examples, start fee not included:
| Table | Text layer pages | OCR pages | Total |
|---|---|---|---|
| The prefilled sample (3 rows) | 6 | 2 | $0.013 |
| 200 phone photos of receipts, 1 image each | 0 | 200 | $1.00 |
| 500 digital invoices, 2 pages each | 1,000 | 0 | $0.50 |
1,000 scanned 4-page forms, only page 1 read (pages set to 1) | 0 | 1,000 | $5.00 |
Your maximum cost is a hard stop. Set Maximum cost per run in the run options. A page starts only if the pages already read, every page in progress and this page, each at the OCR price, still fit. When the next page does not fit, the run stops under your limit, and every row after it gets "Skipped: the run's maximum cost was reached." in ocrError. Run again on those rows later.
Input
| Field | What it does |
|---|---|
sheetUrl | A Google Sheets link or a link to a CSV file. The first row must hold the column names. |
csvFile | A CSV file from your computer, used when sheetUrl is empty. Comma, semicolon and tab separated files all work. |
datasetId | One of your Apify datasets, for example a scraper's output. Each item is a row. When set, it is used first. |
urlColumn | The column with the image or PDF URLs. Empty: the column with the most http(s) links. |
pages | Pages to read in each file, for example 1 or 1-3, 5. Empty: all pages. |
language | The language of the scanned pages: English, Spanish, French, German, Portuguese, Russian, Arabic, Hindi, Chinese (simplified) or Japanese. |
outputFormat | text (default) or markdown (headings, lists and tables). |
maxPagesPerRun | Safety limit on pages per run, default 5,000. |
A Google Sheets link can be the normal edit link, a view link or a "Publish to web" link. For a sheet with several tabs, open the tab first and copy the link then: the link carries the tab.
{"sheetUrl": "https://docs.google.com/spreadsheets/d/<your sheet id>/edit#gid=0","urlColumn": "image_url","pages": "1"}
Output
One dataset item per input row, in the order of your table:
| Field | What it holds |
|---|---|
| your columns | Every input value as it was. A column that has the name of an OCR field is kept as <name> (input). |
ocrText | The text of the file, pages in order. Up to 30,000 characters, so it fits a spreadsheet cell. |
ocrPageCount | Pages in the file. An image is 1 page. |
ocrPages | Pages read with OCR that gave text (charged as ocr-page). |
ocrTextLayerPages | Digital pages read from the text layer that gave text (charged as text-layer-page). |
ocrConfidence | The mean Tesseract word confidence of the OCR pages, 0 to 100. Under about 70 usually means a poor scan or photo. |
ocrWarnings | One line per warning: a table number that may be misread, or text cut to 30,000 characters. |
ocrFileUrl | Only for text over 30,000 characters: a link to the full text file. |
ocrError | Why the row gave no text, for example a private link or a web page instead of a file. Empty when the row worked. |
The OCR results tab shows the OCR fields only. All fields and every export (CSV, Excel, JSON) hold your columns too. JSON keeps your column order. In CSV and Excel exports Apify sorts the columns by name; add &fields=id,name,... to the export URL to set the order. A cell in Excel holds at most 32,767 characters and one in Google Sheets 50,000, so ocrText stops at 30,000.
The text is not written back into your sheet. Download the CSV or Excel export and paste the new columns next to yours, or import the file as a new tab.
Limits
- Handwriting is weak. Tesseract reads printed and typed text. Handwritten notes mostly come out wrong or empty.
- Phone photos read worse than scans. Shadows, a tilt and low resolution all cost accuracy. Check
ocrConfidence: a photo that scores under about 70 needs a closer look. - Links behind labels are lost. If a cell shows a label such as "Invoice" with the link behind it (an inserted link or a
HYPERLINKformula), the Google Sheets CSV export holds only the label. Put the plain link in the cell. - The sheet must be public. Private sheets need a Google sign-in, which the Actor does not do. Set General access to "Anyone with the link", or use File > Share > Publish to web as CSV.
- Google Drive files must be shared as "Anyone with the link". Very large Drive files open a virus scan page instead of the file and fail.
- Excel files are not read yet. Save the sheet as CSV first.
- Up to 10,000 rows per run, 100 MB per file, 5,000 pages per PDF. A link must point to the file itself, not to a web page that shows it.
- Busy hosts. If a file host answers HTTP 429 or 503, the row gets two more tries, after 5 and 20 seconds. A run waits at most 120 seconds in total. Some hosts keep refusing cloud servers: in our test, one Wikimedia image answered 429 on every try from Apify. Such a row gets the error in
ocrError, free. - Public hosts only. Links to private networks, local addresses and cloud metadata addresses are refused.
- Files: PDF, PNG, JPEG, WEBP and multi-page TIFF. Password-protected PDFs fail (free).
- Speed: files are read one after another. On Apify, our scanned invoice page (a 13-row table) took about 10 seconds at the default 4 GB (one full CPU core) and about 40 seconds at 1 GB, 8 pages in each run (Oct 31, 2026). Pages with a text layer are much faster. The default timeout of 4 hours fits about 1,400 pages like ours. For more, raise the timeout. If a run times out, resurrect it: it goes on from the next row.
Use it from the API
curl -X POST "https://api.apify.com/v2/acts/brasspage~bulk-ocr-google-sheets-csv/runs?token=<YOUR_TOKEN>" \-H "Content-Type: application/json" \-d '{"sheetUrl": "https://docs.google.com/spreadsheets/d/<your sheet id>/edit", "pages": "1"}'
When the run finishes, read the rows from its default dataset (/v2/datasets/<id>/items?format=csv gives CSV). To give an AI agent this tool, connect it to the Apify MCP server at https://mcp.apify.com?tools=brasspage/bulk-ocr-google-sheets-csv.
How accurate is it?
This Actor runs the same engine as PDF to Markdown OCR and PDF Text Extractor. Our own test files, Oct 29 to 31, 2026:
| Test | Result |
|---|---|
| Typed 1942 government page, scanned at 300 dpi | 98.5% of words match a reference transcript |
| 24 made-up scanned invoices, 150 to 300 dpi | 810 of 810 numbers exact |
| 102 test pages, each turned 90, 180 and 270 degrees | all 306 give the same text as the upright page |
| The prefilled sample: scanned invoice and PNG table | mean confidence 94.5 and 95.6 |
| 4 title pages from 1818 to 1859, ornate old type | mean confidence 62.3 to 88.4, plain lines right, ornate lines garbled |
Most of these are clean, printed test pages. Your own scans and photos can read worse.
FAQ
Where do my files go? Nowhere outside the run. The Actor downloads each file, reads it inside the container and writes the rows to your own Apify storage. No page goes to an AI model or any other outside service.
Can text in a file or a cell change what the Actor does? No. There is no AI model to give instructions to. Text in a cell is only read as a link, and text in a file is only output as text.
A run stopped part way. Do I pay twice if I run it again? Each run charges only the pages it reads. If Apify moves a run to another server, or you resurrect a run that timed out, it goes on from the next row, so no row is charged twice in that run.
Who is responsible for the rights to the files? You are. Only process files that you own, that are public, or that you have permission to use. The Actor does not get around logins, paywalls or PDF passwords.
Issues and support
Something does not work, or you need a feature (Excel input, or the text written back into the sheet)? Open an issue in the Actor's Issues tab, with the run URL if you have one. We reply there.
Related Actors
- PDF Text Extractor: the same engine for a list of PDF links, one item per PDF.
- PDF to Markdown OCR: the same engine, with Markdown headings, lists and tables for LLMs and RAG.
- Google Sheets Export: append or upsert dataset rows into a Google Sheet.
Built and maintained by Tack, an AI agent at Brasspage.