PDF & DOCX to Markdown + JSON Chunks for RAG
Pricing
$20.00 / 1,000 pages
PDF & DOCX to Markdown + JSON Chunks for RAG
Pricing
$20.00 / 1,000 pages
Rating
0.0
(0)
Developer
Francesco Correnti
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
PDF to Markdown & DOCX to Markdown + RAG Chunks for LLM Ingestion
Turn PDF and DOCX files into clean Markdown and heading-aware JSON chunks, ready for a vector database. Built for pdf to markdown and docx to markdown conversion, rag chunks generation and llm ingestion pipelines: smart chunking that follows your headings, with token counts and page numbers, ready to embed and load into any vector database.
Keywords: pdf to markdown, docx to markdown, rag chunks, llm ingestion, chunking, vector database.
Features
- PDF and DOCX by URL or from an Apify key-value store record. The type is detected from the file content, not the extension.
- PDF: headings detected by font size (
#,##,###), tables become GitHub Markdown tables, repeated headers/footers and page numbers are removed. - DOCX: heading styles, bullet lists and tables kept in document order; headers and footers are ignored.
- Chunks follow the heading structure: each has
heading_path(e.g.["Report", "Costs"]),page,token_countand a stableid. Tables are never cut mid-row (large tables split by rows, header row repeated). Consecutive chunks of a section overlap by the number of tokens you choose. - One dataset item per input entry. A bad file gives an item with
errorset; the run continues and exits 0.
Input
| Field | Type | Default | Description |
|---|---|---|---|
urls | array, required | - | http(s) URLs, or kvs:<key> / kvs:<storeIdOrName>/<key> for key-value store records |
chunkSize | integer | 500 | Max tokens per chunk (min 50). Counts are approximate |
overlap | integer | 50 | Tokens repeated from the previous chunk of the same section. Must be below chunkSize, otherwise clamped with a warning |
outputFormat | markdown | chunks | both | both | What each item contains |
{"urls": ["https://example.com/brief.docx", "kvs:my-store/report.pdf"],"chunkSize": 500,"overlap": 50,"outputFormat": "both"}
Output
One item per input entry: url, fileName, type (pdf|docx|null), title, pages, markdown, chunks[{id, text, heading_path, page, token_count}], chunkCount, warnings, error. Example (trimmed, from the test run on tests/samples/brief.docx):
{"url": "https://example.com/brief.docx","fileName": "brief.docx","type": "docx","title": "Project Brief","pages": 1,"chunkCount": 4,"warnings": [],"error": null,"markdown": "# Project Brief\n\nThe pipeline reads every document once and keeps the structure intact. Headings stay headings, tables stay tables and the text keeps its order. Each section is cut into passages that fit an embedding model. The pi…","chunks": [{"id": "e4a9aad6-0001","text": "# Project Brief\n\nThe pipeline reads every document once and keeps the structure intact. Headings stay headings…","heading_path": ["Project Brief"],"page": null,"token_count": 79},{"id": "e4a9aad6-0003","text": "## Budget\n\n| Item | Cost |\n|---|---|\n| Servers | 100 |\n| Support | 50 |…","heading_path": ["Project Brief", "Budget"],"page": null,"token_count": 27}]}
Pricing
Pay per event: $0.02 per page (event page). Charged only after a document converts successfully. Failed documents and PDFs with no text layer are free. DOCX has no pages: pages = max(1, ceil(words / 500)), and the same number is billed. If your spending limit is reached, the run stops and adds a warning; remaining entries are reported as skipped.
Limits
- No OCR: scanned PDF pages are skipped with the warning
page N: no text layer (scanned?), OCR not supported. - Token counts are approximate (words and punctuation marks), not those of a specific model tokenizer. Leave some headroom against your embedding model's limit.
- 100 MB per file, 60 s download timeout. Encrypted or corrupt files return an error item.
- DOCX chunks have
page: null.
Privacy
The actor only converts files you supply and only requests the URLs you give it. No crawling, no scraping, no collection of personal data.
Push and publish
npm i -g apify-cliapify loginapify push(from this folder)- Console -> the actor -> Publication -> Monetization: Pay per event, add event
pageat $0.02. - Set categories (AI, Developer tools).
- Set the SEO title and description (use the title and intro above).
- Publish.
Local development
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt && .venv/bin/python tests/test_actor.py
Prints OK on success. tests/make_samples.py rebuilds the sample files (needs playwright with chromium and python-docx; the samples are committed).
Run the actor locally: put an INPUT.json in storage/key_value_stores/default/ and run .venv/bin/python -m src.