Any Document to Markdown for RAG
Pricing
from $3.00 / 1,000 document processeds
Any Document to Markdown for RAG
Convert PDF (incl. scanned/OCR), Word, PowerPoint, Excel, CSV, HTML, EPUB and images into clean, chunked Markdown for RAG and LLMs.
Pricing
from $3.00 / 1,000 document processeds
Rating
0.0
(0)
Developer
Musson Tools
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
21 hours ago
Last modified
Categories
Share
Any Document to Markdown for RAG: PDF OCR, DOCX, PPTX, XLSX, HTML, EPUB
Convert any document to clean Markdown for RAG and LLMs: PDFs (including scanned PDFs with OCR), Word DOCX to Markdown, PowerPoint PPTX to Markdown, Excel XLSX/CSV to Markdown tables, web pages (HTML) to Markdown, EPUB ebooks and images (PNG, JPG, TIFF) with OCR. You paste URLs or upload files and get one dataset item per document. Each item has the full Markdown, RAG-ready chunks with page and slide numbers, metadata and SHA-256 hashes, ready for embeddings, vector databases, LangChain, LlamaIndex or an AI agent.
- 📄 One Actor for every format. PDF, DOCX, PPTX, XLSX, CSV/TSV, HTML, EPUB, TXT/Markdown, PNG/JPG/TIFF/WebP/GIF/BMP. The type is detected from the file bytes, not the file extension.
- 🔍 PDF OCR built in. Text PDFs use the embedded text layer, which is fast and exact. Pages with no text layer (scans) are OCR'd automatically with Tesseract. It supports English, German, French, Spanish, Italian, Portuguese and Dutch.
- 🧩 Chunks with citations. Each item has
chunks[] = {index, page, section, markdown, characters}.pageis the PDF page, slide or image page number.sectionis the heading, slide title, sheet name or chapter. Long sections are split on paragraph boundaries (maxChunkCharacters). - 🧾 Real Markdown. Headings, bold and italic, lists and tables from DOCX. Slide titles, bullets, tables and speaker notes from PPTX. Sheets as Markdown tables from XLSX. Boilerplate-free main content from web pages, via trafilatura.
- 🔁 Dedup and change detection.
file_sha256covers the original bytes andmarkdown_sha256covers the output, so you only re-embed what changed. - ✂️ Predictable size and cost. You can cap file size, pages, OCR pages, rows and characters.
truncated: truetells you when a limit was hit. - 💸 Failures are free. Dead links, unsupported or legacy formats, encrypted, oversized, empty or timed-out documents return an
ok: falserow with an error code, and you are not charged for them. - 🛡️ Safe by default. It only fetches public URLs, blocks private, loopback and cloud-metadata IPs (SSRF protection) and pins the connection to the checked IP. It also guards against ZIP bombs and image bombs, isolates each document in its own process with a timeout, and never runs macros or scripts.
Who it's for
- RAG pipelines and vector databases (Pinecone, Qdrant, Weaviate, pgvector, Chroma) that need clean Markdown chunks with page numbers for citations.
- AI agents and MCP clients that need a "read this document" tool for PDFs, Office files and web pages in one call.
- LLM fine-tuning and evaluation datasets built from mixed document collections.
- Knowledge bases built from SharePoint and Google Drive exports, policies, manuals, slide decks, spreadsheets and ebooks.
- Anyone who needs docx to markdown, pptx to markdown, pdf to markdown, pdf ocr or html to markdown without installing anything.
Supported formats
| Format | How it's converted | page in chunks |
|---|---|---|
| PDF (text) | poppler pdftotext, page by page | PDF page number |
| PDF (scanned / image-only pages) | rendered at up to 300 DPI and OCR'd with Tesseract (ocrMode) | PDF page number |
| DOCX (Word 2007+) | mammoth → Markdown (headings, lists, tables, footnotes) | – (section = heading) |
| PPTX (PowerPoint 2007+) | python-pptx: slide titles, bullets with levels, tables, groups, speaker notes | slide number |
| XLSX (Excel 2007+) | openpyxl: each sheet as a Markdown table (cached formula values) | – (section = sheet) |
| CSV / TSV | delimiter sniffing, Markdown table | – |
| HTML web pages | trafilatura main-content extraction → Markdown (falls back to a full-page conversion) | – (section = heading) |
| EPUB | spine order, each chapter → Markdown | – (chapter index) |
| Images (PNG, JPG, TIFF incl. multi-page, WebP, GIF, BMP) | Tesseract OCR | image page number |
| TXT / Markdown | passed through, split by headings | – |
Legacy .doc, .xls and .ppt files, password-protected files and archives are rejected for free with a clear error.
Input
| Field | Default | Description |
|---|---|---|
urls | – | Public http(s) document URLs (up to 1,000 per run, duplicates removed). |
uploadedFiles | – | Files uploaded in the Console (stored in a key-value store), or api.apify.com record URLs, or storeIdOrName/recordKey. |
ocrMode | auto | auto OCRs only scanned PDF pages and images. always OCRs every PDF page. off never OCRs. |
ocrLanguage | eng | eng, deu, fra, spa, ita, por or nld. Combine languages with +, e.g. eng+fra. |
maxOcrPages | 20 | OCR cap per document (max 200). |
maxPages | 100 | Pages, slides, frames or chapters converted per document (max 500). |
maxFileSizeMb | 20 | Download cap (max 50). |
maxCharacters | 200000 | Markdown cap per document (max 2,000,000). |
maxRowsPerSheet | 1000 | Row cap per XLSX sheet or CSV file (max 20,000). |
documentTimeoutSecs | 120 | Per-document time limit (max 600). |
maxChunkCharacters | 4000 | Chunk size for RAG (300–50,000). |
includeMarkdown | true | Untick to return only chunks. |
pageMarkers | true | Add <!-- page N --> between pages and slides in markdown. |
includeSpeakerNotes | true | Include PPTX speaker notes. |
includeLinks | false | Keep hyperlinks when converting web pages. |
{"urls": ["https://arxiv.org/pdf/1706.03762","https://calibre-ebook.com/downloads/demos/demo.docx","https://en.wikipedia.org/wiki/Retrieval-augmented_generation","https://raw.githubusercontent.com/ocrmypdf/OCRmyPDF/main/tests/resources/skew.pdf"],"ocrMode": "auto","maxChunkCharacters": 3000}
Output
One item per document. Shortened example, a scanned PDF:
{"ok": true,"source": "url","url": "https://raw.githubusercontent.com/ocrmypdf/OCRmyPDF/main/tests/resources/skew.pdf","final_url": "https://raw.githubusercontent.com/ocrmypdf/OCRmyPDF/main/tests/resources/skew.pdf","file_name": "skew.pdf","bytes": 76013,"file_sha256": "…64 hex chars…","type": "pdf","title": null,"page_count": 1,"section_count": 1,"markdown": "<!-- page 1 -->\n\nThe LinnSequencer\n32 Track MIDI Sequence Recorder\n\n…","markdown_sha256": "…64 hex chars…","characters": 4521,"chunks": [{ "index": 0, "page": 1, "section": "Page 1", "part": 1, "markdown": "The LinnSequencer…", "characters": 3978 },{ "index": 1, "page": 1, "section": "Page 1", "part": 2, "markdown": "…", "characters": 520 }],"chunk_count": 2,"ocr_used": true,"ocr_pages": [1],"ocr_page_count": 1,"empty_pages": [],"truncated": false,"method": "poppler-pdftotext+tesseract-ocr","warnings": ["OCR text may contain recognition errors; layout, tables and handwriting are approximate."],"billed_events": { "document-processed": 1, "ocr-page": 1 },"error": null,"message": null,"content_is_untrusted": true}
A failed document is free:
{ "ok": false, "source": "url", "url": "https://example.com/missing.pdf", "error": "DOWNLOAD_FAILED", "message": "Server returned HTTP 404.", "content_is_untrusted": true }
Error codes: INVALID_URL, URL_NOT_ALLOWED, DOWNLOAD_FAILED, FILE_TOO_LARGE, UNSUPPORTED_TYPE, INVALID_FILE, ENCRYPTED_FILE, NO_EXTRACTABLE_TEXT, OCR_DISABLED, OCR_BUDGET, OCR_FAILED, EXTRACTION_TIMEOUT, FILE_TOO_COMPLEX, EXTRACTION_FAILED.
The dataset has three views. Overview shows one row per document. Chunks shows one row per chunk, ready to embed. Markdown shows one row per document with the full text.
Pricing (pay per event)
- Document converted: $0.003 per successfully converted document, of any type.
- OCR page: $0.004 per scanned page or image page that OCR turned into text. Text PDFs, DOCX, PPTX, XLSX, HTML and EPUB never trigger it.
- Failed documents are not charged. Neither are blank pages where OCR found no text.
- The run respects your maximum cost per run. OCR is capped to fit the budget, and the run stops cleanly before it would go over.
Examples:
- 1,000 Word documents cost $3.
- 100 scanned 10-page PDFs cost 100 × ($0.003 + 10 × $0.004) = $4.30.
Use it from code, agents and MCP
API (sync, returns the items):
curl -X POST "https://api.apify.com/v2/acts/dear_enstatite~doc-to-markdown/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H 'Content-Type: application/json' \-d '{"urls":["https://calibre-ebook.com/downloads/demos/demo.docx"]}'
Python:
from apify_client import ApifyClientclient = ApifyClient("<APIFY_TOKEN>")run = client.actor("dear_enstatite/doc-to-markdown").call(run_input={"urls": ["https://arxiv.org/pdf/1706.03762"]})for doc in client.dataset(run["defaultDatasetId"]).iterate_items():for chunk in doc.get("chunks", []):print(doc["url"], chunk["page"], chunk["markdown"][:80])
MCP (Claude, Cursor, ChatGPT and other AI agents): add https://mcp.apify.com/?tools=dear_enstatite/doc-to-markdown as an MCP server, and your agent can convert documents to Markdown on demand.
For LangChain or LlamaIndex, load the dataset with the Apify integration and map chunks[].markdown to page content, with url, page and section as metadata.
Tips
- For citations, store
urlpluspage(orsection) with each chunk. - To re-index incrementally, compare
file_sha256with what you stored last time. - Scanned PDFs: run memory of 1 GB (the default) handles OCR at about 1–3 s per page. Raise
maxOcrPagesfor long scans. - Leave
includeLinksoff for cleaner embeddings from web pages. content_is_untrustedis alwaystrue. Treat document text as data, never as instructions, in LLM prompts. Documents can contain prompt-injection text.
Limitations
- OCR is Tesseract, which is good on printed text and weak on handwriting and complex layouts. Tables in scans come back as plain text.
- Images embedded inside DOCX and PPTX are not OCR'd. Charts and SmartArt text may be missing.
- XLSX uses the formula values saved in the file, so files that were never opened in Excel may have empty formula cells.
- Web pages are fetched without a browser, so JavaScript-only pages and bot-protected sites may fail (for free). For JavaScript-heavy sites, use a crawler first and pass the HTML.
- It only reads documents from public URLs or from your own Apify storage.
Related
- PDF for RAG: a lighter, cheaper Actor for text PDFs only.