HTML to Markdown Converter: Webpage to Markdown & JSON avatar

HTML to Markdown Converter: Webpage to Markdown & JSON

Pricing

from $1.50 / 1,000 page converteds

Go to Apify Store
HTML to Markdown Converter: Webpage to Markdown & JSON

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

Grace M. Hartwell

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 minutes ago

Last modified

Share

Hartwell Toolworks

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 language and wordCount, 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 HTML92.41 % fewer tokens (range 75.82 %–99.63 %)
All 10 pages together693,388 → 52,970 tokens
Example page (Wikipedia "RAG")76,605 → 5,366 tokens
vs. plain extracted textabout 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 (![alt](src)).
  • 📊 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, text and an internal flag.
  • 🔒 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:

EventPriceWhen
page-converted$0.0015 per page ($1.50 per 1,000)after a converted page is saved
apify-actor-start$0.00005 per runautomatically 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

  1. Click Try for free.
  2. Add public URLs under URLs, and/or paste HTML into Raw HTML (set Base URL for raw HTML so relative links become absolute).
  3. Choose options: main content only, keep links, keep images, convert tables, links list, redact e-mails.
  4. Optional: set Max pages and a Max total charge.
  5. 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 fieldDefaultDescription
startUrlsdemo https://example.com/ if nothing is givenPublic 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" }].
extractMainContenttrueReadability + clean-up; false converts the whole <body>.
keepLinks / keepImages / keepTablestrue / false / trueWhat to render in the Markdown.
includeLinksfalseAdd a links array (max 500).
redactEmailstrueReplace e-mail addresses with [email removed].
maxPages1001–10,000 per run; also capped by Max total charge.
requestTimeoutSecs / maxConcurrency / maxRequestsPerMinute30 / 5 / 60Fetch limits.
proxyConfigurationoffOptional Apify Proxy. Not used to bypass logins or paywalls.

Output fields

FieldDescription
url, requestedUrl, sourceFinal URL, requested URL, url or html.
statusok or error.
title, description, languageFrom <title>/Open Graph, meta description, <html lang>.
markdown, wordCountConverted Markdown; words without code blocks and URLs.
headings{ level, text } for H1–H6.
linksOnly with includeLinks.
metadatacanonicalUrl, siteName, ogType, ogImage, publishedTime, modifiedTime, keywords, extractionMode, markdownLength; for URLs also statusCode, contentType, fetchedAt.
error, errorCodeNOT_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_FAILED items.
  • 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 related or share). Turn off extractMainContent if that happens.
  • Each run is capped by maxPages (max 10,000) and your Max total charge.

Other Actors by Hartwell Toolworks

ActorWhat it does
Broken Link Checker & Redirect Chain Checker404s, 5xx, redirect chains and loops, with every hop
Deduplicate & Merge Apify DatasetsMerge scraper runs; only new, unique items; duplicates are free
Bulk PageSpeed Insights & Core Web Vitals CheckLCP, INP, CLS on mobile and desktop, with regression alerts

Found a bug or an edge case? Open an issue on the Issues tab.