PDF to Markdown & Document to Markdown: OCR, RAG Chunks
Pricing
from $2.00 / 1,000 document converteds
PDF to Markdown & Document to Markdown: OCR, RAG Chunks
PDF to Markdown and document to Markdown converter for LLMs, RAG and AI agents. PDF, scanned PDF (OCR), DOCX, PPTX, XLSX, EPUB and HTML to clean Markdown or plain text, with tables, headings and table-aware RAG chunks. $0.003 per document.
Pricing
from $2.00 / 1,000 document converteds
Rating
0.0
(0)
Developer
Tobby Tools
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
6 days ago
Last modified
Categories
Share
Document to Markdown Converter: PDF to Markdown, OCR & RAG Chunks
Turn PDFs, scans and Office files into clean Markdown and table-aware RAG chunks with one API call, for $0.003 per document.
| Proof | |
|---|---|
| OCR on a noisy scan | 98.6% word F1, vs 94.1% for the best competing Apify converter and 96.9% for the Docling library (benchmark) |
| Structure | The only converter in our test that kept all 4 heading levels, Table 2's two-level header and 10^20 exponents in Attention Is All You Need |
| Reproducible | Scripts, ground truth and every raw output are public: github.com/tobbytools/pdf-to-markdown-rag |
| Price | $0.003 per document (up to 50 pages). Failed documents are free |
Document to Markdown for LLMs and RAG: convert PDF to Markdown, PDF to text, DOCX to Markdown, PPTX, XLSX, EPUB, HTML and scanned PDFs or images (OCR) to clean Markdown or plain text. Tables (including merged cells and tables that continue across pages), headings, lists and reading order are kept, and every document comes back with table-aware RAG chunks that carry page numbers and bounding boxes. $0.003 per document, and you only pay for documents that convert.
Use it as a hosted MarkItDown alternative that also does OCR, multi-column layouts and real tables, from the Apify Console, the API, or no-code tools (n8n, Make, Zapier).
Quick start
- Paste a PDF (or DOCX, PPTX, XLSX, EPUB, HTML, image) URL into Files, or upload a file.
- Keep the defaults and click Start.
- Read
content(Markdown) andchunks(ready for embeddings) in the Output tab, or export as JSON, CSV or Excel.
Minimal input:
{ "files": ["https://arxiv.org/pdf/1706.03762"] }
Shortened output (the full real result is below):
{ "status": "succeeded", "title": "Attention Is All You Need", "pageCount": 15, "tableCount": 5,"content": "# Attention Is All You Need\n\n...\n\n## 3 Model Architecture\n\n### 3.1 Encoder and Decoder Stacks ...","chunks": [{ "section": "Attention Is All You Need > 1 Introduction", "pages": [2], "charCount": 1384, "text": "..." }] }
From code, call run-sync-get-dataset-items:
curl -X POST "https://api.apify.com/v2/acts/tobbyb~document-to-markdown-converter/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H "Content-Type: application/json" -d '{"files":["https://arxiv.org/pdf/1706.03762"]}'
Use cases
- RAG ingestion. Chunks never split a table row, carry their section path and page numbers, and can be one dataset row each for Pinecone, Qdrant, Weaviate or Chroma.
- Scanned archives. Old reports, invoices and typewritten pages become searchable text, plus an optional searchable PDF.
- Financial and scientific PDFs. Dense numeric tables and two-column papers keep their structure and reading order.
- No-code document pipelines. n8n community node (
n8n-nodes-document-to-markdown-converter), Make, Zapier, or base64 input when files aren't public. - AI agents. Give an agent a document URL and get Markdown back, through LangChain, LlamaIndex or Apify's MCP server.
What you get for each document
| Output | What it contains |
|---|---|
content | The whole document as Markdown (# headings, lists, tables) or plain text |
chunks | Table-aware chunks for embeddings: never split mid-row, a continued table repeats its header row, each chunk has section path, pages, page boxes (bbox) and character offsets |
tables | Every table as JSON rows, markdown, and html with rowspan/colspan when cells are merged; pages when a table spans several pages; bbox |
pages | Text per page, slide, sheet or EPUB chapter, page size, and quality flags: text layer or OCR, OCR confidence, table confidence, image coverage, needsVision |
figures | Pictures and diagrams with page, bbox and their Figure N: caption |
elements (optional) | Headings, paragraphs, list items and tables with bounding boxes, for citations and highlighting |
metadata | Title, author, dates, page/word/table counts, OCR pages, SHA-256, removed running headers/footers per page, warnings |
| Files (optional) | .md, .txt, editable Word .docx, Excel .xlsx with one sheet per table, searchable PDF for scans |
Benchmark: PDF to Markdown quality vs other Apify converters
Same 4 public documents, run on Apify on 2026-10-18 with each Actor's documented input: the Attention Is All You Need paper (headings and a two-level table), the two-column BERT paper (reading order), the Federal Reserve H.4.1 release (dense financial tables) and a synthetic noisy 150-DPI scan of IRS text with known ground truth (OCR). Other Actors are anonymized by their engine; the scripts and raw outputs are kept so the numbers can be reproduced.
| Converter | Headings found (of 21) / levels | Table 2 rows / two-level header / 10^20 exponents | BERT sentences intact¹ | Fed numeric table rows / key row correct | OCR word F1 on scan | Time, 4 docs |
|---|---|---|---|---|---|---|
| This Actor | 21 / 4 | yes / yes / yes | 93.4% | 75² / yes | 98.6% | 36 s |
| LLM-Markdown PDF Actor | 21 / 4 | yes / no / yes | 94.4% | 66 / no | 94.1% | 94 s |
| Document-to-Markdown Actor (layout) | 21 / 4 | yes / no / no | 52.8% | 77 / no | 0% (no OCR) | 4 s |
| PDF-to-Markdown API Actor | 21 / 1 | no / no / no | 83.8% | no output | no output | 60 s |
| Docling-based Actor | 21 / 1 | yes / no / no | stopped at its $0.20 cost cap after the first document | – | – | 352 s |
| Docling library (local, 1 CPU core) | 21 / 1 | yes / yes / no | 90.9% | 82 / no (+ signs split from numbers) | 96.9% | 214 s |
| MarkItDown-based Actors (2, same output) | 0 / 0 | no / no / no | 4.1% (columns turned into fake tables) | 12 / no | failed / 0% | ~51 s |
| Plain PDF text extractors (2) | 0 / 0 | no / no / no | 94.4% | 0 / no | 0% (no OCR) | 3–4 s |
¹ Share of 197 prose sentences from the PDF's own text stream found intact. Plain extractors copy that stream, so they match it by construction; our misses are page numbers and footnotes that we move out of the text, and table cells that we keep as tables. ² Tables that continue on the next page are merged, so repeated header rows are not counted twice.
The open-source libraries were also run locally on the same files (MarkItDown 0.1.8 gives the same output as the MarkItDown-based Actors). Docling 2 is strong on table structure, but flattens every heading to ##, separates +/- signs from numbers in financial tables, and needs about 2 GB of RAM. On the same single CPU core it took 214 s for the four files versus 33 s for this converter (174 s versus 1.2 s on the three text PDFs).
Hosted Actor vs running a library yourself
| This Actor | MarkItDown (self-hosted) | Docling (self-hosted) | |
|---|---|---|---|
| OCR for scans | Yes, only on pages that need it | No (0% on our scan) | Yes (96.9% word F1) |
| Heading levels kept (Attention paper) | 4 | 0 | 1 |
| Two-column reading order (BERT sentences intact) | 93.4% | 4.1% | 90.9% |
| Time, same 4 documents | 33 s on one core | about 3 s (no OCR) | 214 s on one core, about 2 GB RAM |
| Infrastructure | None: API, Console, n8n, Make, Zapier | Your server | Your server |
| Cost | $0.003 per document | Your compute | Your compute |
Sample output (shortened, real run on arxiv.org/pdf/1706.03762)
{"status": "succeeded","fileType": "pdf","title": "Attention Is All You Need","pageCount": 15,"tableCount": 5,"wordCount": 6202,"content": "# Attention Is All You Need\n\n...\n\n## 3 Model Architecture\n\n### 3.1 Encoder and Decoder Stacks\n\n...","tables": [{"page": 8,"rows": [["Model", "BLEU EN-DE", "BLEU EN-FR", "Training Cost (FLOPs) EN-DE", "Training Cost (FLOPs) EN-FR"],["GNMT + RL [38]", "24.6", "39.92", "2.3 · 10^19", "1.4 · 10^20"]],"markdown": "| Model | BLEU EN-DE | BLEU EN-FR | ...","bbox": [136.7, 98.7, 475.3, 240.3]}],"chunks": [{"index": 5,"text": "...eight P100 GPUs.\n\n## 2 Background\n\nThe goal of reducing sequential computation ...","section": "Attention Is All You Need > 1 Introduction","pages": [2],"boxes": [{ "page": 2, "bbox": [107.7, 301.7, 505.7, 535.5] }],"charStart": 4692, "charEnd": 6078, "charCount": 1384}],"figures": [{ "page": 3, "bbox": [196.6, 72, 415.4, 394.4], "caption": "Figure 1: The Transformer - model architecture." }],"pages": [{ "pageNumber": 3, "text": "...", "ocr": false, "width": 612, "height": 792,"quality": { "source": "text-layer", "imageCoverage": 0.15, "figureCount": 1, "needsVision": false } }],"metadata": { "creator": "LaTeX with hyperref", "createdAt": "2024-04-10T21:11:43", "marginText": [{ "page": 1, "text": "arXiv:1706.03762v7 [cs.CL] 2 Aug 2023" }] }}
PDF to Markdown for RAG: table-aware chunking
- Chunks break at headings first, then paragraphs, then sentences, with configurable size and overlap.
- Tables are never cut mid-row. If a table is longer than a chunk, the next chunk repeats the header row and the section path, and is marked
tableContinued: true. - Tables that continue across pages are merged into one table (repeated headers are dropped), and sentences that run over a page break are joined.
- Each chunk keeps
pagesandboxes(page + bounding box) so your app can cite and highlight the source. - Set One dataset item per chunk for one row per chunk; that shape works directly with Apify's Pinecone, Qdrant, Weaviate and Chroma integrations and with LangChain or LlamaIndex dataset loaders.
OCR for scanned PDFs and images
With ocrMode: auto, pages with no text layer, pages that are mostly an image, and pages with a garbled text layer (broken fonts) are read with Tesseract 5 OCR in 28 languages. Upside-down and sideways scans are rotated, and tilted scans are deskewed. Each OCR page reports its confidence, and needsVision: true flags pages (low confidence, large charts) that are worth sending to a vision model. On a noisy, blurred, tilted 150-DPI synthetic scan with known ground truth, word F1 was 98.6% (character error rate 1–2.4%).
DOCX, PPTX, XLSX, EPUB and HTML to Markdown
| Format | What is kept |
|---|---|
Text, scanned and mixed PDFs; multi-column reading order; ruled and borderless tables; headings from font size and numbering; superscripts (10^20, footnote marks ¹); password-protected PDFs (pdfPassword); page ranges | |
| DOCX | Headings, nested lists, tables (merged cells in HTML mode), footnotes, links, image alt text |
| PPTX | One page per slide: title, bullets, tables, grouped shapes, speaker notes |
| XLSX / XLS / CSV | One page per sheet as a table (up to 5,000 rows per sheet) |
| EPUB | Chapters in reading order, with title, author and language |
| HTML | Main content only (menus, cookie banners, sidebars removed), tables, links |
| Images | PNG, JPG, TIFF (multi-page), WebP, BMP, GIF via OCR |
| TXT / Markdown | Passed through and chunked |
Use with n8n, Make, Zapier, LangChain and the API
- URLs: public links, including Google Drive, Google Docs, Dropbox and GitHub share links (converted to direct downloads automatically).
- Base64: send file bytes in
base64Files([{"fileName": "invoice.pdf", "data": "<base64>"}]) when the file isn't public, e.g. from an n8n, Make or Zapier step. - Key-value store: convert records from an Apify key-value store.
{"files": ["https://arxiv.org/pdf/1706.03762", "https://www.federalreserve.gov/releases/h41/current/h41.pdf"],"outputFormat": "markdown","tableFormat": "markdown","chunkSize": 1500,"chunkOverlap": 150,"ocrMode": "auto","saveFiles": ["docx", "xlsx"]}
Pricing (pay per event)
| Event | Price |
|---|---|
| Document converted (up to 50 pages) | $0.003 |
| Each additional 50 pages | $0.003 |
| OCR page (only pages that needed OCR and produced text) | $0.003 |
A 12-page text PDF costs $0.003; a 140-page report $0.009; a 10-page scan $0.003 + 10 × $0.003 = $0.033; 1,000 Word or HTML files $3. Failed documents (404, damaged, password-protected without a password, empty) are free, and the run stops cleanly at your maximum cost per run.
Input reference
| Field | Default | Description |
|---|---|---|
files | example paper | Uploaded files or file URLs (Drive/Dropbox/GitHub links work) |
startUrls | – | Bulk URL list (userData is copied to the output) |
base64Files | – | [{fileName, data}] file bytes as base64 or a data: URI |
keyValueStoreId, keyValueStoreKeys | – | Convert records from a key-value store |
outputFormat | markdown | markdown or text |
tableFormat | markdown | markdown, or html to keep merged cells (rowspan/colspan) |
chunkSize, chunkOverlap | 1500, 150 | Chunk length and overlap in characters; 0 turns chunking off |
datasetItemPerChunk | false | One dataset row per chunk |
ocrMode | auto | auto, force (every page) or off |
ocrLanguages | ["eng"] | 28 languages incl. French, German, Spanish, Chinese, Japanese, Korean, Arabic, Russian, Hindi |
maxOcrPagesPerDocument | 100 | OCR safety limit per document |
saveFiles | [] | markdown, text, docx, xlsx, searchablePdf, json |
includePages, includeTables | true | Page-by-page text and structured tables |
includeQuality | true | Per-page quality flags |
includeElements | false | Per-page layout elements with bounding boxes |
pageRange | all | e.g. 1-5, 8, 12- |
pdfPassword | – | Password for encrypted PDFs (stored encrypted) |
extractTables, removeHeadersFooters | true | Table detection; remove running headers/footers (kept in metadata.headersFootersByPage) |
maxPagesPerDocument | 500 | Convert only the first N pages (or EPUB chapters) |
htmlMainContentOnly | true | Remove menus and boilerplate from web pages |
maxFileSizeMb, maxDocuments, maxConcurrency, downloadTimeoutSecs | 100, 10000, auto, 120 | Run limits |
Errors are explicit, not crashes
A document that can't be converted becomes a row with status: "failed" and an errorCode; the other documents keep going.
| errorCode | Meaning |
|---|---|
NOT_FOUND, ACCESS_DENIED, DOWNLOAD_FAILED, TIMEOUT, INVALID_URL | The file couldn't be downloaded |
INVALID_BASE64 | base64Files[].data isn't valid base64 |
FILE_TOO_LARGE | Above maxFileSizeMb |
EMPTY_FILE | 0 bytes |
DAMAGED_FILE | Corrupt or truncated PDF, Office or EPUB file |
PASSWORD_REQUIRED, WRONG_PASSWORD | Encrypted PDF: set pdfPassword |
UNSUPPORTED_FORMAT | e.g. legacy .doc/.ppt, ZIP archives, video |
NO_TEXT_FOUND | Blank pages, or OCR is off for a scan |
SPENDING_LIMIT_REACHED | Your maximum cost per run was reached (status skipped) |
FAQ
How do I convert a PDF to Markdown? Paste the PDF URL (or upload the file) into Files, keep the defaults and click Start. The Markdown is in content; download it as .md with saveFiles: ["markdown"].
Is this a good document to Markdown converter for RAG? Yes: chunks are table-aware, carry section paths, pages and bounding boxes, and can be one dataset row each for vector database integrations.
Does it do PDF to text? Set outputFormat: "text" for plain text (table cells separated by tabs).
Does it work on scanned PDFs (OCR)? Yes. ocrMode: auto OCRs only the pages that need it and charges only for those pages.
How does it compare with MarkItDown or Docling? See the benchmark above: MarkItDown has no OCR and turned two-column text into fake tables; Docling is good on table structure but flattens headings and is much heavier. This Actor keeps heading levels, two-level table headers and superscripts at $0.003 per document.
Can I keep merged table cells? Set tableFormat: "html". Every table in tables[] also has html when it has merged cells.
Can I get a Word or Excel file? Add docx and/or xlsx to saveFiles. Excel gets one sheet per table, numbers stored as numbers.
Is my data kept? Files are processed inside your own Apify run, and results stay in your run's storage under your account's retention settings.
Can I try it for free? Apify's free plan includes monthly platform credit you can spend on this Actor. A 15-page text PDF costs $0.003.
Where are code examples? LangChain, LlamaIndex, Python client and n8n examples, plus the full benchmark, are in github.com/tobbytools/pdf-to-markdown-rag.
Limits? Legacy .doc/.ppt and ZIP archives aren't supported. Math formulas come out as plain characters with ^ exponents, not LaTeX. Handwriting OCR is limited.