Any Document to Markdown for RAG avatar

Any Document to Markdown for RAG

Pricing

from $3.00 / 1,000 document processeds

Go to Apify Store
Any Document to Markdown for RAG

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

Musson Tools

Maintained by Community

Actor 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}. page is the PDF page, slide or image page number. section is 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_sha256 covers the original bytes and markdown_sha256 covers 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: true tells 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: false row 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

FormatHow it's convertedpage in chunks
PDF (text)poppler pdftotext, page by pagePDF 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 notesslide number
XLSX (Excel 2007+)openpyxl: each sheet as a Markdown table (cached formula values)– (section = sheet)
CSV / TSVdelimiter sniffing, Markdown table–
HTML web pagestrafilatura main-content extraction → Markdown (falls back to a full-page conversion)– (section = heading)
EPUBspine order, each chapter → Markdown– (chapter index)
Images (PNG, JPG, TIFF incl. multi-page, WebP, GIF, BMP)Tesseract OCRimage page number
TXT / Markdownpassed through, split by headings–

Legacy .doc, .xls and .ppt files, password-protected files and archives are rejected for free with a clear error.

Input

FieldDefaultDescription
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.
ocrModeautoauto OCRs only scanned PDF pages and images. always OCRs every PDF page. off never OCRs.
ocrLanguageengeng, deu, fra, spa, ita, por or nld. Combine languages with +, e.g. eng+fra.
maxOcrPages20OCR cap per document (max 200).
maxPages100Pages, slides, frames or chapters converted per document (max 500).
maxFileSizeMb20Download cap (max 50).
maxCharacters200000Markdown cap per document (max 2,000,000).
maxRowsPerSheet1000Row cap per XLSX sheet or CSV file (max 20,000).
documentTimeoutSecs120Per-document time limit (max 600).
maxChunkCharacters4000Chunk size for RAG (300–50,000).
includeMarkdowntrueUntick to return only chunks.
pageMarkerstrueAdd <!-- page N --> between pages and slides in markdown.
includeSpeakerNotestrueInclude PPTX speaker notes.
includeLinksfalseKeep 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 ApifyClient
client = 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 url plus page (or section) with each chunk.
  • To re-index incrementally, compare file_sha256 with what you stored last time.
  • Scanned PDFs: run memory of 1 GB (the default) handles OCR at about 1–3 s per page. Raise maxOcrPages for long scans.
  • Leave includeLinks off for cleaner embeddings from web pages.
  • content_is_untrusted is always true. 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.
  • PDF for RAG: a lighter, cheaper Actor for text PDFs only.