PDF to Markdown & Text Extractor for LLM and RAG avatar

PDF to Markdown & Text Extractor for LLM and RAG

Pricing

from $1.40 / 1,000 pdf converteds

Go to Apify Store
PDF to Markdown & Text Extractor for LLM and RAG

PDF to Markdown & Text Extractor for LLM and RAG

Convert PDF URLs to clean Markdown or plain text for LLMs, AI agents and RAG. Headings, lists, paragraphs and simple tables, optional ready-to-embed chunks with page numbers. No start fee, $0.002 per PDF, scanned PDFs are not charged.

Pricing

from $1.40 / 1,000 pdf converteds

Rating

0.0

(0)

Developer

Data Gleaner

Data Gleaner

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

Give it PDF links, get clean Markdown, plain text and ready-to-embed chunks back. Headings become # titles, wrapped lines become real paragraphs, bullet lists stay lists, simple tables become Markdown tables, and page headers, footers and page numbers are removed. Built for RAG ingestion, AI agents and LLM pipelines. No browser, no API key, no start fee.

Price: $0.002 per PDF ($2 per 1,000 documents), no start fee. PDFs that fail to download or have no text (scans) are returned with the reason and not charged. See Pricing below.

Why use this one

  • Cheapest per document. One flat price per PDF, whether it has 2 pages or 200. No start fee and no per-page charge.
  • Real Markdown, not a text dump. Heading levels are guessed from font size, bold and section numbers (1, 2.1, A.3); lines are re-flowed into paragraphs, words hyphenated at a line end are re-joined, - and • lists are kept, and tables with aligned columns are returned as Markdown tables.
  • RAG chunks included. Set chunkSize and each document also returns a chunks array: pieces cut at paragraph and sentence boundaries, with overlap, each with its pageStart and pageEnd so an answer can cite the page.
  • Fast. Text extraction reads the file in-process, so a 100-page report converts in about two seconds.
  • Safe on bad input. One broken link never stops the run: every URL returns one row, with an error that says what happened.
  • Honest limit: no OCR yet. A scanned PDF is returned with hasTextLayer: false and is not charged.

Minimal input

{"urls": [{"url": "https://arxiv.org/pdf/1706.03762"}], "outputFormat": "markdown", "chunkSize": 1000}

Start it with no input and it converts one built-in sample PDF (the 15-page arXiv paper 1706.03762) and says so in the run's status message.

What does PDF to Markdown do?

For each link it downloads the file (up to 50 MB, redirects followed, a real PDF check on the first bytes), reads the text layer with every character's position and font, and rebuilds the document structure. Typical uses:

  • RAG ingestion. Turn a folder of reports, papers or manuals into Markdown chunks with page numbers for a vector database.
  • AI agents. Give an agent a tool that reads any PDF link into text it can quote and reason over.
  • Research papers. Convert arXiv and journal PDFs to Markdown with section headings, ready to summarise or compare.
  • Contracts and policies. Pull terms, clauses and numbered sections into text for review or clause extraction.
  • Reports and filings. Annual reports, government and regulatory reports, white papers and earnings releases as searchable text.
  • Knowledge bases and search. Index documentation PDFs by title, page and section.

Input

FieldTypeWhat it does
urlslist of linksThe PDF files to convert. Leave empty for the built-in sample.
outputFormatchoicemarkdown (default), text or both.
maxPagesPerPdfnumberConvert only the first N pages, default 200. pageCount still shows the full length.
pageRangetextOptional pages, 1-based: 1-5, 8, 10-12, 3- (page 3 to the end).
chunkSizenumber0 (default) returns no chunks. Set about 1000 characters (roughly 250 tokens) to also get chunks.
chunkOverlapnumberCharacters repeated between neighbouring chunks, default 100.
includePageBreakstrue/falseAdd a --- Page 3 --- line where each page starts.
removeHeadersFooterstrue/falseDrop running headers, footers and page numbers, default true.
maxPdfsnumberProcess at most this many of the URLs; also your cost cap.
maxFileSizeMbnumberSkip larger files (default 50).
maxConcurrencynumberPDFs downloaded in parallel, default 4.
proxyConfigurationobjectOptional Apify Proxy for sites that refuse the download. Default is no proxy.
{
"urls": [
{"url": "https://arxiv.org/pdf/1706.03762"},
{"url": "https://nvlpubs.nist.gov/nistpubs/ai/NIST.AI.100-1.pdf"}
],
"outputFormat": "both",
"pageRange": "1-10",
"chunkSize": 1000,
"chunkOverlap": 150,
"includePageBreaks": true,
"maxPdfs": 50
}

Output

One dataset row per PDF.

FieldMeaning
url, finalUrlThe link you gave and where the file was finally downloaded from.
fileNameFrom the server or the link.
titleThe PDF's title metadata, else the first heading.
authorFrom the PDF metadata, if present.
pageCount, pagesProcessedPages in the file and pages converted.
wordCount, charCountSize of the extracted text.
hasTextLayerfalse for scanned or image-only PDFs.
markdown, textThe content, depending on outputFormat.
chunksWhen chunkSize > 0: {index, text, pageStart, pageEnd} objects.
metadataproducer, creator, creationDate, modificationDate (ISO 8601).
errornull on success, otherwise the reason (download refused, not a PDF, scanned, password-protected).
scrapedAt, inputWhen it ran and the settings used.
{
"url": "https://arxiv.org/pdf/1706.03762",
"finalUrl": "https://arxiv.org/pdf/1706.03762",
"fileName": "1706.03762v7.pdf",
"title": "Attention Is All You Need",
"author": null,
"pageCount": 15,
"pagesProcessed": 15,
"wordCount": 5995,
"charCount": 38771,
"hasTextLayer": true,
"markdown": "# Attention Is All You Need\n\n## Abstract\n\nThe dominant sequence transduction models are based on complex recurrent or convolutional neural networks ...\n\n## 1 Introduction\n\n...",
"chunks": [
{"index": 0, "text": "# Attention Is All You Need\n\nAshish Vaswani ...", "pageStart": 1, "pageEnd": 1},
{"index": 1, "text": "...", "pageStart": 1, "pageEnd": 2}
],
"metadata": {"producer": "pdfTeX-1.40.25", "creator": "LaTeX with hyperref", "creationDate": "2024-04-10T21:11:43+00:00", "modificationDate": "2024-04-10T21:11:43+00:00"},
"error": null,
"scrapedAt": "2026-10-22T06:00:00+00:00",
"input": {"url": "https://arxiv.org/pdf/1706.03762", "outputFormat": "markdown", "pageRange": null, "maxPagesPerPdf": 200, "chunkSize": 1000, "includePageBreaks": false}
}

Pricing

$0.002 per PDF converted ($2 per 1,000), no start fee, billed through the pay-per-event event pdf-document. Higher Apify plans get lower prices: $0.0017 on Silver and $0.0014 on Gold. This price applies from 22 October 2026. A PDF is billed once when its text is extracted, however many pages it has and whether or not you ask for chunks. Nothing is charged for a link that fails to download, is not a PDF, is password-protected or has no text layer.

Worked examples:

  • 1 research paper (any length) = $0.002.
  • 100 contracts or reports = $0.20.
  • A 5,000-document knowledge base = $10.00, less if some are scans.
  • 1,000 links where 80 are scanned or dead = 920 billed = $1.84.

Set maxPdfs and the run cannot cost more than that many times $0.002. If you also set a maximum charge on the run, it stops there too.

Limits

  • No OCR yet. Scanned and image-only PDFs have no text to read; they are returned with hasTextLayer: false and an explanation, and are not charged. Text embedded in images inside a normal PDF is not read.
  • Password-protected PDFs are skipped (returned with an error, not charged).
  • Layout is inferred. Headings, lists and tables are guessed from fonts and positions, so unusual designs, complex multi-row table headers, equations and figure labels can come out as plain lines of text. Multi-column pages follow the reading order stored in the PDF, which is correct for most papers and reports.
  • Size. Files over maxFileSizeMb (default 50 MB) are skipped. Very long documents are capped by maxPagesPerPdf.
  • Some sites refuse automated downloads (HTTP 403). That row has the reason and is not charged; try proxyConfiguration or another copy of the file.

Use it from n8n, Make, Zapier or an AI agent

Actor ID: datagleaner/pdf-to-markdown

Minimal input:

{"urls": [{"url": "https://arxiv.org/pdf/1706.03762"}], "chunkSize": 1000}

Each tool below runs this Actor with your own Apify API token.

  • n8n: add the Apify node (@apify/n8n-nodes-apify). Choose Run an Actor and get dataset, set Actor to datagleaner/pdf-to-markdown and paste the input above.

  • Make: use the Apify app's Run an Actor module, then Get Dataset Items. Watch Actor Runs can trigger a scenario when a run finishes.

  • Zapier: use the Apify action Run Actor, then Fetch dataset items. The trigger Finished Actor run starts a Zap when a run ends.

  • AI agents (MCP): connect to https://mcp.apify.com/?tools=datagleaner/pdf-to-markdown. In Claude Code:

    claude mcp add --transport http apify "https://mcp.apify.com/?tools=datagleaner/pdf-to-markdown"
    

    Then run /mcp to sign in to Apify in your browser. Other clients can sign in with OAuth or send the header Authorization: Bearer YOUR_APIFY_TOKEN. Then ask the agent in plain words, for example:

    Convert this PDF to Markdown and summarise section 3: https://arxiv.org/pdf/1706.03762

  • LangChain (Python):

# pip install langchain-apify, then set APIFY_TOKEN in your environment
import json
from langchain_apify import ApifyActorsTool
tool = ApifyActorsTool("datagleaner/pdf-to-markdown")
result = tool.invoke({"run_input": json.loads('{"urls": [{"url": "https://arxiv.org/pdf/1706.03762"}], "chunkSize": 1000}')})
  • LlamaIndex (Python): run the Actor with the Apify client and load the rows as documents:
# pip install apify-client llama-index
from apify_client import ApifyClient
from llama_index.core import Document
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("datagleaner/pdf-to-markdown").call(run_input={"urls": [{"url": "https://arxiv.org/pdf/1706.03762"}]})
docs = [Document(text=row["markdown"], metadata={"title": row["title"], "url": row["url"], "pages": row["pageCount"]})
for row in client.dataset(run["defaultDatasetId"]).iterate_items() if row.get("markdown")]

FAQ

Do I need an API key or login? No, only an Apify account. The Actor downloads public PDF links; it cannot open files behind a login.

What if I start it with no links? It converts one built-in sample PDF (arXiv 1706.03762, 15 pages) so you can see the output, and says so in the run's status message.

How are chunks cut? At paragraph boundaries first, then sentence or word boundaries for very long paragraphs, to about chunkSize characters, with chunkOverlap characters repeated from the previous chunk. Each chunk carries the first and last PDF page it covers.

Why is a table not a table? Tables are detected when three or more consecutive lines have the same number of aligned columns. Merged cells, multi-line cells and tables drawn as images are returned as text.

What happens to a scanned PDF? It comes back as a row with hasTextLayer: false, the page count and an explanation in error, and it is not charged. OCR is planned.

Can I convert only some pages? Yes, pageRange (for example 1-5,9) and maxPagesPerPdf.

Responsible use

This Actor converts PDF files you point it to. Only submit documents you are allowed to download and process, and respect the terms of the sites that host them. If the documents contain personal data, the obligations for processing it are yours.