PDF to Markdown OCR Converter: Scanned PDFs & Images to Text avatar

PDF to Markdown OCR Converter: Scanned PDFs & Images to Text

Pricing

from $6.00 / 1,000 page converteds

Go to Apify Store
PDF to Markdown OCR Converter: Scanned PDFs & Images to Text

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

Brasspage

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

2 hours ago

Last modified

Security

Limited permissions

Share

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 fonts810 of 810 numbers
Scanned tables with no grid lines, 134 new tables74% of cells right, was 45%
Digital PDF tables with no grid lines, 67 new tables86% 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 itYou get back
PDF URLs, scanned or digitalmarkdown: 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 uploadfileUrl: a .md file to download
Optional: a page range such as 1-3pageCount, 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.

TestResult
Digital invoice PDF, 13 rows65 of 65 cells exact
24 scanned invoices, 4 fonts, 150 to 300 dpi810 of 810 numbers. 1 page shaped the last fix
The 13-row invoice, scanned look36 of 36 numbers. 64 of 65 cells, 1 misread letter
12 scanned tables with no math between columns391 of 393 numbers. Both misses carry warnings
Table screenshot, PNG, light grid lines44 of 44 cells
Clean typewritten scan, 1 page from 1942, 194 words98.5% word match with an earlier AI transcript
8 dense forms, scanned look407 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 4787
Date: 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 frozeBuild 0.1.30Build 0.1.32
Exact tables1748
Cells right47%86%
Narrow column gaps, exact0 of 3218 of 32
Wrapped cells, exact0 of 208 of 20
Files worse than before0
  • 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 frozeBuild 0.1.35Build 0.1.36
Exact tables618
Cells right45%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.

PhotosWords 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 a note when 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

  1. Page with real text: the Actor reads that text, so the characters are exact.
  2. 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.
  3. 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.
  4. 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.
  5. 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 .md file to download.
  • PDF OCR converter: extract text from PDF scans and digital files. Set outputFormat to text for 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

FieldDescription
documentUrlsDirect 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.
documentFileUpload one PDF or image.
pagesFor example 1-3, 5, 10- (10- means page 10 to the end). Empty means all pages. An image is page 1.
outputFormatmarkdown (default) or text.
markdownTablestrue (default): Markdown pipe tables, also in plain text output. false: one row per line, cells separated by tabs.
secondReadertrue (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.
languageLanguage of scanned pages: English (default), Spanish, French, German, Portuguese, Russian, Arabic, Hindi, Chinese (simplified), Japanese.
maxPagesPerRunSafety 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.03762 with "pages": "1-3". About 5 seconds, $0.01805.
  • A scanned page to plain text: https://raw.githubusercontent.com/tesseract-ocr/test/main/testing/phototest.tif with "outputFormat": "text". About 7 seconds, $0.00605.
  • A form with tables to spreadsheet rows: https://www.irs.gov/pub/irs-pdf/f1040.pdf with "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."
]
}
FieldMeaning
markdown or textAll converted pages, joined with a blank line. text is for outputFormat: text.
pageCountPages in the file.
pagesConvertedPages you get text for, and the pages charged. A blank page is not counted.
sourcetext layer or ocr.
meanConfidenceThe reader's average word confidence for the page, 0 to 100.
readerRapidOCR when the second reader's text replaced Tesseract's. Otherwise not there.
warningsCells or rows to check by hand. Also says when a page was turned upright.
errorWhy 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.

EventPrice
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.

JobCost
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.