URL to Markdown: Website & PDF to Markdown for LLM/RAG avatar

URL to Markdown: Website & PDF to Markdown for LLM/RAG

Pricing

from $0.75 / 1,000 page converteds

Go to Apify Store
URL to Markdown: Website & PDF to Markdown for LLM/RAG

URL to Markdown: Website & PDF to Markdown for LLM/RAG

Convert web pages, sitemaps, docs sites and PDFs to clean Markdown for LLMs and RAG, in bulk. Keeps headings, code blocks and tables, adds exact token counts and ready-made RAG chunks. Automatic JavaScript rendering for dynamic sites.

Pricing

from $0.75 / 1,000 page converteds

Rating

0.0

(0)

Developer

Jason

Jason

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

Turn hundreds or thousands of web pages, PDFs, sitemaps, Google Sheets of links or whole docs sites into clean, structure-preserving Markdown in one run, ready for ChatGPT, Claude, LangChain, LlamaIndex, vector databases and RAG pipelines.

URL to Markdown: Website & PDF to Markdown for LLM/RAG - sample output

$1.10 per 1,000 pages (down to $0.75 on higher Apify plans). Failed, blocked and duplicate URLs are never charged.

  • 🧹 Only the content, not the website. Menus, headers, footers, cookie banners, sidebars, "read more" cards and comment threads are removed. Headings, lists, tables, links and code are kept.
  • 💻 Real code blocks. Fenced code with the language tag (```python), indentation intact. No more code flattened into one line.
  • 📊 Real tables. Data tables become Markdown tables; layout tables are flattened so they don't turn into junk.
  • ⚡ Fast HTTP first, browser only when needed. Pages built by JavaScript (empty app shells) are rendered automatically in a headless browser. Same price.
  • 🛡️ Gets past more "403 Forbidden" pages. Refused requests are retried with a real Chrome/Safari TLS fingerprint, then in a browser, then through your proxy if you set one.
  • 🔢 Exact token counts (OpenAI o200k_base tokenizer) per page and per chunk, so you can budget LLM context before you spend it.
  • ✂️ RAG chunks built in. Heading-aware chunks that never exceed your token size (exact count), with overlap. Each chunk carries its heading path.
  • 🕸️ Crawl a docs site or blog. Follow links 1–5 levels deep inside the same folder, host or domain, with include/exclude patterns. Or feed sitemaps.
  • 📄 PDFs → text, Markdown/text files (llms.txt, README.md) pass through unchanged.
  • 📥 Bring your list any way you like: paste URLs, add a sitemap, or link a TXT/CSV file or a Google Sheet.
  • 📚 One combined file: every converted page also lands in all-pages.md, ready to upload to a Custom GPT, Claude Project or NotebookLM.
  • 🧾 Honest errors. Every URL that failed is listed with the reason in a free failed-urls dataset (CSV export) and the ERRORS record. Failures never become empty billed rows.

Head-to-head: this Actor vs the most-used Store fetcher

Same 10 real URLs, run on Oct 20, 2026 (Apify cloud, default settings for both). "Junk lines" are navigation/share/sign-in/comment-form lines left in the Markdown. "Prose kept" = how many of the competitor's real text paragraphs (150+ characters) also appear in our output.

URL typeCompetitor: tokens / junk linesThis Actor: tokens / junk linesProse keptNotes
BBC news article1,776 / 141,176 / 022 of 2234% fewer tokens, zero menu junk
Guardian long read5,781 / 114,295 / 230 of 30
Python docs (asyncio)17,266 / 4513,208 / 188 of 8832 code blocks fenced, language tagged where the page says it
Wikipedia comparison (tables)23,153 / 914,539 / 914 of 14 (checked by hand)Data tables kept, nav boxes and citation markers dropped
JavaScript-only page (quotes.toscrape.com/js)30 tokens, no content276 tokens, all 10 quotesn/aRendered automatically; competitor needs a manual wait setting
Blog guide with 300+ comments (CSS-Tricks)67,390 / 3456,294 / 11article keptComment thread removed: 10x cheaper to embed
arXiv PDF18,16618,211same
GitHub repo page4,278 / 131,397 / 0README keptSidebar and "you signed in" banners removed
G2 reviews (heavy bot protection)✅ 12,881❌ HTTP 403–Needs residential proxies; not included at this price (bring your own proxy)
Stack Overflow (Cloudflare)✅ 31,592❌ HTTP 403–Same

Totals: we converted 8 of 10 vs 9 of 10 (the competitor returned no content for the JavaScript page, we failed the two bot-protected sites). On the 7 pages both converted we used 57% fewer tokens (59,120 vs 137,810) for the same content, with 23 junk lines vs 437. Speed: our pages took 0.05–2.7 s each inside one batch run; the competitor took 3.8–61 s per URL, one URL per call.

Price: $1.10 per 1,000 pages vs $1.50 (27% cheaper), and a run takes thousands of URLs instead of one.

When to use the competitor instead: when your list is mostly sites with heavy bot protection (G2, Stack Overflow, Indeed...) and you don't have your own proxy.

What can I use it for?

  • Feeding a chatbot or RAG app your docs, help center, blog or knowledge base (crawl it or use its sitemap).
  • Building a Custom GPT / Claude Project knowledge file in one click: download all-pages.md.
  • Bulk-converting research links (articles, papers, PDFs) into LLM-ready text.
  • Monitoring content changes: every row has a contentHash, so you can diff runs.
  • Pre-processing for summarization, translation, classification or embeddings.

How to use it

  1. Paste URLs into URLs, add a Sitemap URL, link a TXT/CSV/Google Sheet, or set Crawl links to follow a site's links.
  2. Optionally set RAG chunk size (for example 800 tokens with 100 overlap).
  3. Click Start, then export the dataset as JSON, CSV or Excel, download all-pages.md, or pull it via the API, the MCP server, Make, Zapier or n8n.

Example inputs

Convert a list:

{
"urls": ["https://docs.python.org/3/tutorial/introduction.html", "https://arxiv.org/pdf/2005.11401"],
"chunkSizeTokens": 800,
"chunkOverlapTokens": 100
}

Crawl a docs section two levels deep, skipping changelogs:

{
"urls": ["https://docs.apify.com/platform/actors"],
"crawlDepth": 2,
"crawlScope": "samePath",
"excludeUrlPatterns": ["*/changelog*"],
"maxUrls": 300
}

Convert every URL in a Google Sheet (shared as "Anyone with the link"):

{ "urls": [], "urlsFileUrl": "https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID/edit#gid=0", "maxUrls": 5000 }

Example output (one row per page, shortened)

{
"url": "https://docs.python.org/3/library/asyncio-task.html",
"finalUrl": "https://docs.python.org/3/library/asyncio-task.html",
"statusCode": 200,
"title": "Coroutines and tasks",
"description": "This section outlines high-level asyncio APIs to work with coroutines and Tasks...",
"language": "en",
"canonicalUrl": "https://docs.python.org/3/library/asyncio-task.html",
"markdown": "# Coroutines and tasks\n\nThis section outlines high-level asyncio APIs ...\n\n```python\n>>> import asyncio\n\n>>> async def main():\n... print('hello')\n```",
"wordCount": 6745,
"tokens": 13208,
"tokensEstimate": 14377,
"chunkCount": 22,
"chunks": [{"index": 0, "heading": "Coroutines and tasks", "text": "# Coroutines and tasks\n\n...", "tokens": 780, "tokensEstimate": 766, "charCount": 3062}],
"extractor": "main",
"fetchMethod": "http",
"depth": 0,
"contentHash": "3bcf912531e8…",
"fetchMs": 1048,
"fetchedAt": "2026-10-20T23:58:56+00:00"
}

fetchMethod tells you how the page was fetched: http, http-impersonate (real-browser fingerprint retry), browser (JavaScript rendering) or proxy.

Other outputs of each run:

  • all-pages.md: every converted page in one Markdown file (key-value store).
  • failed-urls dataset: one row per failed URL with the reason (free, export as CSV/Excel). Its link is in OUTPUT.failedUrlsCsv.
  • OUTPUT: counts, total tokens, fallbacks used, and the status of each URL.
  • ERRORS: the same failures as JSON: http-error, blocked-by-site, blocked-by-robots, no-content, unsupported-type, blocked-private-network, invalid-url.

Input options

OptionWhat it doesDefault
URLsPages, PDFs, .md/.txt files3 sample pages
Sitemap URLsAdds every page in the sitemap(s)none
URL list filePublic TXT/CSV link or Google Sheet; any columnnone
Max URLsHard cap per run (listed + sitemap + crawled pages)100
Crawl links (depth) / scope / include / excludeFollow links 0–5 levels; same folder, host or domain; glob or /regex/ filters0 (off) / same folder
Extraction modemain (content only) or full (cleaned full page)main
Content CSS selector / Remove elementsOverride detection or strip extra blocksnone
Output formatsmarkdown, text, htmlmarkdown
RAG chunk size / overlapHeading-aware chunks in real tokens (0 = off)off / 100
Keep links / imagesKeep [text](url) and ![alt](src)links on, images off
Add list of all page linkslinks[] with absolute URL + anchor textoff
JavaScript renderingauto (only when needed), never, alwaysauto
Retry refused pages with a real-browser fingerprintFree 403/429 retryon
Proxy for blocked pagesApify datacenter proxy or your own proxy URLs, used only after other retries failoff
Combined Markdown file / exact token countsall-pages.md; o200k_base token countson / on
Respect robots.txtSkip disallowed URLson
Parallel requests / per domainSpeed vs. politeness10 / 3

Pricing

Pay per page converted: $1.10 per 1,000 on the Free and Starter plans, $0.95 on Scale, $0.75 on Business and above, plus a tiny $0.00005 run start fee. JavaScript rendering, fingerprint retries, chunking, exact tokens, the combined file and crawling are all included. Failed, blocked, skipped and duplicate URLs cost nothing. Set Maximum cost per run and the Actor stops cleanly when it is reached.

Limitations

  • Heavily protected sites (G2, Stack Overflow, Indeed and similar) often refuse datacenter traffic even from a real browser. They are reported as http-error 403 and not charged. Add your own residential proxy URLs under Proxy to reach them (Apify residential proxy isn't supported because its cost would exceed the page price).
  • robots.txt is respected by default, so some news sites (for example WSJ, Reuters) are skipped as blocked-by-robots. Turn it off only for your own sites or with permission.
  • No logins or cookies. Content behind a login isn't available.
  • PDF extraction reads the text layer. Scanned PDFs without text aren't OCR'd.
  • tokensEstimate (about 4 characters per token) is kept for older integrations; tokens is the exact count.

FAQ

Is it compatible with my existing runs? Yes. Every 1.0 input field works the same and every 1.0 output field is still there. New fields were added (tokens, fetchMethod, depth, parentUrl, modifiedDate, image, keywords).

Does JavaScript rendering cost more? No. It's the same price per page; the browser only starts when a page needs it.

How do I get one file for ChatGPT / Claude? Open the run's Storage → Key-value store → all-pages.md, or use the "All pages as one Markdown file" link on the Output tab.

Can I call it from an AI agent? Yes: through the Apify API, the Apify MCP server, or integrations like Make, Zapier and n8n.

This Actor only reads publicly accessible pages, follows robots.txt by default, and doesn't collect personal data by design. Respect each website's terms and copyright when you store or republish content. If you're unsure, check with a lawyer.

Feedback

Found a page that converts badly? Open an issue with the URL, and it will be looked at quickly.