PDF Text Extractor - Markdown, Tables & RAG Chunks
Pricing
from $0.24 / 1,000 page extracteds
PDF Text Extractor - Markdown, Tables & RAG Chunks
Extract text from PDF to clean Markdown with real tables, headings and lists. Bulk PDF to text conversion for RAG, LLM and vector database ingestion, with optional context-aware chunking. Detects scanned PDFs, handles encrypted files and broken URLs. Pay only for documents extracted.
Pricing
from $0.24 / 1,000 page extracteds
Rating
0.0
(0)
Developer
HJL Analytics and AI development
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Convert PDFs into clean, structured Markdown that a language model can actually use. Headings, tables and lists survive the conversion. Optional retrieval-ready chunks come with their heading breadcrumb attached.
Built for RAG pipelines, vector databases and LLM ingestion, where the quality of your retrieval is capped by the quality of your text extraction.
Why most PDF extractors are not good enough for RAG
Most tools call extract_text() and hand you the result. That produces three
problems you only notice after your retrieval quality is already bad:
| Problem | What it does to your pipeline |
|---|---|
| Tables flattened into prose | Region North 1200 48000 South 900 36000 embeds as numeric noise. The relationship between a number and its column header is destroyed. |
| No heading structure | A chunk reading "The limit is 40 hours." is unretrievable. Which limit? Which policy? The section title held that context and it was thrown away. |
| Running headers on every page | "ACME Holdings Confidential — Page 4 of 60" repeated into 60 chunks, diluting every embedding. |
| Hard line wrapping kept | Sentences arrive broken mid-clause, so chunk boundaries land in the middle of ideas. |
This Actor addresses each of them.
What it does
Real Markdown structure
Headings become #/##/### by comparing font sizes to the document's body
size — not by guessing from capitalisation. Lists become - items.
Paragraphs are rebuilt from wrapped lines, with hyphenation rejoined.
Tables that stay tables
Tables are detected, rendered as Markdown tables, and — crucially — their text is removed from the prose flow, so table content is never emitted twice.
Two detection paths run:
- Ruled tables — standard grids with visible borders.
- Borderless "booktabs" tables — the academic and analyst-report style with horizontal rules only and no vertical lines. Most extractors miss these entirely and flatten them into prose. Columns are recovered from the vertical whitespace corridors a human reader's eye uses.
Spurious grids are rejected: a bordered callout box is not a one-column table, and a dense figure is not a 59-column one. When a grid is rejected its text is still returned as prose — content is never silently dropped.
RAG chunking with context
Enable chunkForRag and each chunk arrives with the heading trail that
locates it:
{"index": 12,"breadcrumb": "Employee Handbook > Leave Policy > Parental Leave","headings": ["Employee Handbook", "Leave Policy", "Parental Leave"],"text": "Employees are entitled to 16 weeks...","page": 7}
- Chunks never cross a heading, so one chunk never mixes two sections.
- Each carries its breadcrumb, so it stays meaningful once embedded.
- Paragraphs and tables are never split mid-way.
- Overlap keeps facts that straddle a boundary retrievable, and is never carried across a section break.
Clean-up you would otherwise write yourself
- Running headers and footers detected and stripped (page numbers normalised, so "Page 1 of 12" and "Page 7 of 12" are recognised as the same furniture).
- Rotated margin text — arXiv stamps, spine labels, watermarks — excluded rather than dropped mid-sentence into your abstract.
- Multi-column pages read column by column, not straight across the gutter.
- Word spacing repaired on tightly-kerned PDFs that otherwise return
Providedproperattributionisprovided.
Built for batches
One row per document. A password-protected, corrupt, oversized or 404'd file
returns a row with status: "error" and a reason — it never aborts the
run. Scanned PDFs are flagged with isScanned: true and a warning rather
than silently returning nothing.
How to use it
- Paste one or more direct PDF URLs into PDF URLs. Anything you can link to works — a file on your own server, an S3 or Drive direct link, a published report.
- Choose an output format: Markdown keeps headings, lists and tables; plain text strips all markup; Both returns each in its own field.
- Turn on RAG chunks if the text is going into a vector database. Each chunk carries the heading breadcrumb it sits under, so an embedding keeps its context.
- Start the run. Results appear as one dataset row per document.
Every run is a normal Apify run, so you can schedule it, trigger it from the API, or wire it into Make, Zapier, LangChain or LlamaIndex.
Pricing
You are charged only for documents that extract successfully — a small per-document fee plus a per-page fee. Failed downloads, encrypted files, corrupt PDFs and 404s are not charged. A run that extracts nothing costs nothing.
Pricing per page rather than a flat fee per file means a two-page invoice costs a fraction of a 300-page annual report, instead of subsidising it.
Input
| Field | Type | Default | Description |
|---|---|---|---|
pdfUrls | array | — | Required. Direct links to the PDFs. |
outputFormat | string | markdown | markdown, text, or both. |
extractTables | boolean | true | Detect tables and render them as Markdown. |
chunkForRag | boolean | false | Also return retrieval-ready chunks. |
chunkSize | integer | 1500 | Soft character ceiling per chunk. |
chunkOverlap | integer | 150 | Characters repeated between chunks. |
includeMetadata | boolean | true | Return title, author, dates, producer. |
maxPagesPerDocument | integer | 0 | Stop after N pages. 0 = no limit. |
password | string | — | Password for encrypted PDFs. |
Example
{"pdfUrls": ["https://example.com/annual-report.pdf","https://example.com/policy.pdf"],"outputFormat": "markdown","extractTables": true,"chunkForRag": true,"chunkSize": 1200}
Output
One dataset item per document:
{"url": "https://example.com/annual-report.pdf","filename": "annual-report.pdf","status": "ok","error": null,"pageCount": 15,"tableCount": 4,"isScanned": false,"markdown": "# Annual Report\n\n## Executive Summary\n\n...","metadata": { "Title": "Annual Report 2026", "Author": "ACME" },"chunks": [ { "index": 0, "breadcrumb": "...", "text": "...", "page": 1 } ],"chunkCount": 37}
Failed documents:
{"url": "https://example.com/missing.pdf","filename": "missing.pdf","status": "error","error": "http 404"}
Limitations — stated up front
- Scanned PDFs are not OCR'd. If a page has no text layer there is
nothing to extract. Those documents return
isScanned: trueand a warning so you can route them elsewhere, rather than silently returning nothing. - Dense interactive forms (tax forms, application forms) extract far less cleanly than reports, papers and manuals. Their content is laid out as positioned fields rather than as a reading flow.
- Multi-row table headers are returned as separate rows rather than being merged into one header.
- Text is extracted in the document's own language; nothing is translated.
Common uses
PDF for LLM and RAG pipelines: loading documentation, reports, contracts, research papers, manuals and policies into a vector database as PDF RAG chunks, each carrying the heading it sits under so a retrieved chunk keeps its context. Building a RAG knowledge base from a document set.
Also common: multi page PDF extraction across long manuals and reports; contract PDF extraction and form PDF extraction, where field labels and table cells have to survive; pulling invoice PDF text and line items as structured rows; extracting tables from PDFs; bulk PDF to Markdown conversion for static sites and wikis; and PDF to clean text when you want no markup at all.
Encrypted PDF files open with a supplied password. When one cannot be
read it is reported with the reason and charged nothing.
Integrations
Standard Apify output: pull results via the API, export to JSON/CSV/Excel, schedule runs, or connect to Make, Zapier, LangChain, LlamaIndex and other Apify integrations.
FAQ
Is this legal? Yes. You supply documents you already have the right to use, and the Actor extracts them. No third-party website is accessed, no terms of service are involved, and no proxies are used.
How much will a run cost? You are charged per page successfully extracted. A 40-page report costs $0.016; a 300-page manual costs $0.12. Pricing is per page rather than per file on purpose — extraction cost scales with pages, so a flat per-file price would either overcharge short documents or lose money on long ones.
What happens if one document in my batch fails?
Only that document. It appears in the dataset with status: "error" and the
reason, the rest of the batch continues, and you are not charged for it.
It returned nothing for my PDF. Why?
Check isScanned and the warning field. A scanned PDF is an image with no
text layer, so there is nothing to extract without OCR. The Actor detects this
and says so rather than silently returning an empty string.
How is this different from a plain text extractor? A naive extractor returns a wall of text: no headings, no tables, and words welded together across line breaks. On a real research paper this Actor recovers 16 headings and 4 tables where the naive baseline finds none, and removes several hundred welded words. Tables come out as real Markdown tables, not as scattered numbers.
Can I get the data out programmatically? Yes — the standard Apify dataset API, plus JSON, CSV and Excel export. Every output field is described in the dataset schema, so tools and AI agents can read the structure without guessing.
Other Actors by this author
| Actor | What it does |
|---|---|
| Audio & Video Transcriber — Speech to Text, SRT & Timestamps | The same idea for recordings: Whisper speech-to-text on your own audio and video, with timestamps, SRT/VTT subtitles and the same RAG chunking. Pairs naturally with this Actor when a knowledge base mixes documents and recordings. |