How to convert a URL to Markdown
Whether you want clean Markdown for an LLM prompt, a RAG pipeline, a documentation archive, or just to quote a blog post in your notes - here are the four ways to do it, ranked from easiest to "you'll regret this".
When you'd want this
- LLM context - paste a clean page into a chat without the nav, ads, and cookie banners.
- RAG / vector indexing - Markdown is the most common ingestion format and preserves structure.
- Documentation mirroring - turn a vendor's docs into your own static-site source files.
- Note-taking and clipping - pipe the result into Obsidian, Bear, or a Git-tracked notes folder.
- Migration - moving a blog from a CMS to a Markdown-based static site.
Method 1 - The web tool (recommended)
The fastest path. No signup, no install, no API token. Best when you want to convert a single page or two, right now.
-
Open the converter
Go to the homepage. The tool is the first thing you see.
-
Paste the URL
Drop any public URL into the input. Articles, docs, blog posts, product pages, single-page apps - all fine. The crawler runs a real headless browser, so JavaScript-rendered content works.
-
Click "Convert to Markdown"
You'll see a progress message ("Crawling… 12s"). After 20–90 seconds for most pages, the cleaned-up Markdown appears below.
-
Copy or download
Use the Copy button to put the Markdown on your clipboard, or Download .md to save it as a file.
The web tool is rate-limited to 3 free conversions per browser. If you hit the limit, switch to the API or run the URL to Markdown Actor on Apify yourself (free plan: $5/month of free usage).
Method 2 - The REST API
Best when you need to convert URLs from code: a script, a cron job, a backend service, or a RAG indexing pipeline.
curl -X POST \
"https://api.apify.com/v2/acts/apify~url-to-markdown/run-sync-get-dataset-items?token=$APIFY_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/article",
"scrapingTool": "raw-http",
"proxyConfiguration": { "useApifyProxy": true }
}' | jq -r '.[0].markdown'
For the JavaScript and Python SDKs, async polling, and the recommended input, see the API integration guide.
Method 3 - The MCP server
Best if you live inside Claude Desktop or Claude Code and want the AI itself to call the converter. Install once, then just ask:
Convert https://example.com/article to clean Markdown
using the Apify URL to Markdown Actor.
See the MCP setup guide for the one-line install and config.
Method 4 - Manual: HTML-to-Markdown libraries
You can piece this together yourself with fetch, an HTML parser, and an HTML-to-Markdown converter. It looks deceptively simple:
// In theory:
import TurndownService from 'turndown';
const html = await fetch('https://example.com/article').then(r => r.text());
const md = new TurndownService().turndown(html);
console.log(md);
In practice, this falls apart fast. Here are the issues you'll hit, in roughly the order you'll hit them:
1. The page is JavaScript-rendered
A fetch() only gets the server-rendered HTML. For React, Vue, Next.js, Angular, and most modern marketing sites, that means an empty <div id="root"></div>. To get real content you need to spin up Playwright or Puppeteer, which means downloading ~300 MB of Chromium, dealing with launch flags, sandboxing on Linux, and waiting for network-idle.
2. Anti-bot blocking
Cloudflare, DataDome, PerimeterX, Akamai Bot Manager, and Google's bot detection will challenge or outright 403 you. You'll need residential proxies, browser fingerprint randomisation, and TLS fingerprint shaping - which by itself is an entire engineering project.
3. Cookie banners and modals
The first ~30% of most pages, after the cookie banner is rendered, is junk: GDPR notices, newsletter modals, app-install nags. These show up in your Markdown unless you write per-site selectors to dismiss them.
4. Boilerplate (nav, footer, sidebars, ads)
A naive HTML-to-Markdown pass will faithfully convert your nav, footer, related-articles widget, ad slots, and 47 social-share buttons. You need a content-extraction step (Readability.js, trafilatura, or a custom selector list) before the conversion.
5. Dynamic loading and pagination
Lazy-loaded images, "Load more" buttons, infinite scroll, accordions that hide half the content - all of those require browser interaction (clicks, scrolls, waits) before the HTML is "complete".
6. Maintenance
Even after you solve all the above, every site changes its DOM eventually. Selectors break, anti-bot vendors update, frameworks ship new SSR strategies. Your "simple" converter becomes a permanent maintenance burden.
Bottom line
Rolling your own URL-to-Markdown converter is straightforward for your own static blog, and brittle for everything else. For arbitrary URLs, a battle-tested tool - like the Apify URL to Markdown Actor (or the Website Content Crawler for whole sites) - saves you weeks of infrastructure work.
Which method should I pick?
| Use case | Recommended method |
|---|---|
| One-off conversion | Web tool |
| A few dozen URLs from a script | REST API |
| From inside an AI chat | MCP server |
| Thousands of URLs / whole-site dump | Apify console (bulk run) |
| A site you fully control | Manual (Turndown / Pandoc) - fine here |