PDF Text Extractor & Document to Markdown (Word, Excel, PPT)
Pricing
from $2.50 / 1,000 document converteds
PDF Text Extractor & Document to Markdown (Word, Excel, PPT)
Extract text from PDF, Word, PowerPoint, Excel, HTML and EPUB files as clean Markdown for AI. PDF to Markdown, DOCX to text, OCR for scanned PDFs and images in 32 languages, plus free chunking for RAG and vector databases. Never charges for a failed or empty result.
Pricing
from $2.50 / 1,000 document converteds
Rating
0.0
(0)
Developer
Pavel Tashev
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
24 days ago
Last modified
Categories
Share
What does PDF Text Extractor & Document to Markdown do?
This Actor extracts text from PDF, Word (DOCX), PowerPoint (PPTX), Excel (XLSX), HTML, EPUB, CSV, JSON and XML files and returns it as clean, LLM-ready Markdown. Scanned PDFs and images (PNG, JPG, TIFF, WebP, BMP) are read with built-in OCR. Use it as a bulk PDF text extractor, a PDF to Markdown converter, an OCR tool for scans or a document parser for AI pipelines. Give it a list of file URLs — or paste the files themselves — and it returns one result per document: the Markdown text, the document title, file type, word count and how many pages were read with OCR.
It is built for RAG pipelines, AI agents, search indexing and knowledge bases, where you need the text of many documents in one consistent format. Because it runs on the Apify platform, you get API access, scheduling, webhooks, integrations (Make, Zapier, n8n, LangChain, LlamaIndex) and run monitoring out of the box.
You are never charged for a failed or empty result
Every result says what it is, and only real results cost anything.
status | Meaning | Charged |
|---|---|---|
success | The document was converted | Yes |
empty | The file opened but held no text — a scan with OCR off, or a page needing a login | No |
failed | Could not be done — the error field says why | No |
skipped | Not attempted, for example after the maximum cost per run was reached | No |
If every input fails, the run itself fails with an explanation instead of reporting success with no data.
Why use this PDF text extractor?
- One tool for every common format. No separate PDF, Word and PowerPoint parsers to maintain.
- Markdown keeps structure. Headings, lists and tables survive the conversion, so chunking and embeddings work better than with flat text.
- Excel sheets become Markdown tables that language models can read directly.
- OCR for scanned PDFs and images, with no Google and no external APIs. Pages without a text layer are read with the open-source Tesseract engine inside your run, in 32 languages. Pages are cleaned up before reading (grayscale, thresholding, automatic handling of light-on-dark pages), which makes text sharper and OCR faster. Your files never leave the run.
- Mixed PDFs just work. In a PDF with both text pages and scanned pages, only the scanned pages go through OCR, and the text stays in page order.
- Pay only for documents that convert. Downloads that fail, files that are too large and unsupported formats are never charged. OCR is charged only for pages where it found readable text.
- Batch friendly. Paste hundreds of URLs or upload a text file with one URL per line; files are processed in parallel.
Typical uses: feeding company documents into a chatbot, indexing research papers, extracting text from pitch decks and reports, digitizing scanned archives and receipts, preparing training or evaluation data, and giving AI agents a reliable "read this file" tool.
How to extract text from PDF and Word files
- Click Try for free.
- In File URLs, paste direct links to your documents (or upload a text file of URLs).
- Click Start.
- When the run finishes, open the Output tab. The Overview view lists every file and its status; the Markdown view shows the converted text.
- Download the results as JSON, CSV, Excel or HTML, or fetch them through the API.
Input
| Field | Description | Default |
|---|---|---|
| File URLs | Direct links to documents. Duplicates are removed automatically. | – |
| Include Markdown in output | Turn off to get only metadata (type, title, word count). | On |
| OCR mode | Auto reads images and PDF pages that have no text layer. Off never runs OCR (images fail, scanned pages come back empty). Force reads every PDF page with OCR, even pages that already have text. | Auto |
| OCR languages | Languages in your scans, 32 to choose from (see the list below). Pick up to 5. | English |
| Maximum OCR pages per file | OCR stops after this many pages in one file; the result is marked ocrTruncated. Maximum 500. | 200 |
| Split into chunks for RAG | Off, By headings (new chunk at every heading, with the heading path) or Fixed size. Chunking is free. | Off |
| Chunk size / overlap / minimum | Target chunk length in characters, how much text each chunk repeats from the previous one, and the shortest chunk kept on its own. | 1200 / 150 / 200 |
| Where to put the chunks | chunks array inside each document, or one dataset item per chunk. | In the document |
| Or paste files | Files as base64 instead of URLs, for documents that are not on the public web. [{"name": "report.pdf", "data": "<base64>"}] | – |
| PDF password | Opens password-protected PDFs | – |
| Start / End page | Read only pages from–to, counting from 1, end included | all |
| First N / Last N pages | Read only the beginning or only the end of a document | all |
| Maximum pages per file | A ceiling applied after the other page settings | – |
| Include per-page text | Also return each page separately, with its real page number | Off |
| Skip empty pages | Leave pages with no text out of the per-page output | Off |
| Remove running headers and footers | Strip lines that repeat near the top or bottom of most pages | Off |
| Remove page numbers | Strip lines that are only a page number | Off |
| Extract tables | Also return tables as rows and Markdown (see below) | Off |
| Maximum file size (MB) | Larger files are skipped and not charged. Maximum 100. | 50 |
| Files processed in parallel | Higher is faster but uses more memory. Maximum 8. | 5 |
Example input:
{"fileUrls": [{ "url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf" },{ "url": "https://calibre-ebook.com/downloads/demos/demo.docx" }],"includeMarkdown": true}
Output
Each document produces one item in the dataset:
{"url": "https://calibre-ebook.com/downloads/demos/demo.docx","fileName": "demo.docx","fileType": "docx","fileSizeBytes": 1311881,"title": "Text Formatting","markdown": "Demonstration of DOCX support in calibre\n\nThis document demonstrates ...","wordCount": 1703,"characterCount": 11139,"likelyScanned": false,"ocrPages": 0,"ocrLanguages": null,"ocrTruncated": false,"pageCount": null,"pagesRead": null,"pages": null,"tables": null,"tableCount": null,"status": "success","error": null,"processedAt": "2026-09-15T09:12:44.120Z"}
pageCount, pagesRead, pages, tables and tableCount are filled in for PDFs; they stay null for other
formats and when the matching setting is off.
A scanned page or image read with OCR looks like this (real output, text shortened):
{"url": "https://archive.org/download/aberpa.whittierjg.1887.statue/page/n10.jpg","fileName": "aberpa.whittierjg.1887.statue_0010.jpg","fileType": "jpg","fileSizeBytes": 686743,"title": "STATUE OF LIBERTY. ae","markdown": "STATUE OF LIBERTY. ae\n\nWAR DEPARTMENT, t\nWASHINGTON City, September 27, 1886.\n\nGENERAL: Among the requirements of the\nJoint Resolution of Congress, approved March 3, ...","wordCount": 204,"characterCount": 1226,"likelyScanned": false,"ocrPages": 1,"ocrLanguages": ["eng"],"ocrTruncated": false,"status": "success","error": null}
A file that cannot be converted is still listed, with "status": "failed" and a plain-language error such as "Download failed with HTTP 404 Not Found: the file was not found at this URL."
You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.
Output fields
| Field | Meaning |
|---|---|
url | The URL you provided |
fileName | File name from the server or the URL |
fileType | pdf, docx, pptx, xlsx, html, epub, csv, json, xml, txt, md, png, jpg, tiff, webp or bmp |
title | Document title from its metadata, or its first heading |
markdown | The converted text |
wordCount, characterCount | Size of the converted text |
likelyScanned | true when a PDF has pages without a text layer (scanned images) |
ocrPages | Number of pages or images where OCR found readable text (these are the charged OCR pages) |
ocrLanguages | OCR languages used, when OCR ran |
ocrTruncated | true when OCR stopped early because of Maximum OCR pages per file or your maximum cost per run |
chunkCount, chunks | Number of chunks and the chunks themselves, when chunking is on |
pageCount, pagesRead | Pages in the PDF, and how many were actually read after any page range |
pages | Per-page text with the real page number, when Include per-page text is on |
tables, tableCount | Tables as rows and Markdown, when Extract tables is on |
status, error | success, empty, failed or skipped, with the reason |
Read only the pages you need
Every page setting also lowers your bill, because you are charged per document converted and OCR is charged per page. "The first 10 pages of a 400-page report" costs a fraction of the whole thing.
| Setting | Example |
|---|---|
| Start / End page | startPage: 8, endPage: 10 reads pages 8, 9 and 10 |
| First N pages | firstNPages: 10 |
| Last N pages | lastNPages: 2 — the signature page of a contract |
| Maximum pages per file | a ceiling so one huge file cannot run away with the budget |
Turn on Include per-page text and each page comes back separately with its real page number, so a citation stays correct even when only a range was read:
{"pageCount": 15,"pagesRead": 3,"pages": [{ "page": 8, "text": "Table 2: The Transformer achieves better BLEU scores...", "wordCount": 421 },{ "page": 9, "text": "...", "wordCount": 380 }]}
Asking for pages that do not exist is reported as such rather than returning an empty document.
Cleaner text: headers, footers and page numbers
A running header, a footer and a page number appear on every page. Chunk such a document and that furniture lands in every chunk, where it drowns the real text in a retrieval index.
Remove running headers and footers finds lines that repeat near the top or bottom of most pages — it never
guesses by position, so a one-off heading is safe. Remove page numbers strips lines that are only a number,
such as 12 or Page 3 of 40. A long repeated line, such as a legal notice, is deliberately kept.
Password-protected PDFs
Put the password in PDF password and the file is read normally. Without it the document is reported as protected and not charged; with the wrong one you are told the password did not open it, which is a different problem with a different fix.
The password is stored with the run input rather than encrypted. That is a deliberate trade-off: this Actor runs with limited permissions, which is what lets AI agents pay for it directly, and at that level the platform cannot decrypt secret inputs. Use a document password you are comfortable storing.
Tables
Turn on Extract tables and tables come back both as rows and as Markdown, with the page they came from:
{"tableCount": 2,"tables": [{"page": 3,"rowCount": 6,"columnCount": 2,"rows": [["IF the entity/individual on line 1 is a(n)...", "THEN check the box for..."]],"markdown": "| IF the entity... | THEN check... |\n| --- | --- |"}]}
Where this works, plainly: ruled tables — invoices, forms, financial statements, statistical releases — where lines on the page mark the cells. Where it does not: the borderless tables common in academic papers, which parsers collapse into a single column of run-together text. Rather than hand you that as a "table", those are dropped, so a document can legitimately come back with no tables at all. That is why the setting is off by default.
Chunking for RAG
Vector databases and LLM prompts need documents split into pieces. Turn on Split into chunks for RAG and this Actor does it for you, at no extra cost — you still pay only per converted document (and per OCR page for scans).
- By headings starts a new chunk at every Markdown heading and records the heading path, so each chunk knows where it came from in the document. This is the better default for reports, manuals and contracts.
- Fixed size ignores structure and only follows the size limit.
- Code blocks and tables are never cut in the middle. A very long code block is split on line boundaries with the fence repeated, and a very long table is split on row boundaries with the header row repeated, so every chunk is valid Markdown on its own.
- Overlap repeats the last characters of the previous chunk, snapped to a sentence start, so a sentence split across two chunks is still findable.
approxTokensis a rough estimate: characters ÷ 4, rounded up. Use it to size prompts, not for billing.
Example input:
{"fileUrls": [{ "url": "https://calibre-ebook.com/downloads/demos/demo.docx" }],"chunkMode": "markdown","chunkSize": 800,"chunkOverlap": 100,"chunkOutput": "items","includeMarkdown": false}
One chunk from that run (real output, text shortened):
{"itemType": "chunk","chunkId": "489a13ca4f0bbe66","index": 1,"text": "e output format in the top right corner of the conversion dialog to EPUB or AZW3 and click **“OK”**.\n\n# Text Formatting\n…","charCount": 760,"approxTokens": 190,"headingPath": ["Text Formatting"],"startChar": 715,"endChar": 1378,"sourceUrl": "https://calibre-ebook.com/downloads/demos/demo.docx","fileName": "demo.docx","fileType": "docx","documentTitle": "Text Formatting"}
With One item per chunk, the dataset holds one "itemType": "document" row per file followed by its "itemType": "chunk"
rows, which imports straight into a vector database. With In the document, each document keeps a chunks array instead.
chunkId is stable: the same document and text always produce the same id, so re-runs can be de-duplicated.
How much does it cost to convert documents and scans to text?
This Actor uses pay-per-event pricing with two events. Chunking is free. See the Pricing tab for current prices.
- Document converted: a small fee for each document that converts successfully. Failed downloads and unsupported files cost nothing.
- OCR page: charged separately for each scanned PDF page or image where OCR found readable text. Text PDFs, Word, PowerPoint, Excel and the other text formats never use OCR, so they never incur this charge. Pages that OCR could not read (illustrations, blank scans) are not charged. If the first three pages of a scan come back unreadable, the rest are skipped: the file is returned as
emptywith a reason, and you pay nothing for it.
Platform compute is included in the price. You can set a maximum cost per run: the Actor OCRs only as many pages as your budget allows, marks the file ocrTruncated, and skips files it can no longer afford.
The Actor also watches the clock. It stops starting new files two minutes before the run timeout and lists the remaining URLs as skipped with a reason, so a run that runs out of time still returns everything it finished instead of being cut off mid-file. If you see that message, raise the run timeout or split the list across several runs.
Tips
- Use direct file links. A link to a "download page" returns that page's HTML, not the file.
- Choose the right OCR languages. Tesseract reads a language much better when it is selected. Add only the languages that appear in your documents; each one slows OCR down.
- Avoid OCR charges by setting OCR mode to Off when you only need text PDFs and office files.
- Force mode helps when a PDF has a broken or garbled text layer; it re-reads every page with OCR.
- OCR speed: about 1–2 seconds per page at the default memory. For large scanned batches, try 2–4 GB of memory so more pages can run in parallel.
- Large batches: keep parallel files at 5–10. Some servers rate-limit many simultaneous downloads.
- Metadata only: turn off Include Markdown in output to quickly check file types and sizes across many URLs.
- Building a RAG index? Turn on Split into chunks for RAG, set Where to put the chunks to One item per chunk, and turn off Include Markdown in output so the dataset holds only the chunks.
OCR languages
English, German, French, Spanish, Italian, Portuguese, Dutch, Polish, Bulgarian, Romanian, Czech, Slovak, Hungarian, Greek, Danish, Swedish, Finnish, Norwegian, Catalan, Russian, Ukrainian, Turkish, Arabic, Hebrew, Hindi, Japanese, Korean, Chinese (simplified), Chinese (traditional), Vietnamese, Thai and Indonesian.
Pick up to 5 per run. Tesseract reads a language much better when it is selected, and each extra language slows OCR down, so choose only the languages that actually appear in your documents.
Supported formats and limitations
- Supported: PDF (text and scanned), DOCX, PPTX, XLSX, HTML, EPUB, CSV, JSON, XML, TXT, MD, and images: PNG, JPG, TIFF (including multi-page), WebP, BMP.
- OCR works best on printed text in clean scans. It is weak on handwriting, phone photos taken at an angle, multi-column layouts and complex tables; reading order can differ from the visual layout. OCR text is plain paragraphs, without Markdown headings or tables.
- Not supported: legacy
.doc,.pptand.xlsfiles (save them as.docx,.pptx,.xlsxor PDF first), password-protected documents, HEIC photos, and languages outside the list above. Each of these fails with a plain-language message and is never charged. - HTML pages are converted as a whole, including navigation text. For clean article extraction from websites, use a web crawler Actor.
- Files that need a login or that block automated downloads cannot be fetched.
Related tools
Build a content or RAG pipeline with these tools:
- Audio & Video Transcriber: turn audio, video and podcast episodes into text and subtitles.
- RSS Feed Reader & Finder: read RSS, Atom and JSON feeds or find the feed of any website.
- Sitemap URL Extractor: list every URL of a website from its sitemaps, or only new and removed pages.
FAQ and support
Is my data stored? Documents are downloaded only for conversion. OCR runs inside your run with Tesseract; nothing is sent to Google or any other external API. Results are saved to your own Apify dataset, which you control.
Can I use this with AI agents? Yes. The Actor works through the Apify API and the Apify MCP server, so agents can call it as a document-reading tool.
Something doesn't convert correctly? Open an issue in the Issues tab with the file URL (if it is public) and what you expected. We respond to issues and usually ship fixes quickly.
Only convert documents you have the right to access and process.