How to convert PDF, Word and PowerPoint files to text and Markdown in bulk
Short answer
Send the document links to a converter that reads the PDF text layer page by page, keeps headings, lists and tables as Markdown and reads two-column papers in order. Pageshuck on Apify does this for PDF, Word and PowerPoint files at $0.003 per document, with no start fee; failed and scanned files are not charged.
- List the document URLs (PDF, DOCX or PPTX), one per row. Files up to 100 MB and 500 pages work by default.
- Pick the output: formats ["markdown", "text"], one row per document, or outputMode "pages" for one row per page with page numbers.
- For RAG, set chunkSize (for example 1500 characters): chunks end at paragraph and sentence breaks.
- Check status: ok, no-text (a scan, flagged needsOcr) or error (404, password-protected, too big). Only ok rows are charged.
- Schedule the same input with monitor on to get only new or changed documents later.
Copy-paste code
Python (pip install apify-client): PDF links in, Markdown files out
import os, pathlib
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("cybermax/pdf-to-text").call(run_input={
"urls": ["https://www.irs.gov/pub/irs-pdf/fw9.pdf", "https://arxiv.org/pdf/1810.04805"],
"formats": ["markdown", "text"],
"chunkSize": 1500,
})
out = pathlib.Path("md"); out.mkdir(exist_ok=True)
for i, r in enumerate(client.dataset(run["defaultDatasetId"]).iterate_items()):
if r["status"] == "ok":
(out / f"doc{i}.md").write_text(r["markdown"])
print(r["url"], r["status"], r.get("pageCount"), r.get("words"))JavaScript / Node (npm i apify-client)
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('cybermax/pdf-to-text').call({
urls: ['https://example.com/contract.docx', 'https://example.com/pitch.pptx'],
outputMode: 'pages',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const r of items) console.log(r.url, 'page', r.page, (r.text || r.error || '').slice(0, 80));No code: n8n, Make or Zapier
n8n: HTTP Request node (or the Apify node, action "Run an Actor and get dataset")
Method: POST
URL: https://api.apify.com/v2/acts/cybermax~pdf-to-text/run-sync-get-dataset-items
Auth: Header Auth -> Authorization: Bearer <your Apify token>
Body: JSON {"urls": {{ $json.pdfLinks }}, "formats": ["markdown"]}
Output: one n8n item per document (markdown, text, pageCount, words, metadata)
Make: Apify app -> "Run an Actor" (Actor: cybermax/pdf-to-text, wait for finish = yes)
-> Apify "Get Dataset Items" (dataset = the run's defaultDatasetId) -> your next module
Zapier: Apify app -> action "Run Actor" (cybermax/pdf-to-text, input JSON as above)
-> trigger "Finished Actor Run" -> "Fetch Dataset Items" -> your app
Runs longer than 5 minutes: start with POST /v2/acts/cybermax~pdf-to-text/runs and read the dataset when the run finishes.From an AI agent (MCP)
# Any MCP client (Claude Desktop, Claude Code, Cursor, VS Code): Apify's hosted MCP server
{
"mcpServers": {
"pdf-to-text": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://mcp.apify.com/?tools=cybermax/pdf-to-text",
"--header", "Authorization: Bearer ${APIFY_TOKEN}"],
"env": { "APIFY_TOKEN": "<your Apify token>" }
}
}
}
# The agent sees one tool, cybermax--pdf-to-text, with the Actor's input schema.| Document | Type | Pages | Words |
|---|---|---|---|
| IRS Form W-9 (fw9.pdf) | 6 | 6,525 | |
| BERT paper (arXiv, two columns) | 16 | 10,654 | |
| calibre demo.docx | docx | 3 | 1,650 |
Source: Pageshuck (Apify Actor cybermax/pdf-to-text) README, real Apify run on 10 Nov 2026
PDF to Markdown for RAG and LLMs
Plain text loses the structure a model needs. Markdown keeps headings, bullet lists and tables, so chunks split on real sections and tables stay readable. Pageshuck also rejoins words split across lines and puts two-column research papers back in reading order.
Word and PowerPoint in the same run
DOCX and PPTX links go in the same list as PDFs and come back in the same shape: Markdown, text, page or slide count, words and document metadata.
Scanned PDFs need OCR
A scan has no text layer. Pageshuck flags it with needsOcr and does not charge a fully scanned file; export those pages as images and read them with Inkscry, the CyberMax image-to-text OCR Actor.
Good to know
Price on Apify: $0.003 per document ($3 per 1,000), no start fee and no per-page fee. Failed, password-protected and fully scanned files are free. Apify's free plan includes $5 of usage each month.
Use it on documents you own or are allowed to process; it converts only the files you link to.
Docsieve: Websites to clean Markdown for RAG
$0.001 per page, no start feeConverting web pages rather than files? Docsieve crawls a website or docs site into clean Markdown, RAG chunks and llms.txt at $0.001 per page.
Runs on your own Apify account, pay per result; failed results are not charged.Questions
Does it keep tables?
Yes. Tables come out as GitHub Markdown tables in the markdown field, and as tab-separated cells in text.
Can I get one row per page?
Yes. Set outputMode to pages for one row per page with its page number, useful for citations.
How big can a file be?
Up to 100 MB and 500 pages by default; raise maxFileSizeMb (300 max) and maxPages (5,000 max). The price per document stays the same.
Can an AI agent use it?
Yes. Apify's MCP server exposes it as cybermax--pdf-to-text for Claude, Cursor and other MCP clients.
Free: the Free API Starter Kit
Copy-paste calls for 4 APIs with free daily tiers (CVE priority, VIN recalls, US duty rates, email checks), then 5 short emails on KEV/EPSS, MCP and free data.