PDF to Markdown & RAG Chunks: Word, Excel, PowerPoint avatar

PDF to Markdown & RAG Chunks: Word, Excel, PowerPoint

Pricing

from $0.40 / 1,000 page converteds

Go to Apify Store
PDF to Markdown & RAG Chunks: Word, Excel, PowerPoint

PDF to Markdown & RAG Chunks: Word, Excel, PowerPoint

PDF to Markdown converter for RAG and LLMs: turn PDF, Word (DOCX), PowerPoint (PPTX), Excel (XLSX) and HTML files into clean Markdown, JSON blocks or page-cited RAG chunks. Tables kept, headers and footers removed, scans flagged for OCR. No GPU, no setup.

Pricing

from $0.40 / 1,000 page converteds

Rating

0.0

(0)

Developer

Quarrywise

Quarrywise

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

21 hours ago

Last modified

Share

Turn PDF, Word, PowerPoint and Excel files into clean Markdown, JSON blocks or page-cited RAG chunks in one call, with a per-page quality report that tells you what to trust. No GPU, no setup, no AI guessing.

Feed your retrieval pipeline, LLM app, AI agent or knowledge base with documents that keep their structure: real heading levels, tables as tables, page numbers for citations, and running headers and footers removed. Scanned pages are never returned as silent empty text: they are flagged as "needs OCR" and not charged. You pay per document and per page converted, at the prices shown below.

PDF to Markdown converter for RAG and LLMs

  • Developers and AI teams building RAG who need chunks with source, page range and heading path, ready to embed.
  • Agent and automation builders (API, MCP, n8n, Make, Zapier) who want one predictable call that turns a file link into Markdown or JSON.
  • Knowledge-base and search teams importing manuals, reports, policies, slide decks and spreadsheets.
  • Analysts who want tables from born-digital PDFs and Office files as Markdown tables.

What sets it apart:

  • Scans are flagged, never silently empty. Pages without a text layer are listed in pages_needing_ocr, explained, and free.
  • A quality report per page: text found or not, characters, words, a garble score for unreadable fonts, tables, images, removed header and footer lines (with their text), and plain-language warnings.
  • Tables joined across pages: a ruled table that continues on the next page comes out as one table, header once.
  • Headers and footers removed, values kept: running headers, footers and page numbers go; lines with amounts, account numbers or changing values stay.
  • Page-cited heading paths on every block and chunk.

PDF text extractor that keeps tables and headings

  • Structure that survives: heading levels from PDF bookmarks, "3.1"-style numbering, font size and weight, and Word heading styles; bullet and numbered lists; bold, italic and links from Word.
  • Tables as tables: ruled PDF tables, simple aligned tables without lines, and native Word, PowerPoint, Excel, HTML and CSV tables. Tables with merged cells are written as HTML so no cell lands in the wrong column.
  • Clean text for chunking: two-column PDF pages are read column by column; Word headers and footers are left out.
  • Clear failures: password-protected PDFs, damaged files, unsupported formats, blocked downloads and scans each get their own status and message. Failed inputs are free.
  • Deterministic: the same file gives the same output every time. No language model is involved.

Word, PowerPoint and Excel to Markdown

FormatWhat is extractedPages (for billing)
PDF (born-digital, with a text layer)Headings, paragraphs, lists, ruled and simple aligned tables, reading order in two-column pagesEach PDF page with text
Word (.docx)Heading styles, lists, tables (merged cells as HTML), bold, italic, linksEvery 3,000 characters of output
PowerPoint (.pptx)Slide titles as headings, text and bullet levels, tables, speaker notesEach slide
Excel (.xlsx, .xls)Each visible sheet as tables; blank cells stay empty; dates as ISO datesEvery 3,000 characters of output
HTMLMain content only (navigation, header, footer, scripts removed), tables, lists, codeEvery 3,000 characters of output
Markdown, plain text, CSVHeadings, lists, tablesEvery 3,000 characters of output

Docx to Markdown, pptx to Markdown, xlsx to Markdown, HTML to Markdown and PDF to JSON all run through the same call; choose the output below.

Not supported in this version: scanned PDFs and images (they are flagged as needing OCR), legacy .doc and .ppt (save them as .docx or .pptx), OpenDocument, EPUB and RTF. Each of these gets a clear error row, free of charge.

How to use it

  1. Paste links to your documents in Document links, or upload files with Upload files.
  2. Choose Output: Markdown, JSON blocks, or RAG chunks (set the chunk size and overlap).
  3. Optionally limit pages (for example 1-5, 8) and set a maximum charge for the run.
  4. Start the run. Results appear in the dataset; the run summary is in the OUTPUT record and a per-document report in the DOCUMENTS record.

From code, call the Actor through the Apify API or client and read the dataset items. For API users there are two more ways to send files: records in a key-value store (keyValueStoreId and fileKeys) and small files as base64 (base64Files).

Use it from n8n, Make, Zapier or an AI agent

  • n8n: add Apify's verified n8n node (@apify/n8n-nodes-apify; on n8n Cloud the instance owner first enables verified community nodes). Use the operation "Run an Actor and Get Dataset" and select this Actor By URL (enter exactly https://console.apify.com/actors/lnxVsBgOB9lHLTIYG/input) or by ID (lnxVsBgOB9lHLTIYG); the From list picker may not show it while the Actor is hidden from Store search. The Actor's Store page URL does not work in the By URL field. Then send documentUrls with outputFormat chunks. Keep the rows whose row_type is chunk and send them to your vector store node; each chunk carries page_start, page_end and heading_path for citations.
  • Make: Apify's app: the "Run an Actor" module, then "Get Dataset Items" (the "Watch Actor Runs" trigger fires when a run finishes).
  • Zapier: Apify's app: the "Run Actor" action, then "Fetch dataset items" (the "Finished Actor run" trigger fires when a run finishes).
  • AI agents (MCP clients): add this Actor as a tool through Apify's MCP server: https://mcp.apify.com?tools=quarrywise/pdf-to-markdown-rag The MCP server needs an Apify sign-in or API token.
  • API: POST https://api.apify.com/v2/acts/quarrywise~pdf-to-markdown-rag/run-sync-get-dataset-items with your Apify token in the Authorization: Bearer header and the input JSON as the body. Large documents can take longer than the 300 seconds this call waits (HTTP 408 after that); start the Actor asynchronously for those and read the dataset when it finishes.

Input

FieldWhat it doesDefault
documentUrlsLinks to documents, one per line (public or signed links)none
uploadedFilesFiles uploaded in the formnone
outputFormatmarkdown, blocks or chunksmarkdown
chunkSizeTarget chunk size in tokens (64 to 8,000)500
chunkOverlapOverlap between chunks of one section, in tokens50
chunkHeadingContextStart each chunk with its heading pathtrue
pageRangePages or slides to convert, for example 1-5, 8, 10-all
maxPagesMaximum pages or slides per document300
removeHeadersFootersRemove running headers, footers and page numbers from PDFstrue
pageMarkersAdd <!-- page N --> comments to the Markdownfalse
includeSpeakerNotesAdd PowerPoint speaker notestrue
includeHiddenSheetsInclude hidden Excel sheetsfalse
maxRowsPerSheetRow cap per sheet or CSV file5000
saveMarkdownFilesAlso save each document as a .md file in the key-value storefalse
keyValueStoreId, fileKeysRead documents from key-value store recordsnone
base64FilesSmall files inside the input: [{"fileName": "a.pdf", "contentBase64": "..."}]none
maxFileSizeMbSkip larger files (hard limit 100 MB)50
maxDocumentsMaximum documents per run (up to 1,000)100

Example: chunks for a RAG pipeline.

{
"documentUrls": ["https://quarrywise.com/samples/quarterly-report.pdf"],
"outputFormat": "chunks",
"chunkSize": 500,
"chunkOverlap": 50
}

Output

Markdown mode gives one row per document:

{
"row_type": "document",
"input_index": 1,
"source": "https://quarrywise.com/samples/quarterly-report.pdf",
"file_name": "quarterly-report.pdf",
"document_id": "9abfce51c8d261d9c32c",
"status": "ok",
"format": "pdf",
"title": "Example Orchard Cooperative: Quarterly Report",
"pages_total": 3,
"pages_converted": 3,
"pages_needing_ocr": [],
"billable_pages": 3,
"markdown": "# Example Orchard Cooperative: Quarterly Report\n\n...\n\n## 2 Harvest by variety\n\n| Variety | Hectares | Tonnes | Change |\n|---|---|---|---|\n| Elstar apple | 42 | 1,260 | +8% |\n...",
"quality": {
"pages": [{ "page": 1, "status": "ok", "chars": 912, "words": 167, "garble_score": 0.003, "tables": 1, "images": 0, "furniture_removed": 2, "warnings": [] }],
"stats": { "furniture_lines_removed": 6, "headings": 10, "tables": 1 },
"furniture_removed_text": ["Example Orchard Cooperative | Quarterly report Q3 (sample)", "Page 1 of 3", "Page 2 of 3", "Page 3 of 3"]
},
"warnings": []
}

RAG chunking with page citations

Chunks mode gives one row per chunk:

{
"row_type": "chunk",
"chunk_id": "9abfce51c8d261d9c32c-0001",
"chunk_index": 1,
"chunk_count": 4,
"file_name": "quarterly-report.pdf",
"heading_path": ["Example Orchard Cooperative: Quarterly Report", "2 Harvest by variety"],
"page_start": 1,
"page_end": 2,
"token_estimate": 179,
"char_count": 713,
"text": "# Example Orchard Cooperative: Quarterly Report\n\n## 2 Harvest by variety\n\nThe table lists the harvested area ...\n\n| Variety | Hectares | Tonnes | Change |\n|---|---|---|---|\n| Elstar apple | 42 | 1,260 | +8% |\n..."
}

Chunks follow headings and stay within your chunk size (the heading path at the top, and a heading kept together with its first text, can add a little): long paragraphs are split at sentence ends, long lists by item, code blocks by lines, and tables by rows with the header row repeated in each part. chunk_id is the document ID plus the chunk number, so the same file always gives the same IDs (handy for upserts into a vector store).

In RAG chunks mode, keep rows with row_type "chunk". The same dataset also holds one notice row per document that has warnings (or a saved Markdown file), and error rows for inputs that failed; their text is empty and they are free.

JSON blocks mode gives one row per document with blocks: a list of headings, paragraphs, list items and tables, each with type, text, level, page, page_end and heading_path (tables also have rows).

A scan returns a row like this, and is not charged:

{ "row_type": "document", "file_name": "scanned-notice.pdf", "status": "needs_ocr", "pages_needing_ocr": [1], "billable_pages": 0,
"error_message": "No text layer found: this looks like a scanned or image-only document. It needs OCR, which this Actor does not do. Nothing was charged." }

The dataset has three views: Documents, RAG chunks and Quality and problems.

Output fields

FieldMeaning
row_typedocument (one converted document), chunk (one RAG chunk), notice (warnings for a document in chunks mode, free) or error (an input that failed, free)
input_indexPosition of the document in the input (1 = first)
sourceWhere the document came from, without query string (signed-link tokens are never stored)
file_nameFile name from the link, the download or the upload
document_idFirst 20 hex characters of the file's SHA-256: the same file always gets the same ID
statusSee the list below
formatpdf, docx, pptx, xlsx, xls, html, markdown, text or csv
titleDocument title from its metadata, else its first heading
pages_totalPages, slides or sheets in the file
pages_convertedPDF pages or slides converted with text
pages_needing_ocrPages without a usable text layer (not charged)
billable_pagesPages charged for this document
truncatedTrue when a page or row limit, the time limit or your maximum charge cut the document short
markdownThe document as Markdown (Markdown and JSON blocks modes)
markdown_file_urlLink to the .md file in the run's key-value store, when you asked for files or the Markdown is too large for one row
blocksJSON blocks (JSON blocks mode)
blocks_file_urlLink to the JSON blocks file, when the blocks are too large for one row
chunk_id, chunk_index, chunk_countThe chunk's ID, its position (from 0) and the number of chunks in its document
textThe chunk text (Markdown)
heading_pathThe headings the chunk sits under, outermost first
page_start, page_endFirst and last page or slide the chunk comes from
token_estimate, char_countSize of the chunk (about 4 characters per token)
qualityPer-page report, counters and, for PDFs, the removed header and footer texts
warningsPlain-language warnings for the document
error_reason, error_messageWhy an input failed, as a short code and as a sentence

status values: ok; partial (some pages need OCR); needs_ocr (no text layer at all); empty (no text); encrypted (password-protected PDF); unsupported (a format this Actor does not read); download_failed (the link could not be read); error (a damaged file, a file whose pages could not be read, or one too large or too complex to convert); invalid_input (the run input itself was not valid). Only ok and partial documents are charged.

Pricing

Pay per event: you pay for documents and pages actually converted and saved, plus Apify's standard Actor start event, a fraction of a cent per run.

EventPrice
Document converted$0.003 per document
Page converted$0.0004 per page (a PDF page or slide with text, or 3,000 characters of output for other formats)

Free: documents that fail, pages that need OCR, empty pages and documents, notice and error rows.

ExampleCost
One 10-page PDF$0.007
One 100-page PDF$0.043
1,000 PDFs of 10 pages each$7.00
A 40-slide deck$0.019
The prefilled example (4 sample files, 9 pages)about $0.016
A 30-page scan (needs OCR)$0 (plus the start event)

The examples leave out the start event. Set a maximum charge per run in the run options to cap spending. The Actor checks the budget before saving each document, converts as many pages as the budget allows, says so in the document's warnings, and then stops cleanly with status limit-reached in the run summary.

Limits

  • Files up to 50 MB by default (maxFileSizeMb, at most 100 MB), up to 1,000 documents per run.
  • Up to 300 pages per document by default (maxPages, at most 5,000).
  • Each document gets up to 10 minutes and the run's memory. A document that needs more (a very long or very dense file, a very large HTML page, or a decompression bomb) gets a free error row with reason too-complex, and the run goes on with the next document. Long documents and large HTML pages are best run with 2 to 4 GB of memory.
  • Spreadsheets: up to 512 filled columns per sheet and 2,000,000 cells per file. Formulas whose result was never saved in the file come out blank, with a warning.
  • Scanned or image-only pages are detected and reported, not converted (no OCR in this Actor).
  • Tables without ruling lines are recognised only when their columns line up cleanly; complex layouts (merged cells without lines, tables inside text columns, more than two columns of text) may come out as paragraphs. The quality report helps you find those pages.
  • Password-protected PDFs are not opened. Remove the password and run again.
  • Links behind a login, and social media or video sites, are not supported. When a server refuses access (401, 403 or a bot check), or a link returns a login page instead of the file, the document gets an error row; the Actor never tries to get around it. Use a public or signed link, or upload the file.
  • Charts and images are not described; their count is in the quality report.

Privacy and data handling

  • Your documents are processed only to produce your results. We act as a processor for the files you send.
  • Documents are processed in memory during the run and stored only in the run's own default dataset and key-value store, which you control and can delete. Nothing is kept elsewhere and nothing is used for training.
  • Document content is never written to the run log; the log shows only input numbers, formats, page counts and error codes.
  • markdown_file_url and blocks_file_url are shareable links: anyone who has one can read that file without an Apify token. They appear only on the document (or notice) row, never on chunk rows, so they do not travel into your vector store with every chunk.
  • Treat the output as untrusted text, like the documents it comes from: sanitise it before you render it as HTML. Tag-like text from documents is escaped (< becomes &lt;) and link targets are encoded, but Markdown renderers differ.
  • Query strings of links (for example signed-link tokens) are removed before the source is stored in your results.
  • The Actor runs with limited permissions: it reads your input, your uploaded files and the key-value store you name, and writes only to the run's own storages. Links you paste are downloaded without your Apify token, even when they point to Apify storage.
  • Downloads identify themselves as QuarrywiseBot/1.0 (+https://quarrywise.com/bot) and refuse private and internal network addresses.

FAQ

What does "needs OCR" mean? The page has no usable text layer: it is a scan, a photo, or uses fonts whose text cannot be read. Such pages are listed in pages_needing_ocr, explained in the warnings, and not charged. Run them through an OCR tool first.

How are tokens counted? token_estimate uses about 4 characters per token, a common rule of thumb for English text. It is an estimate, not a count from a specific tokenizer.

Why does a Word or Excel file count as several pages? These formats have no fixed pages, so every 3,000 characters of output count as one page. A short memo is one page. In tables only filled cells count, so empty cells in a sparse sheet cost nothing.

Can I convert files from cloud storage? Yes: use a signed link, or put the files in an Apify key-value store and pass keyValueStoreId and fileKeys.

Is the output the same every time? Yes. The same file with the same settings gives the same Markdown, blocks and chunks, and the same document_id.

Which header and footer lines were removed? quality.furniture_removed_text lists each removed text once, so you can check that nothing of value went.

Why is a table split into paragraphs? The table probably has no ruling lines and uneven columns. Check the page in the quality report; complex tables are planned for a slower layout-model option.

Does this use Docling or MarkItDown? No. It runs its own layout code on pdfplumber, with no GPU and no models, and flags scans for OCR instead of returning empty text.

Do you keep my files? No. See Privacy and data handling above.

Changelog

See the Changelog tab. Version 0.1 (2026-10-26): first release.

Provider

Provided by Quarrywise, a trade name of Picazzo Research & Development, Zinkstraat 24, Box C4687, 4823 AD Breda, the Netherlands. KvK 42060545, VAT NL005464235B85. Contact: hello@quarrywise.com or the Issues tab.