PDF to AI-Ready Data (Markdown, Tables, RAG Chunks, OCR)
Pricing
from $1.00 / 1,000 page processeds
PDF to AI-Ready Data (Markdown, Tables, RAG Chunks, OCR)
Convert PDFs into clean Markdown, JSON/CSV tables and RAG-ready chunks with page metadata. Built-in OCR for scanned PDFs. No AI API calls, no proxies.
Pricing
from $1.00 / 1,000 page processeds
Rating
0.0
(0)
Developer
Loris Barce
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
15 hours ago
Last modified
Categories
Security
Limited permissionsShare
PDF to AI-Ready Data — Markdown, Tables, RAG Chunks & OCR
Turn any PDF into clean Markdown, tables as JSON/CSV and RAG-ready chunks with page metadata — in seconds, with built-in OCR for scanned documents.
Everything runs locally inside the Actor: no AI APIs, no proxies, no browser. You only pay for the pages you actually process.
Why use it
- 🧱 Structure preserved — headings (
#,##) rebuilt from font sizes, bulleted and numbered lists, clean paragraphs. - 🧹 Noise removed — running headers/footers and page numbers repeated on ≥ 50% of pages are stripped; words hyphenated across line breaks are re-joined.
- 📊 Tables extracted — fully gridded tables, tables drawn with horizontal rules only (papers, reports) and borderless financial statements made of aligned number columns all become JSON (array of rows) and CSV, and are embedded in the Markdown as GitHub tables.
- ✂️ Chunks ready for embeddings — split on paragraph and sentence boundaries with configurable size and overlap, each chunk tagged with
pageStart,pageEnd,chunkIndex,sourceUrlanddocTitle. - 🔍 OCR for scans — pages without a text layer are OCR'd automatically (Tesseract, 300 DPI) in English, Italian, German, French and Spanish.
- 🛡️ Robust — one broken PDF never stops the batch; every failure is reported with a clear reason. Memory stays flat even on 300+ page documents.
Use cases
- RAG chatbots and AI agents over your documents — manuals, policies, contracts, knowledge bases.
- Table extraction from reports and invoices — financial statements, price lists, invoices to CSV/JSON.
- Digitising scanned archives — make old scanned PDFs searchable and embeddable.
- Pre-processing for LLM pipelines — feed Markdown instead of raw PDF text to get better answers and fewer tokens.
Input
| Field | Type | Default | Description |
|---|---|---|---|
pdfUrls | array of strings | – | Direct links to PDF files. |
uploadedFiles | array of strings | – | Uploaded files: a file/record URL, a key in the run's default key-value store, or storeIdOrName/key. |
outputs | array | ["markdown"] | Any of markdown, text, tables, chunks. |
ocrMode | string | auto | auto (OCR only pages without text), always, never. |
ocrLanguages | array | ["eng","ita"] | eng, ita, deu, fra, spa. |
chunkSize | integer | 1000 | Max characters per chunk (overlap included). |
chunkOverlap | integer | 150 | Characters repeated from the previous chunk. Must be < chunkSize / 2. |
pageRange | string | all pages | e.g. 1-10,15 or 20-. |
maxPages | integer | 500 | Cost guard: max pages processed per document. |
maxFileSizeMb | integer | 50 | Larger files are rejected before processing. |
Example:
{"pdfUrls": ["https://www.rfc-editor.org/rfc/pdfrfc/rfc2119.txt.pdf"],"outputs": ["markdown", "tables", "chunks"],"ocrMode": "auto","ocrLanguages": ["eng"],"chunkSize": 1000,"chunkOverlap": 150}
Output
Dataset (one row per document)
{"sourceUrl": "https://example.com/annual-report.pdf","docId": "annual-report-3f2a91bc","title": "Annual Report 2025","pages": 42,"totalPages": 42,"ocrPages": 0,"markdown": "# Annual Report 2025\n\n## Highlights\n\n...","markdownUrl": "https://api.apify.com/v2/key-value-stores/.../records/annual-report-3f2a91bc.md","text": null,"textUrl": null,"tablesCount": 7,"tablesUrl": "https://api.apify.com/v2/key-value-stores/.../records/annual-report-3f2a91bc-tables.json","chunksCount": 118,"status": "succeeded","error": null,"warnings": []}
markdown/textare inlined when ≤ 1 MB; larger documents only get the…Urllink.statusissucceeded,failed(witherror, e.g.password protected,not a PDF (content-type: text/html, missing %PDF header),file too large (…),HTTP 404 while downloading),partial(spending limit reached mid-document — what was processed is saved) orskipped(spending limit reached before the document started).
chunks dataset (one row per chunk)
{"text": "## Highlights\n\nRevenue grew 12% year over year, driven by ...","pageStart": 3,"pageEnd": 4,"chunkIndex": 5,"sourceUrl": "https://example.com/annual-report.pdf","docTitle": "Annual Report 2025"}
The chunks dataset belongs to the run; its ID is in OUTPUT.chunksDatasetId and it is listed under the run's storages.
Key-value store
| Key | Content |
|---|---|
{docId}.md | Markdown |
{docId}.txt | Plain text (if text requested) |
{docId}-tables.json | All tables: [{tableIndex, page, nRows, nCols, rows}] |
{docId}-table-N.csv | Table N as CSV (N starts at 1) |
OUTPUT | Run summary: {documents, succeeded, failed, partial, skipped, pagesProcessed, ocrPages, tables, chunks, stoppedBySpendLimit, durationSec} |
Connect it to a vector database
- Run this Actor with
outputs: ["chunks"]. - Add an integration to the run: Pinecone Integration, Qdrant Integration (or Weaviate, Milvus, Chroma…) from Apify Store.
- Point the integration at the
chunksdataset, maptextas the field to embed and keepsourceUrl,docTitle,pageStart,pageEndas metadata.
Each vector then cites the exact pages it came from — perfect for answers with sources.
The same dataset works with LangChain / LlamaIndex Apify loaders, n8n, Make and Zapier.
Pricing (pay per event)
| Event | Price | When |
|---|---|---|
page-processed | $0.001 / page | each page extracted from the text layer |
ocr-page | $0.005 / page | each page that needed OCR (instead of page-processed) |
table-extracted | $0.002 / table | each table, only when tables is in outputs |
A 20-page text report with 3 tables costs $0.026. Failed downloads, non-PDF files and password-protected files are never charged.
When your run reaches its maximum cost, the Actor stops cleanly: pages already paid for are saved (status partial), remaining documents are marked skipped, and the run still finishes as SUCCEEDED.
Limits
- Password-protected PDFs are not supported — they are reported as
failed: password protected. The Actor never tries to unlock them. - OCR quality depends on the scan — resolution, skew and contrast matter. Handwriting is not supported.
- Borderless tables are detected when they are numeric (amounts, years, percentages in aligned columns — e.g. income statements). Borderless tables of pure text with no lines at all are kept as text. Very narrow sub-columns under a spanning header may be merged into one cell.
- Multi-column layouts are read line by line across the page; complex magazine layouts may mix columns.
- Max file size and page count are capped by
maxFileSizeMbandmaxPages. - Downloads from private/internal network addresses are blocked for security.
FAQ
Does it send my documents to OpenAI or another AI service? No. Extraction and OCR run entirely inside the Actor container.
Can I process files that aren't public? Yes — upload them to a key-value store (or use the file upload in the input) and list them in uploadedFiles.
🇮🇹 In breve (italiano)
Converte PDF in Markdown pulito (titoli, elenchi, paragrafi), tabelle JSON/CSV e chunk pronti per RAG con numero di pagina, con OCR automatico per i PDF scansionati (eng, ita, deu, fra, spa). Nessuna API AI esterna: tutto gira dentro l'Actor.
- Prezzi: 0,001 $ a pagina, 0,005 $ a pagina OCR, 0,002 $ a tabella (solo se richiedi
tables). I file non validi non vengono addebitati. - Limite di spesa: al raggiungimento del limite l'Actor si ferma in modo pulito, salva quanto elaborato e termina in SUCCEEDED.
- Limiti: niente PDF protetti da password; la qualità OCR dipende dalla scansione; le tabelle senza linee vengono riconosciute se sono numeriche (es. conti economici), quelle di solo testo restano come testo.
- Vector DB: collega il dataset
chunksalle integrazioni Pinecone/Qdrant di Apify usandotextcome campo da indicizzare.