PDF to Markdown for RAG & LLMs (tables, no API key needed) avatar

PDF to Markdown for RAG & LLMs (tables, no API key needed)

Pricing

from $3.00 / 1,000 document pages

Go to Apify Store
PDF to Markdown for RAG & LLMs (tables, no API key needed)

PDF to Markdown for RAG & LLMs (tables, no API key needed)

Convert PDFs to clean structured Markdown for RAG and LLM ingestion. Preserves tables. Flat $0.004/page, no API key required.

Pricing

from $3.00 / 1,000 document pages

Rating

0.0

(0)

Developer

Fabio Suizu

Fabio Suizu

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

PDF to Markdown for RAG & LLMs — Tables Preserved, $0.004/page, No API Key Needed

Turn any PDF URL into clean, structured Markdown that is ready to feed into RAG pipelines, vector databases, and LLM prompts — with zero setup.

Paste PDF links. Press Start. Get Markdown with real headings, lists, and actual Markdown tables instead of collapsed text soup. That's it.

No LlamaParse key. No Reducto contract. No OpenAI account. No monthly subscription. You pay a flat $0.004 per page through Apify — everything else is included.


Why this Actor?

Every serious RAG or agent pipeline hits the same wall: PDFs. Naive extractors (pypdf, pdftotext) destroy tables, shuffle multi-column layouts, and drop heading structure — and your retrieval quality dies with them. The dedicated parsing APIs (LlamaParse, Reducto, Unstructured) fix that, but they make you sign up for another account, another API key, another bill.

This Actor runs on a managed document-parsing backend — the key is built in.

This ActorLlamaParseReductoDIY (pypdf & friends)
Requires your own API keyNo — works out of the boxYes (LlamaCloud key + credits)Yes (sales contact)
Price per page$0.004 flat$0.003–$0.056 depending on mode~5× more"Free" + your engineering time
TablesReal Markdown tablesMode-dependentYesUsually destroyed
Headings & structureProper #/## hierarchyYesYesFlat text
SetupNone — paste URLsAccount, credits, SDKContract, integrationCode, maintenance
BillingPay per event — only pages actually convertedCredit packsEnterprise contract

A 20-page contract costs $0.08. A 300-page annual report costs $1.20. Failed documents are never charged.

What it does

  1. Downloads each PDF from any direct URL — public links, presigned S3/GCS URLs, or files stored in an Apify key-value store. Files are validated as real PDFs before processing (an HTML viewer page instead of a raw file produces a clear error, not garbage output).
  2. Parses the document with layout awareness: reading order is reconstructed (multi-column pages come out in the right sequence), headings become #/##/###, lists stay lists, and tables are emitted as GitHub-flavored Markdown tables — the single biggest quality lever for RAG over business documents.
  3. Outputs Markdown twice: inline in the dataset item (for API consumers and agents) and as a downloadable .md file in the run's key-value store (for humans and downstream jobs).
  4. Keeps going on failure: a dead link or corrupt file produces an { url, error } item; the rest of the batch is processed and only successful pages are charged.

Input

{
"sources": [
"https://slicedinvoices.com/pdf/wordpress-pdf-invoice-plugin-sample.pdf",
"https://example.com/reports/annual-report-2025.pdf"
],
"maxPages": 500
}
FieldTypeDefaultDescription
sourcesarray(required)URLs of PDF files: direct links or Apify key-value store record URLs
maxPagesinteger500Safety cap per document; larger documents produce an error item and are never charged

Output

One dataset item per source. Here is the result for the sample invoice above:

{
"url": "https://slicedinvoices.com/pdf/wordpress-pdf-invoice-plugin-sample.pdf",
"filename": "wordpress-pdf-invoice-plugin-sample.pdf",
"pages": 1,
"char_count": 731,
"charged_pages": 1,
"markdown": "# Invoice\n\n**From:** Sliced Invoices...",
"files": {
"md": "https://api.apify.com/v2/key-value-stores/<storeId>/records/001-slicedinvoices.com-pdf-wordpress-pdf-invoice-plugin.md"
}
}

And the Markdown itself — note the tables survive as tables:

# Invoice
**From:** Sliced Invoices — Suite 5A-1204, 123 Somewhere Street, Your City AZ 12345
**To:** Test Business — 123 Somewhere St, Melbourne VIC 3000
| Invoice Number | Order Number | Invoice Date | Due Date | Total Due |
| -------------- | ------------ | ---------------- | ---------------- | --------- |
| INV-3337 | 12345 | January 25, 2016 | January 31, 2016 | $93.50 |
| Service | Description | Hrs/Qty | Rate/Price | Adjust | Sub Total |
| ---------- | ------------------------------------ | ------- | ---------- | ------ | --------- |
| Web Design | New website design and development | 1.00 | $85.00 | 0.00% | $85.00 |
| Sub Total | $85.00 |
| --------- | ---------- |
| Tax | $8.50 |
| **Total** | **$93.50** |

That is exactly what you want in a vector store: an LLM can answer "what is the total due and when?" from this chunk directly, no layout guessing.

If a source fails (dead link, not a PDF, over the page cap), the run keeps going and the failed source produces:

{ "url": "https://example.com/broken-link.pdf", "error": "Could not download the file: HTTP 404" }

Pricing

$0.004 per converted page, minimum 1 page per document. Billed via Apify's pay-per-event — no subscription, no credit packs, no compute-unit math.

WorkloadCost
1-page invoice$0.004
20-page contract$0.08
300-page annual report$1.20
1,000 × 2-page invoices$8.00
Same annual report on LlamaParse Premium (~$0.045/page) + a LlamaCloud account$13.50 and two invoices

Documents that fail to download or convert are never charged. Documents over your maxPages cap are never charged.

Use it via API

Run the Actor from any language using the Apify API:

curl -X POST "https://api.apify.com/v2/acts/<username>~pdf-to-markdown-for-rag/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "sources": ["https://slicedinvoices.com/pdf/wordpress-pdf-invoice-plugin-sample.pdf"] }'

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('<username>/pdf-to-markdown-for-rag').call({
sources: ['https://slicedinvoices.com/pdf/wordpress-pdf-invoice-plugin-sample.pdf'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].markdown);

Python (drop-in for a RAG ingestion job):

from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("<username>/pdf-to-markdown-for-rag").call(
run_input={"sources": ["https://slicedinvoices.com/pdf/wordpress-pdf-invoice-plugin-sample.pdf"]}
)
for item in client.dataset(run["defaultDatasetId"]).list_items().items:
chunks = split_markdown(item["markdown"]) # your chunker
vector_store.add(chunks, metadata={"source": item["url"]})

Use it from AI agents (MCP)

This Actor works out of the box with the Apify MCP server, so agents built on Claude, ChatGPT, Cursor, or any MCP-compatible framework can call it as a tool:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com/sse?actors=<username>/pdf-to-markdown-for-rag"
}
}
}

Your agent can turn any PDF a user shares into LLM-ready Markdown with no API key juggling inside the agent — this Actor needs none, and pay-per-event billing means you are only ever charged for pages actually converted.

FAQ

Do I need a LlamaParse / Reducto / OpenAI API key? No. That is the point of this Actor. Parsing runs on a managed backend whose credentials are bundled with the Actor. You only need your Apify account.

Why Markdown and not plain text or JSON? Markdown is the lingua franca of LLM ingestion: heading hierarchy gives your chunker natural split points, tables stay machine-readable, and every major framework (LangChain, LlamaIndex, Haystack) has first-class Markdown loaders. Plain text loses structure; per-block JSON makes you rebuild it.

How are tables handled? Tables are detected from the page layout and emitted as GitHub-flavored Markdown tables (pipes and header rows), not as space-aligned text. Merged or deeply nested table cells are flattened on a best-effort basis.

Does it work on scanned PDFs? Digital (text-based) PDFs give the best results. Scanned pages are processed through the backend's visual document understanding, so typical scanned invoices and contracts work; very low-quality scans may reduce accuracy.

Which languages are supported? The parser is language-agnostic for Latin-script languages and handles the major non-Latin scripts (CJK, Cyrillic, Arabic) as long as the PDF carries proper text or a legible scan.

How long does a conversion take? Simple digital PDFs process in seconds. Heavy, scan-based, or very large documents can take up to ~20 seconds per page; each document has a generous 20-minute processing budget.

What are the size limits? Up to 1 GB per file download and maxPages pages per document (default 500, configurable up to 10,000). Anything over a limit produces an error item and is never charged.

What happens when one URL in my batch is broken? The run continues. The broken URL produces a { url, error } item in the dataset; all other documents are processed and only successful pages are charged.

Where is my Markdown file? Twice in the run: inline in the dataset item (markdown field) and as a downloadable .md file in the run's key-value store — each item links to it under files.md.

Can I convert DOCX, PPTX, or HTML? This Actor is tuned for PDF. For other formats, print/export them to PDF first (most converters do this losslessly) and pass the resulting URL.

Is my document stored? Documents are processed transiently and deleted from the worker after conversion. The resulting Markdown lives in your Apify dataset/key-value store, under your control.

  • Build RAG knowledge bases from contracts, reports, manuals, and research papers
  • Feed clean document context to AI agents (Claude, ChatGPT, custom LLM apps) via MCP
  • Extract invoice and financial-statement tables into readable, diffable Markdown
  • Preprocess PDF corpora for fine-tuning or embedding pipelines
  • Archive PDFs as searchable, greppable, version-controllable Markdown