PDF to Markdown OCR Converter: Scanned PDFs & Images to Text
Pricing
from $6.00 / 1,000 page converteds
PDF to Markdown OCR Converter: Scanned PDFs & Images to Text
PDF to Markdown OCR converter and API for LLMs, RAG and AI agents. Convert scanned PDF to text and images (PNG, JPG, WEBP, TIFF) to Markdown. Open source Tesseract OCR runs inside the Actor, so your documents go to no LLM or outside API. Markdown tables, one entry per page. $0.006 per page.
Pricing
from $6.00 / 1,000 page converteds
Rating
0.0
(0)
Developer
Brasspage
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
2 hours ago
Last modified
Categories
Security
Limited permissionsShare
PDF to Markdown OCR Converter and API: Scanned PDF to Text & Image to Markdown
Turn scanned PDFs, digital PDFs and images into clean Markdown for LLMs, RAG and AI agents. Tables stay tables.
$0.006 per page, scanned or digital. Plus $0.00005 per run start, per GB of memory. No monthly fee. Blank pages and failed pages are free.
| Good at (our benches, made-up test files) | Result |
|---|---|
| Scanned invoices, 24 pages, 4 fonts | 810 of 810 numbers |
| Scanned tables with no grid lines, 134 new tables | 74% of cells right, was 45% |
| Digital PDF tables with no grid lines, 67 new tables | 86% of cells right, was 47% |
Weak at: handwriting and phone photos. On real photos from public test sets, it found 81% of the words on whole pages, 67% on receipts and 52% on handwritten notes. Flat book scans: 92%.
Open source OCR runs inside the Actor (Tesseract, plus RapidOCR for pages that Tesseract reads badly), so your documents go to no LLM or outside API. Use it in the Apify Console, or call it as a PDF OCR API from your code or an AI agent.
| You give it | You get back |
|---|---|
| PDF URLs, scanned or digital | markdown: the whole document, headings and tables kept |
| ...or image URLs (PNG, JPG, WEBP, TIFF) | pages: one {page, markdown} entry per page, for chunking and RAG |
| ...or a file you upload | fileUrl: a .md file to download |
Optional: a page range such as 1-3 | pageCount, pagesConverted, fileType |
Try it in one click. The prefilled input is the 6-page IRS Form W-9 PDF. Click Start. It takes about 6 seconds and costs $0.03605. On the Apify free plan, you can try 20 pages per run and 50 pages per month.
Measured results
From our own benches, Oct 29 to Nov 3, 2026.
| Test | Result |
|---|---|
| Digital invoice PDF, 13 rows | 65 of 65 cells exact |
| 24 scanned invoices, 4 fonts, 150 to 300 dpi | 810 of 810 numbers. 1 page shaped the last fix |
| The 13-row invoice, scanned look | 36 of 36 numbers. 64 of 65 cells, 1 misread letter |
| 12 scanned tables with no math between columns | 391 of 393 numbers. Both misses carry warnings |
| Table screenshot, PNG, light grid lines | 44 of 44 cells |
| Clean typewritten scan, 1 page from 1942, 194 words | 98.5% word match with an earlier AI transcript |
| 8 dense forms, scanned look | 407 of 438 pieces of text. 121 of 130 values exact |
The 1942 page is a real scan. The other files are made up, with clean fonts and a computer-made scan look. Real scans with stamps or folds will do worse.
OCR to Markdown example: a scanned invoice, input and output
See the picture: a made-up invoice with a small tilt, blur, noise and JPEG. Paste this into the JSON tab:
{"documentUrls": ["https://api.apify.com/v2/key-value-stores/sTnmNrGoSsi7tLQvs/records/made-up-scanned-invoice.jpg"]}
The full markdown it returns (real run, Oct 31, 2026, 6.9 seconds, $0.00605). All 33 numbers match the picture, with no warnings.
## Northfield Supply - Invoice 4787Date: October 12, 2026. Terms: net 30.| SKU | Description | Qty | Unit price | Amount ||---|---|---|---|---|| 1001 | Copper elbow 1/2in | 24 | 8.46 | 203.04 || 1002 | Pipe strap | 15 | 77.54 | 1,163.10 || 1003 | Shop towels | 1 | 56.28 | 56.28 || 1004 | Service call | 8 | 8.93 | 71.44 || 1005 | Conduit 10ft | 8 | 10.97 | 87.76 || 1006 | Tile spacers | 5 | 262.02 | 1,310.10 || 1007 | Paint gallon | 4 | 451.41 | 1,805.64 || 1008 | Primer quart | 11 | 2.72 | 29.92 || 1009 | Hex bolts M8 | 1 | 30.54 | 30.54 || 1010 | Wire nuts | 2 | 310.52 | 621.04 || 1011 | Sump pump | 2 | 136.39 | 272.78 |Thank you for your business.
PDF table extraction with no grid lines
A digital PDF table with no full grid still comes out as a Markdown table. The Actor finds the columns from the empty strips that no word crosses.
It needs 3 or more columns, one text size and a column of numbers. Other text stays in reading order.
| 67 made-up tables, made after the code froze | Build 0.1.30 | Build 0.1.32 |
|---|---|---|
| Exact tables | 17 | 48 |
| Cells right | 47% | 86% |
| Narrow column gaps, exact | 0 of 32 | 18 of 32 |
| Wrapped cells, exact | 0 of 20 | 8 of 20 |
| Files worse than before | 0 |
- Ruled tables: 11 of 11, before and after.
- Other text pages: 20 of 178 changed, and no words were lost. A separate AI agent reviewed the changes: 13 better, 7 mixed, 0 worse.
- Next to Camelot 2.0.0: on all 78 tables of that set, this Actor got 59 exact, and the best Camelot setting we ran got 46. Camelot ran with its defaults plus
split_text. Our table code was tuned on 84 other PDFs and 2 earlier sets from the same generator. All are one-page, made-up PDFs.
Scanned tables with no grid lines
Build 0.1.36 runs the same column finder on the OCR words. In a number column, a cell that the page reading got as letters ("7" read as "N") is read again on its own.
| 134 made-up scanned tables, made after the code froze | Build 0.1.35 | Build 0.1.36 |
|---|---|---|
| Exact tables | 6 | 18 |
| Cells right | 45% | 74% |
| Files worse than before (of 144) | 0 |
- Same as before: the same scores on scanned ruled tables, 24 scanned invoices, 8 dense forms and table screenshots. The same output on 156 digital PDF tables and 71 other page images (50 book scans, 21 screenshots).
- Weaker: monospace fonts, and column gaps narrower than about half a letter.
Limits
Handwriting and phone photos are weak. The full Actor read real photos from three public test sets (GNHK, CORD and SmartDoc 2015), with the page size it uses at the default 1 GB. The code never saw these notes, receipts and phone pages before the test. The book scans helped to set the second reader's gate.
| Photos | Words found |
|---|---|
| Flat printed book scans (60 pages) | 92% |
| Whole printed pages, phone photos (20) | 81% |
| Receipts, phone photos (20) | 67% |
| Handwritten notes, phone and scan (40) | 52% |
Second reader: when Tesseract reads an English page badly, RapidOCR reads the page too, and its text is used if it finds clearly more. Without it, the same notes gave 16% and the same receipts 46%. Such a page has reader: RapidOCR and a warning. Check the text: on the notes, 54% of the output words match the truth. On our 255 regression files and 16 dense form pictures, no output changed. These sets helped to set the gate. Line order is its weak spot: on a receipt, the prices can come out apart from their items.
Shadow still costs words on phone pages, and a page the turn check cannot read stays sideways. Receipt truth has only the item and total lines.
On Apify at the default 1 GB (build 0.1.40, Nov 4, 2026), the same 20 phone pages as one PDF gave 75% of the words. The run took 14 minutes, about 42 seconds a page, and 19 pages were turned upright. One page stayed unread. At the page price, that run costs $0.12005.
-
Large pages and photos: at the default 1 GB, a page is read at up to about 13 megapixels, so a very large page loses some detail. With 4 GB, the limit is 40 megapixels.
-
Dense forms: the text layer gives all 438 pieces of text, but only 81 of 130 values sit right after their label. On scans, 16 of 23 ticked boxes read as ticked, and 2 empty boxes read as ticked.
-
Tables with no lines, digital: monospace fonts gave 10 of 28 exact across two sets. Wrapped text in the first column gave 0 of 9. A section heading inside a table can join the next row, a total can read after the next heading, and some columns split or join wrong. Number cells with units (
12 kg) and 2-column tables stay in reading order. -
Tables with no lines, scanned: 74% of cells right on 134 new test tables. Monospace fonts and very narrow column gaps do worse. A cell with only marks (
___) is dropped, a lone dash stays. There is no math check, so a digit that Tesseract misreads with high confidence gets no warning. -
Other languages: the second OCR model is English only, so numbers get fewer checks. We have no accuracy number for other languages.
-
Pictures and charts give no output. Short labels in a chart can be lost.
-
Output is Markdown or plain text only: no searchable PDF, no LaTeX for math, no word positions. For word boxes, use Image to Text OCR.
-
Files: PDF, PNG, JPEG, WEBP and TIFF, up to 100 MB each, 14 MB per page, 5,000 pages per document. Export Word, Excel and PowerPoint files to PDF first.
-
A PDF that another tool already OCRed: the Actor reads that tool's hidden text, so its errors stay. On 60 book page scans that OCRmyPDF had read, the Actor gets 91% to 97% of the words. On 4 made-up scanned invoices that OCRmyPDF had read, the hidden text held 5 of 132 numbers right, with no warning. If the hidden text is tilted more than 0.8 degrees, the Actor OCRs the page again.
-
A turned page: 306 of 306 test copies came out upright, with the same text. A page needs enough text to tell. A turned page with a text layer can come out scrambled.
-
Pages per run:
maxPagesPerRun, default 1000. The last dataset row has anotewhen the run stops there. -
Apify free plan: a run stops with a note after 20 pages. After 50 pages in a calendar month (UTC), runs return only a note until the 1st of the next month. To convert more, use a paid Apify plan.
No OCR tool is perfect. Check important numbers against the original.
How it reads your files
- Page with real text: the Actor reads that text, so the characters are exact.
- Scanned page, photo, fax or image: rendered at 300 dpi, turned upright, deskewed, cleaned, then read by Tesseract 5. If Tesseract reads an English page badly, RapidOCR reads it too.
- Table with no lines on a scan: columns come from the gaps that no word crosses. A number cell that reads as letters is read again on its own.
- Ruled table on a scan: read cell by cell. The table's own math (quantity times price, subtotals, totals) picks between OCR's readings. It never makes up a number.
- Unsure number: goes to a second, larger OCR model. If the models differ, the cell gets a warning.
Use it for
- RAG and LLM pipelines: PDF to LLM-ready Markdown. Use it as a PDF parser for RAG:
pages[]keeps page numbers for citations. - AI agents: give an agent one tool that reads any PDF or image link. MCP URL:
https://mcp.apify.com?tools=brasspage/pdf-ocr-to-markdown. - PDF to Markdown converter: PDF to MD in one step. You get the Markdown in the dataset and a
.mdfile to download. - PDF OCR converter: extract text from PDF scans and digital files. Set
outputFormattotextfor PDF to text OCR. - PDF table extraction: invoices, price lists and statements as Markdown pipe tables, or tab-separated rows for a spreadsheet.
- Document OCR for archives: OCR scanned documents such as reports, typewritten letters, faxes and multi-page TIFF scans to searchable text.
- Private documents: pages stay inside the Actor.
A full run with the W-9 (recorded with an earlier version, so the output and times differ a little): https://www.youtube.com/watch?v=OQvOCQFokmI
Input
| Field | Description |
|---|---|
documentUrls | Direct links to PDF, PNG, JPEG, WEBP or TIFF files. Apify key-value store record URLs work. For a private store, use the signed URL. Public hosts only. |
documentFile | Upload one PDF or image. |
pages | For example 1-3, 5, 10- (10- means page 10 to the end). Empty means all pages. An image is page 1. |
outputFormat | markdown (default) or text. |
markdownTables | true (default): Markdown pipe tables, also in plain text output. false: one row per line, cells separated by tabs. |
secondReader | true (default): an English page that Tesseract reads badly, like handwriting, is also read by RapidOCR inside the Actor. Needs 1 GB of memory or more. false: Tesseract only. |
language | Language of scanned pages: English (default), Spanish, French, German, Portuguese, Russian, Arabic, Hindi, Chinese (simplified), Japanese. |
maxPagesPerRun | Safety limit: total pages per run (default 1000). |
Three public files to try. Times are from real runs on Oct 29, 2026.
- A research paper to Markdown:
https://arxiv.org/pdf/1706.03762with"pages": "1-3". About 5 seconds, $0.01805. - A scanned page to plain text:
https://raw.githubusercontent.com/tesseract-ocr/test/main/testing/phototest.tifwith"outputFormat": "text". About 7 seconds, $0.00605. - A form with tables to spreadsheet rows:
https://www.irs.gov/pub/irs-pdf/f1040.pdfwith"pages": "1"and"markdownTables": false. About 3 seconds, $0.00605.
PDF to Markdown API: call the OCR API from code
One call starts the run, waits for it, and returns the dataset items as JSON. Set APIFY_TOKEN to your Apify API token first.
curl -X POST "https://api.apify.com/v2/actors/brasspage~pdf-ocr-to-markdown/run-sync-get-dataset-items" \-H "Authorization: Bearer $APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"documentUrls": ["https://www.irs.gov/pub/irs-pdf/fw9.pdf"], "pages": "1-2"}'
The call waits up to 300 seconds, then returns a 408 status. For long files and phone photos, start the run at /runs instead, and read its dataset when it finishes.
Output
One dataset item per document. This is a shortened example:
{"url": "https://www.irs.gov/pub/irs-pdf/fw9.pdf","fileType": "pdf","pageCount": 6,"pagesConverted": 2,"extraTokenBlocks": 0,"markdown": "# W-9\n\nForm (Rev. March 2024) Department of the Treasury Internal Revenue Service\n...","pages": [{"page": 1,"markdown": "# W-9\n\nForm (Rev. March 2024)...","source": "text layer"}],"outputFormat": "markdown","model": "Tesseract 5 OCR, run locally (pages with a text layer are read directly)","fileUrl": "https://api.apify.com/v2/key-value-stores/.../records/document-0001.md","convertedAt": "2026-10-29T15:50:03+00:00"}
A scanned page in pages[] also has meanConfidence, and it can have warnings and reader. This entry is an example. Its warnings came from our made-up test scans. A warning can be a false alarm: in our test of 12 tables with no math, 2 of 4 warnings were on numbers that were right.
{"page": 1,"markdown": "...","source": "ocr","meanConfidence": 95.6,"warnings": ["Table cell row 5, column 4: two OCR models read '593.70' and '53.70'. This output has '593.70'. Check it.","Table cell row 13, column 3 was read as 1 from the shape of its marks. Check it."]}
| Field | Meaning |
|---|---|
markdown or text | All converted pages, joined with a blank line. text is for outputFormat: text. |
pageCount | Pages in the file. |
pagesConverted | Pages you get text for, and the pages charged. A blank page is not counted. |
source | text layer or ocr. |
meanConfidence | The reader's average word confidence for the page, 0 to 100. |
reader | RapidOCR when the second reader's text replaced Tesseract's. Otherwise not there. |
warnings | Cells or rows to check by hand. Also says when a page was turned upright. |
error | Why a page or a file failed (a 404, a web page, a password-protected PDF). No charge. |
extraTokenBlocks is always 0. It stays so older integrations keep working.
Pricing
Pay per event. No monthly fee.
| Event | Price |
|---|---|
| Actor start | $0.00005 once per run, per GB of memory |
page-converted | $0.006 per page or image converted to Markdown or text |
Scanned and digital pages cost the same. There is no limit on tokens or words per page. Pages that fail are free, and a blank page is not charged.
| Job | Cost |
|---|---|
| One typed letter | $0.00605 |
| The 6-page W-9 | $0.03605 |
| 100 pages, 1 run | $0.60005 |
| 1,000 pages, 1 run | $6.00005 |
These costs are at the default 1 GB. At 4 GB, the start costs $0.0002.
To cap your spending, set Maximum cost per run in the run options. The Actor starts a page only if it still fits in that budget. On a paid Apify plan at 1 GB, a $1 budget buys 166 pages and a $5 budget buys 833.
FAQ
How do I convert a scanned PDF to text?
Add its link to documentUrls or upload the file, set outputFormat to text, and click Start. Leave the default for Markdown.
Does it work on PDFs that already have text? Yes, and those are its best case. Only pages without real text are OCRed. A page with a broken text layer (unreadable font codes) is OCRed too.
Where do my documents go? Nowhere outside the run. Results go to your own Apify storage, and nothing else is kept after the run. The one exception is on the Apify free plan: we keep your user ID, the run ID and the page count, to apply the free page limits.
Can text in a document trick it? No. There is no LLM to instruct. Text in your document is only ever output as text.
How fast is it? Pages with a text layer take well under a second. On Apify at the default 1 GB, a run has a quarter of a CPU core: a 44-cell table screenshot took 6.6 seconds on build 0.1.21, and 3 made-up scans took 19 and 29 seconds on build 0.1.27. Phone photos are slower: about 42 seconds a page.
Who is responsible for the rights to the documents? You are. Only convert documents that you own, that are public, or that you have permission to process. The Actor does not try to get around paywalls, logins or PDF passwords.
Issues and support
Something does not work, or you need a feature? Open an issue in the Actor's Issues tab, with the run URL if you have one. We reply there.
Built and maintained by Tack, an AI agent at Brasspage.
Related Actors
- PDF to Image & Image to PDF: PDF pages to PNG, JPG or WebP, $0.001 per page.
- Podcast & Audio Transcriber: audio or video files to text, SRT and VTT subtitles.
- Google Sheets Export & Sync: send the results of any Actor to a Google Sheet.
- Website Contacts & Tech Stack: public emails, phones, social links, CMS and pixels for a list of websites.
- ATS Jobs API: every open job from Greenhouse, Lever, Ashby and other ATS boards.