PDF, DOCX & PPTX to Markdown Converter for AI & RAG
Pricing
from $5.00 / 1,000 converted documents
PDF, DOCX & PPTX to Markdown Converter for AI & RAG
PDF to Markdown, DOCX to Markdown and PPTX to Markdown converter for AI and RAG: turns PDF, Word, PowerPoint and HTML files into clean Markdown with tables kept as Markdown tables, page and slide numbers, metadata and optional RAG chunks. Optional OCR for scanned PDFs. URLs or file upload.
Pricing
from $5.00 / 1,000 converted documents
Rating
0.0
(0)
Developer
FedSignals Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
PDF to Markdown, DOCX to Markdown and PPTX to Markdown in one Actor. Give it links to documents (or upload a file) and get back clean, AI-ready Markdown: headings, lists and tables preserved as Markdown tables, page and slide numbers kept as <!-- page: N --> (PowerPoint: <!-- slide: N -->) markers, document metadata (title, subject, creation and modification dates, page count), and optional RAG chunks with configurable size and overlap, each tagged with its page range and heading path. Scanned PDFs can be read with optional OCR.
It's built for RAG pipelines, LLM ingestion, knowledge bases, search indexing and document analysis. Feed the chunk rows straight into a vector database, or download the full .md files.
Supported formats
| format | how it is read | "page" means |
|---|---|---|
| text layer with layout-aware headings (font size), paragraph and hyphenation repair, ruled tables as Markdown tables; rotated margin text is dropped | one PDF page | |
| PDF, scanned | OCR with Tesseract (optional, ocr: auto or always) | one PDF page |
| DOCX (Word) | headings, lists, tables, links | 3,000 characters of output (estimated page) |
| PPTX (PowerPoint) | slide titles, text, tables, notes | one slide |
| HTML | main content, headings, tables, links | 3,000 characters of output (estimated page) |
| plain text | as is | 3,000 characters |
The file type is detected from the bytes, so links without an extension work. Legacy .doc/.ppt and spreadsheets are rejected for free with a clear message.
Example input
{"urls": ["https://www.irs.gov/pub/irs-pdf/fw9.pdf", "https://arxiv.org/pdf/1706.03762"],"ocr": "off","chunkSize": 1000,"chunkOverlap": 100,"chunkOutput": "rows"}
Example output
One document row per input:
{"recordType": "document", "docId": "f4fbd1d654f7", "source": "https://www.irs.gov/pub/irs-pdf/fw9.pdf","fileName": "fw9.pdf", "fileType": "pdf", "status": "ok","title": "Form W-9 (Rev. March 2024)", "subject": "Request for Taxpayer Identification Number and Certification","createdAt": "2024-03-06T08:18:13", "pageUnit": "page", "totalPages": 6, "pagesProcessed": 6,"ocrPages": 0, "tables": 3, "charCount": 37882, "wordCount": 6522, "chunkCount": 47,"markdown": "<!-- page: 1 -->\n\n# W-9 Request for Taxpayer\n...","markdownKey": "f4fbd1d654f7.md", "markdownUrl": "https://api.apify.com/v2/key-value-stores/.../records/f4fbd1d654f7.md"}
and, when chunking is on with chunkOutput: "rows", one chunk row per chunk:
{"recordType": "chunk", "docId": "f4fbd1d654f7", "fileName": "fw9.pdf", "title": "Form W-9 (Rev. March 2024)","chunkIndex": 3, "chunkCount": 47, "pageStart": 1, "pageEnd": 1, "charCount": 766,"headings": ["Part I Taxpayer Identification Number (TIN)"],"text": "### Part I Taxpayer Identification Number (TIN)\n\nEnter your TIN in the appropriate box..."}
A ruled PDF table comes out as a Markdown table (W3C example PDF):
| Disability Category | Participants | Ballots Completed | Ballots Incomplete/ Terminated | Results Accuracy | Time to complete || --- | --- | --- | --- | --- | --- || Blind | 5 | 1 | 4 | 34.5%, n=1 | 1199 sec, n=1 |
The full Markdown of every document is also saved as <docId>.md in the run's key-value store, so you never lose content when the inline copy is turned off or capped.
| status | meaning | charged? |
|---|---|---|
ok | converted | yes: one document fee (covers 10 pages), plus extra and OCR pages |
download_error | 404, timeout, or file above maxFileSizeMb | no |
unsupported | not a PDF/DOCX/PPTX/HTML/text file | no |
conversion_error | the file is damaged or encrypted | no |
no_pages / skipped | the page or spending limit was reached | no |
Live test results (Oct 29, 2026)
A local run against 12 real public documents (IRS forms and publications, an arXiv paper, a W3C table example, a scanned 1960s archive memo, US government and NIH Word templates, a PowerPoint deck, a Wikipedia article, plus a spreadsheet and a broken link) finished in 26 seconds with OCR on auto:
- 10 converted, 1
unsupported(the XLSX), 1download_error(the 404). - 243 pages (242 text pages + 1 OCR page) and 823,500 characters of Markdown. A 59-page IRS publication with 13 tables took 7.4 s, and a 67-page Word protocol template took 11 s.
- 47 tables kept as Markdown tables: 23 from PDFs (IRS W-9: 3, arXiv: 6, IRS Pub 15: 13, W3C: 1) and 24 from Word, PowerPoint and HTML.
- The scanned memo had no text layer. It was flagged with a warning when OCR was off, and OCR returned 637 characters from it (the scan is low quality, so expect noisy text on old documents).
- Chunking at 1,500 characters with 150 characters of overlap produced 741 chunks (median 1,381 characters, all within size plus overlap). 96% of them carry a heading path.
Use cases
- RAG and AI assistants. Turn policy PDFs, manuals and contracts into chunks with page citations.
- LLM preprocessing. Markdown is far cheaper in tokens than raw HTML and keeps the structure models need.
- Knowledge bases and search. Index slide decks and Word documents by heading and page.
- Document analysis. Use the metadata, page counts, table counts and word counts.
Input options
urls: links to documents, or keys of records in the run's default key-value store.fileUrl: upload a file from your computer.ocr:off(default),auto(only PDF pages without a text layer) oralways.ocrLanguage: English, German, French, Spanish, Portuguese, Italian, Dutch, or mixed English with Spanish, French or German.tables(default on): detect ruled tables in PDFs.pageMarkers(default on): add<!-- page: N -->markers (<!-- slide: N -->for PowerPoint).keepImageLinks(default off): keep image links (embedded image data is never copied).markdownInDataset(default on): include the Markdown in the dataset row.chunkSize(0 = off),chunkOverlap(default 200), andchunkOutput(rowsorinline).maxPagesPerDocument(default 500),maxTotalPages(0 = no limit), andmaxFileSizeMb(default 50).maxConcurrency(1-4, default 2) andtimeoutSec(download timeout, default 60).
Known limits
- Layout. PDF text is read line by line. Multi-column layouts and form-style pages, such as tax forms, can interleave text from neighbouring columns. Headings are detected from font size, so they are a good guide but not perfect.
- Tables. PDF tables are found from ruling lines. Tables without borders come out as text. Complex merged-cell headers are flattened. A table row longer than the chunk size is split as text.
- OCR is Tesseract at 300 dpi. It works well on clean scans, but on faxes, handwriting and stamps it is noisy. It costs $0.01 per OCR page. OCR is CPU-heavy, so run scanned batches with 4 GB of memory (one full CPU core): in a live test on Oct 30 it OCR'd dense pages in about 14-15 seconds each. At the default 1 GB (a quarter of a core) the same 6-page form did not finish in 150 seconds, so expect it to be roughly four times slower there and set a longer run timeout.
- Estimated pages. DOCX and HTML have no fixed pages, so page numbers there are 3,000-character estimates, not the page numbers Word would print.
- Not supported: legacy
.doc/.ppt, spreadsheets, password-protected PDFs, and images embedded inside DOCX/PPTX (only their alt text is kept). JavaScript-rendered web pages are read as served, without running scripts. - No personal-name metadata. The author, creator and last-modified-by fields in document properties often contain people's names, so the Actor deliberately leaves them out. Text in the document body is converted as is.
- Your links, your responsibility. The Actor downloads exactly the links you provide, identifying itself as
FedSignalsBot. It doesn't crawl or follow links, and it doesn't checkrobots.txt, because these are direct file requests that you make. Only convert documents you're allowed to process.
Licenses
The Actor uses permissively licensed open-source components only (no GPL/AGPL): pdfplumber and pdfminer.six (MIT), pypdfium2 (Apache-2.0/BSD-3), Microsoft MarkItDown (MIT) with mammoth (BSD-2) and python-pptx (MIT), Tesseract OCR (Apache-2.0) via pytesseract (Apache-2.0), and httpx (BSD-3).
How much does it cost?
Pay per event: you pay only for the events below plus Apify's $0.00005 run-start fee. Platform compute is included in the price.
- $0.005 per document converted ($5 per 1,000 documents), including its first 10 pages.
- $0.001 per extra page after the first 10 pages of a document ($1 per 1,000 pages).
- $0.01 per OCR page, charged separately and only when OCR is on and a page is actually OCR'd. A scanned-only document pays OCR pages only, with no document fee.
- Free: failed, unsupported and empty documents, and empty pages.
Real examples from our test runs:
- Quick-start input (IRS W-9, 6 pages): 1 document = $0.005.
- A 59-page IRS publication: $0.005 + 49 extra pages × $0.001 = about $0.054.
- A $0.01 spending limit on the W-9 plus the 59-page publication (live run, Oct 30): the publication converted its first 14 pages and stopped cleanly, and the W-9 was not started or charged: $0.005 + 4 extra pages × $0.001 + $0.00005 start = $0.00905. Which document gets the budget first depends on download order.
- A scanned page with OCR: $0.01 per OCR page, charged separately and not part of the 10 included pages.
- 4 scanned pages with OCR at 4 GB (live run, Oct 30): 4 × $0.01 + Apify's start fee, which is $0.00005 per GB of memory (4 × $0.00005) = $0.0402.
- 1,000 typical documents of 10 pages or fewer: $5.
Use maxTotalPages, maxPagesPerDocument and Apify's per-run spending limit to cap spend; the Actor stops cleanly when the limit is reached.
Dates, time zones and currency
processedAtis ISO 8601 in UTC (Z).createdAtandmodifiedAtcome from the file's own metadata and keep whatever time zone the file stored; many files store none.
Other languages and regions
OCR (ocrLanguage) supports English, German, French, Spanish, Portuguese, Italian and Dutch, plus English mixed with Spanish, French or German.
Also searched as: convertir PDF a Markdown, OCR (ES) · converter PDF em Markdown, OCR (PT) · convertir PDF en Markdown (FR) · PDF in Markdown umwandeln (DE).
FAQ
Which formats are supported?
PDF (text and, with OCR, scanned), DOCX, PPTX, HTML and plain text. Legacy .doc/.ppt, spreadsheets and password-protected PDFs are rejected for free.
Can I feed the output into a vector database?
Yes. Set chunkSize (for example 1500) and each chunk becomes its own row with page range and heading path.
Where is the full Markdown?
In each document row (unless you turn off markdownInDataset) and always as a .md file in the run's key-value store, linked by markdownUrl.
Does it output author names?
No. Author, creator and last-modified-by metadata are deliberately left out.
Reliability
Measured on Apify as of Oct 29, 2026: 4 of 4 of our own test runs succeeded (100%), with a median run time of 7 seconds (longest 10 s) on small test inputs. It is a small sample from a new Actor; we will update it as runs accumulate. Local tests: 12 real documents in 26 seconds; all 10 supported files converted, 243 pages and 47 tables.
Use it from AI agents (MCP)
Add this Actor as a tool in Claude Desktop, Cursor or any MCP client through the Apify MCP server:
{"mcpServers": {"documents-to-markdown": {"url": "https://mcp.apify.com?tools=fedsignals/documents-to-markdown","headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" }}}}
Use it from code (API)
One call runs the Actor and returns the dataset items. maxTotalChargeUsd caps what the run can charge.
Python:
import requestsitems = requests.post("https://api.apify.com/v2/acts/fedsignals~documents-to-markdown/run-sync-get-dataset-items",params={"maxTotalChargeUsd": 1},headers={"Authorization": "Bearer YOUR_APIFY_TOKEN"},json={"urls": ["https://www.irs.gov/pub/irs-pdf/fw9.pdf"]},timeout=300,).json()print(len(items), "items")
JavaScript (Node 18+):
const res = await fetch("https://api.apify.com/v2/acts/fedsignals~documents-to-markdown/run-sync-get-dataset-items?maxTotalChargeUsd=1",{method: "POST",headers: { Authorization: "Bearer YOUR_APIFY_TOKEN", "Content-Type": "application/json" },body: JSON.stringify({"urls": ["https://www.irs.gov/pub/irs-pdf/fw9.pdf"]}),});const items = await res.json();console.log(items.length, "items");
Related FedSignals Actors
- Lever & Ashby Jobs Scraper: Career Site Job Feed: jobs straight from company career sites
- Website Contact Scraper & Company Enrichment (Tech Stack): company data, tech stack and generic contacts from a domain
- SEC Form D Scraper: EDGAR Startup Funding Rounds: new private funding rounds from SEC Form D filings
Feedback
Found a bug or need a filter or source? Open an issue on the Issues tab or email fedsignals.alerts@gmail.com.
This Actor is not affiliated with or endorsed by Adobe, Microsoft or the publishers of the sample documents.