PDF to Markdown avatar

PDF to Markdown

Pricing

from $1.00 / 1,000 document converteds

Go to Apify Store
PDF to Markdown

PDF to Markdown

PDF to Markdown converter API for RAG and LLMs: clean Markdown, plain text or JSON chunks with page numbers. Tables, multi-column layouts, OCR for scanned pages. $0.002 per PDF + $0.00025 per page; failures are free.

Pricing

from $1.00 / 1,000 document converteds

Rating

0.0

(0)

Developer

John Wilkinson

John Wilkinson

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

37 minutes ago

Last modified

Share

PDF to Markdown Converter API for RAG & LLMs (OCR, Tables)

PDF to Markdown, text or RAG chunks in one API call. $0.001 per document + $0.00012 per page (a 10-page PDF costs $0.0022), and scanned pages with OCR cost $0.001. Failed or empty files are free. No GPU, no LLM, no per-month fee.

Convert PDFs to clean Markdown, plain text, or RAG-ready JSON chunks with page numbers, built for LLM, RAG, vector database, and AI agent pipelines. Give it PDF URLs or upload a file and get one dataset item per document back. Each item has the Markdown, title, page count, language, optional chunks, and a status/error field. OCR for scanned PDFs, tables as Markdown tables, two-column layouts in reading order, and repeated headers, footers, and page numbers removed.

Pay only for what you convert: a small fee per document plus a fee per page. Failed downloads, non-PDFs, and empty documents are free.

What it does

  • PDF → Markdown: headings (#, ##, … detected from font size and weight), paragraphs re-flowed across line breaks, de-hyphenation, bullet and numbered lists.
  • Tables → Markdown tables (ruled tables, including rows stacked without horizontal lines). Choose markdown, text (tab-separated), or skip.
  • Multi-column layouts (scientific papers, reports): left column, then right column, with full-width titles and abstracts kept in place.
  • OCR for scanned pages (Tesseract 5): auto OCRs only the pages that have no text layer, so mixed documents stay cheap. Languages: eng, deu, fra, spa, ita, por, nld, or combinations like eng+deu.
  • RAG chunking: heading-aware chunks with chunkSize and chunkOverlap (in approximate tokens). Each chunk has pageStart, pageEnd, and its headings path (e.g. ["3 Model Architecture", "3.2 Attention"]) for citations and filtering.
  • Page range (1-5,8,10-): convert only what you need and pay only for those pages.
  • Metadata: title (from PDF metadata or the first heading), author, total and processed pages, OCR page count, detected language, raw PDF info.
  • Clean errors: each document gets status = success / empty / error and a readable error (404, "Not a PDF (got HTML page)", password-protected, too large…). One bad URL never fails the run.
  • Fast and light: about 0.1 s per text page on one CPU core; the default is 1 GB of memory. No GPU or ML models.

Input

FieldDefaultDescription
urls–List of PDF URLs ([{ "url": "https://…/file.pdf" }] or plain strings)
file–Upload a PDF from your computer (Console)
base64Files–API/agents: [{ "name": "a.pdf", "data": "<base64>" }]
outputFormatmarkdownmarkdown, text, or json (Markdown + chunks + per-page Markdown)
chunkingfalseAdd RAG chunks (always on for json)
chunkSize / chunkOverlap512 / 64Approximate tokens (1 token ≈ 4 chars)
ocrautoauto (scanned pages only), off, force
ocrLanguageengTesseract code(s), e.g. deu, eng+fra
pageRangealle.g. 1-10, 2,4,6-
tablesmarkdownmarkdown, text, skip
imageCaptionsfalseInsert ![Figure 1: …](page-3-image-1) placeholders with nearby caption text
removeHeadersFooterstrueDrop running headers, footers, and page numbers
maxPagesPerDocument1000Safety cap
maxFileSizeMb100Download limit
maxConcurrency2Parallel documents

Example input

{
"urls": [
{ "url": "https://arxiv.org/pdf/1706.03762" },
{ "url": "https://nvlpubs.nist.gov/nistpubs/CSWP/NIST.CSWP.29.pdf" }
],
"outputFormat": "json",
"chunkSize": 512,
"chunkOverlap": 64,
"ocr": "auto"
}

Output

One dataset item per PDF (abridged):

{
"source": "https://nvlpubs.nist.gov/nistpubs/CSWP/NIST.CSWP.29.pdf",
"status": "success",
"error": null,
"title": "The NIST Cybersecurity Framework (CSF) 2.0",
"language": "en",
"author": null,
"totalPages": 32,
"processedPages": 32,
"ocrPages": 0,
"charCount": 66741,
"markdown": "# The NIST Cybersecurity Framework (CSF) 2.0\n\n## National Institute of Standards and Technology\n\n…\n\n### Abstract\n\nThe NIST Cybersecurity Framework (CSF) 2.0 provides guidance to industry, government agencies, and other organizations to manage cybersecurity risks…",
"chunks": [
{
"chunkIndex": 3,
"text": "### Preface\n\nThe Cybersecurity Framework (CSF) 2.0 is designed to help organizations of all sizes and sectors…",
"pageStart": 4,
"pageEnd": 5,
"headings": ["The NIST Cybersecurity Framework (CSF) 2.0", "National Institute of Standards and Technology", "Preface"],
"charCount": 1901,
"approxTokens": 475
}
],
"pageTexts": [{ "page": 1, "ocr": false, "markdown": "# The NIST Cybersecurity Framework (CSF) 2.0 …" }],
"warnings": [],
"elapsedSec": 3.26
}

A table from a government report comes out as:

| Notice Date | Effective | Received | Company | City | No. Of | Layoff/Closure |
|---|---|---|---|---|---|---|
| 06/22/2015 | 03/25/2016 | 07/01/2015 | Maxim Integrated Product | San Jose | 150 | Closure Permanent |

Download results as JSON, JSONL, CSV, or Excel, or read them through the Apify API.

Use it from code, LangChain, LlamaIndex, or an AI agent

from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("jcwilk/pdf-to-markdown").call(run_input={
"urls": ["https://arxiv.org/pdf/1706.03762"], "outputFormat": "json", "chunkSize": 400})
for doc in client.dataset(run["defaultDatasetId"]).iterate_items():
for ch in doc.get("chunks", []):
embed_and_store(ch["text"], metadata={"source": doc["source"], "page": ch["pageStart"], "section": ch["headings"]})

The Actor also works with the Apify MCP server, so Claude, Cursor, and other MCP clients can call it as a "read this PDF" tool.

Pricing (pay per event)

EventPrice
Actor start (charged by Apify, per GB of run memory)$0.0005 per GB
Document converted$0.001
Page converted (text layer)$0.00012 ($0.12 per 1,000 pages)
Page converted with OCR$0.001 ($1 per 1,000 pages)

Examples (excluding the start fee): 10-page report $0.0022, 100-page manual $0.013, 20-page scanned contract $0.021. Batch many PDFs per run to spread the start fee. Failed, empty, and non-PDF inputs are not charged. Use pageRange to pay for fewer pages.

FAQ

How is this different from LLM-based PDF parsers? It uses deterministic open-source parsing (pdfplumber, pypdfium2, Tesseract), so it's cheap, fast and repeatable. Very complex layouts (math formulas, charts) are not reconstructed the way vision-LLM parsers try to.

Does it work on scanned PDFs? Yes. With ocr: "auto" (the default), pages without a text layer go through Tesseract OCR. Set the language with ocrLanguage. With force, every page is OCR'd (useful when the text layer is broken).

How good are the tables? Ruled and grid tables (forms, financial and government reports) come out as clean Markdown tables. Tables drawn only with whitespace, such as "booktabs" tables in academic papers, are kept as text in reading order rather than turned into tables.

Can it handle two-column papers? Yes. Columns are read left, then right, and full-width titles and abstracts stay at the top.

What chunk size should I use? 300–800 tokens with 10–15% overlap suits most embedding models. Chunks never split mid-sentence unless one sentence is longer than the chunk.

Is my document stored? Documents are processed in memory during the run. Only the results you see in the dataset are saved, under your Apify storage retention settings.

Password-protected PDFs? They return status: "error" with a clear message and are not charged.

Does it support DOCX or images? Not yet. It handles PDFs only, which keeps it fast and cheap.

How fast is it? About 0.1–0.2 s per text page and 2–3 s per OCR page on one CPU core. For large OCR jobs, raise the memory to 2–4 GB to get more CPU.

Limitations

  • Math formulas come out as linear text, not LaTeX.
  • Whitespace-only tables are not converted into Markdown tables.
  • Image captions are placeholders that use the caption text printed in the PDF. No AI image description.
  • Layout detection handles one or two columns. Three or more columns may interleave.

Run locally (no Apify account needed)

python -m venv .venv && . .venv/bin/activate
pip install -r requirements-dev.txt # plus: apt install tesseract-ocr
mkdir -p storage/key_value_stores/default
echo '{"urls":["https://arxiv.org/pdf/1706.03762"]}' > storage/key_value_stores/default/INPUT.json
python -m src # results in storage/datasets/default/
pytest -q # unit and end-to-end tests
python scripts/smoke.py # smoke test on tests/smoke/pdfs (see scripts/fetch_smoke_pdfs.sh)

Built on open-source libraries with permissive licenses: pdfplumber/pdfminer.six (MIT), pypdfium2 (Apache-2.0/BSD-3), Tesseract and pytesseract (Apache-2.0), py3langid (BSD-3). No AGPL or GPL dependencies.