HTML to Markdown Converter: Webpage to Markdown & JSON
Pricing
from $1.50 / 1,000 page converteds
HTML to Markdown Converter: Webpage to Markdown & JSON
Turn any webpage URL or raw HTML into clean, LLM-ready Markdown + JSON for RAG pipelines and AI agents. Removes menus, footers and cookie banners; keeps headings, tables and links. No browser, robots.txt respected. $1.50 per 1,000 pages, failed pages free.
Pricing
from $1.50 / 1,000 page converteds
Rating
0.0
(0)
Developer
Grace M. Hartwell
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 minutes ago
Last modified
Categories
Share
HTML to Markdown Converter turns any public webpage URL or raw HTML into clean, LLM-ready Markdown plus structured JSON. Menus, cookie banners, footers and sidebars are removed; headings, lists, code blocks, tables and links stay. Paste a few URLs, click Start, and you get one dataset item per page. That makes it a website-to-Markdown API for RAG pipelines, AI agents, content migration and SEO audits. You pay $1.50 per 1,000 converted pages, and failed pages are free.
What can you use HTML to Markdown Converter for?
- 🤖 RAG and AI agents: feed clean Markdown from docs, blogs or knowledge bases into a vector database or an LLM prompt, without the navigation and log-in boilerplate.
- 📚 LLM datasets: collect normalized page text with
languageandwordCount, so you can filter by language or length. - 🚚 Content migration: move HTML pages into a Markdown CMS, a docs site, a static site generator or a Git repo.
- 🔎 SEO content audits: titles, meta descriptions, H1–H6 outlines, canonical URLs and word counts for a list of URLs.
- 🗂️ Archiving: readable Markdown snapshots of policy, pricing or documentation pages on a schedule.
- 🧽 HTML clean-up: paste messy exported HTML and get Markdown back without fetching anything.
Example output: one webpage converted to Markdown
Real output from our test run (Wikipedia "Retrieval-augmented generation", default settings; markdown shortened here):
{"source": "html","status": "ok","url": "https://en.wikipedia.org/wiki/Retrieval-augmented_generation","title": "Retrieval-augmented generation - Wikipedia","language": "en","markdown": "From Wikipedia, the free encyclopedia\n\n**Retrieval-augmented generation** (**RAG**) is a technique that enables [large language models](https://en.wikipedia.org/wiki/Large_language_model) (LLMs) to retrieve and incorporate new information from external data sources. …","wordCount": 2361,"headings": [{ "level": 2, "text": "RAG and LLM limitations" },{ "level": 2, "text": "Process" },{ "level": 3, "text": "RAG key stages" }],"metadata": {"canonicalUrl": "https://en.wikipedia.org/wiki/Retrieval-augmented_generation","ogType": "website","extractionMode": "readability"},"error": null,"errorCode": null}
How many tokens does Markdown save compared with raw HTML?
We converted 10 public pages (Wikipedia, MDN, Python docs, Apify docs, web.dev, a Cloudflare blog post, a Guardian topic page) with default settings and counted tokens with tiktoken (cl100k_base):
| Result | |
|---|---|
| Median reduction vs. raw HTML | 92.41 % fewer tokens (range 75.82 %–99.63 %) |
| All 10 pages together | 693,388 → 52,970 tokens |
| Example page (Wikipedia "RAG") | 76,605 → 5,366 tokens |
| vs. plain extracted text | about the same size (median reduction −0.27 %, i.e. Markdown slightly larger) |
Read the last row before you quote the first one. Raw HTML includes inline scripts and CSS, so almost any extraction beats it. Compared with plain text from BeautifulSoup get_text(), Markdown is about the same size, because it keeps link URLs, headings and tables that plain text drops. What you gain is the structure, while the boilerplate is gone: 50 menu/log-in/cookie phrases in the visible text of the 10 pages became 0 in the Markdown. That is a simple string count, not a quality score. Page 10 is a news topic index, so its 99.63 % is not typical for articles.
Measured by Hartwell Toolworks, Oct 2026. Your results will vary.
Key features
- 📝 Clean Markdown: ATX headings, fenced code blocks,
-bullet lists, absolute link URLs, optional images (). - 📊 HTML tables to Markdown tables (GFM). Single-column layout tables become paragraphs.
- 🧹 Boilerplate removal with Mozilla Readability plus extra clean-up of
nav,header,footer,aside, forms, dialogs and elements whose class or ID points to cookie, consent, banner, newsletter, sidebar, share, ads, popup or comments blocks. If no clear article is found, the cleaned<body>is converted instead. - 🔗 Optional links list: up to 500 unique links per page with
url,textand aninternalflag. - 🔒 Privacy by default:
mailto:/tel:links become plain text, and e-mail addresses in the text are replaced with[email removed](you can turn this off). - 🤝 Polite: robots.txt respected; by default at most 5 parallel requests, 60 requests per minute and a 1-second delay per domain.
- 🧩 Apify platform: API, schedules, webhooks, integrations (Make, Zapier, n8n), and exports to JSON, CSV or Excel.
- 💸 Budget control: set Max total charge and the run stops cleanly at your budget.
How much does it cost to convert HTML to Markdown?
Pay-per-event pricing, with no separate compute charge:
| Event | Price | When |
|---|---|---|
page-converted | $0.0015 per page ($1.50 per 1,000) | after a converted page is saved |
apify-actor-start | $0.00005 per run | automatically at run start |
Free: 404s, timeouts, access-restricted pages, robots.txt skips, invalid URLs and conversion errors. Example: 1,000 pages × $0.0015 + 1 start × $0.00005 ≈ $1.50.
How to convert a website to Markdown
- Click Try for free.
- Add public URLs under URLs, and/or paste HTML into Raw HTML (set Base URL for raw HTML so relative links become absolute).
- Choose options: main content only, keep links, keep images, convert tables, links list, redact e-mails.
- Optional: set Max pages and a Max total charge.
- Click Start, then open the Markdown view or export the dataset.
Input example
{"startUrls": [{ "url": "https://example.com" }, { "url": "https://docs.apify.com/platform/actors" }],"rawHtml": "<h1>Hello</h1><p>World <a href=\"/x\">link</a></p>","rawHtmlBaseUrl": "https://example.org/","extractMainContent": true,"keepLinks": true,"keepImages": false,"keepTables": true,"includeLinks": false,"redactEmails": true,"maxPages": 50}
| Input field | Default | Description |
|---|---|---|
startUrls | demo https://example.com/ if nothing is given | Public http(s) URLs, each fetched once (no crawling). |
rawHtml / rawHtmlBaseUrl | – | One HTML document to convert without fetching, plus an optional base URL. |
htmlDocuments | – | Many documents: [{ "html": "...", "url": "optional base URL" }]. |
extractMainContent | true | Readability + clean-up; false converts the whole <body>. |
keepLinks / keepImages / keepTables | true / false / true | What to render in the Markdown. |
includeLinks | false | Add a links array (max 500). |
redactEmails | true | Replace e-mail addresses with [email removed]. |
maxPages | 100 | 1–10,000 per run; also capped by Max total charge. |
requestTimeoutSecs / maxConcurrency / maxRequestsPerMinute | 30 / 5 / 60 | Fetch limits. |
proxyConfiguration | off | Optional Apify Proxy. Not used to bypass logins or paywalls. |
Output fields
| Field | Description |
|---|---|
url, requestedUrl, source | Final URL, requested URL, url or html. |
status | ok or error. |
title, description, language | From <title>/Open Graph, meta description, <html lang>. |
markdown, wordCount | Converted Markdown; words without code blocks and URLs. |
headings | { level, text } for H1–H6. |
links | Only with includeLinks. |
metadata | canonicalUrl, siteName, ogType, ogImage, publishedTime, modifiedTime, keywords, extractionMode, markdownLength; for URLs also statusCode, contentType, fetchedAt. |
error, errorCode | NOT_FOUND, ACCESS_RESTRICTED, UNAVAILABLE_FOR_LEGAL_REASONS, HTTP_ERROR, ROBOTS_TXT_DISALLOWED, TIMEOUT, NOT_HTML, FETCH_FAILED, INVALID_URL, CONVERSION_FAILED. |
HTML to Markdown API (cURL, JavaScript)
curl -X POST "https://api.apify.com/v2/acts/grace_hartwell~html-to-markdown-json/run-sync-get-dataset-items?token=[YOUR_APIFY_TOKEN]" \-H "Content-Type: application/json" \-d '{"startUrls":[{"url":"https://example.com"}],"maxPages":10}'
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('grace_hartwell/html-to-markdown-json').call({startUrls: [{ url: 'https://example.com' }],});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items[0].markdown);
Under the hood: Crawlee CheerioCrawler (plain HTTP, no browser), linkedom, Mozilla Readability and Turndown with custom rules for links, images and tables.
FAQ
Does it render JavaScript?
No. It parses the HTML the server returns. Pages that build their content only in the browser may come back short; check wordCount.
Can it crawl a whole website to Markdown?
No. Each URL is converted once. Pass a list of URLs, for example from the sitemap.
Will Markdown always use fewer tokens?
Fewer than raw HTML in our test, yes. Fewer than plain text, not necessarily: in our test it was about the same size, and on 2 of 10 pages it was over 45 % larger, because Markdown keeps links and tables. With keepLinks turned off, a second run came out at a median 21.25 % fewer tokens than plain text.
Can it get past logins, paywalls or bot protection?
No. Those pages come back as free ACCESS_RESTRICTED items.
Does it extract e-mails or phone numbers?
No. If a page you choose contains personal data, you need a legal basis (for example under GDPR) to process it.
Limitations: what this Actor does not do
- No JavaScript rendering (Cheerio, no headless browser).
- No crawling; duplicate input URLs are converted once.
- No logins, cookies, paywall or anti-bot bypass.
- Only HTML is converted; PDFs and images return free
NOT_HTML/FETCH_FAILEDitems. - Images are not downloaded;
<figcaption>,<iframe>,<svg>,<canvas>, scripts and styles are dropped. - Tables are simplified: nested markup becomes plain text.
- Heuristic boilerplate removal can occasionally remove wanted content (class names like
relatedorshare). Turn offextractMainContentif that happens. - Each run is capped by
maxPages(max 10,000) and your Max total charge.
Other Actors by Hartwell Toolworks
| Actor | What it does |
|---|---|
| Broken Link Checker & Redirect Chain Checker | 404s, 5xx, redirect chains and loops, with every hop |
| Deduplicate & Merge Apify Datasets | Merge scraper runs; only new, unique items; duplicates are free |
| Bulk PageSpeed Insights & Core Web Vitals Check | LCP, INP, CLS on mobile and desktop, with regression alerts |
Found a bug or an edge case? Open an issue on the Issues tab.