HTML to Markdown Converter - URL or HTML to GFM
Pricing
$1.50 / 1,000 converted pages
HTML to Markdown Converter - URL or HTML to GFM
Convert a page (by URL) or raw HTML to clean GitHub-Flavored Markdown - headings, links, fenced code, tables, strikethrough. Single, bulk, or inline HTML. $0.0015 per page no start fee, cheaper than paid converters; failed fetches free.
Pricing
$1.50 / 1,000 converted pages
Rating
0.0
(0)
Developer
Anthony Snider
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 hours ago
Last modified
Categories
Share
HTML to Markdown Converter - URL or Raw HTML to Clean GitHub-Flavored Markdown
Give it a URL or an HTML string, get clean GitHub-Flavored Markdown back - real code fences with language hints, real GFM tables, strikethrough, and links, with the scripts, styles and hidden elements stripped out. Single page, bulk list, or inline HTML. $0.0015 per page, no start fee. Failed fetches are recorded free.
Feeding pages to an LLM is the common case: Markdown carries the same structure as HTML at a fraction of the tokens. Docs migration, turning a knowledge base into a RAG corpus, and archiving articles as text all want the same thing.
What you get
Per page or HTML string, one record with these exact fields:
ok- true when the conversion produced Markdownurl- the final URL after redirects (null when you passed raw HTML with nobaseUrl)title- the page's<title>, when it has onemarkdown- the converted documentlength- character length of the Markdownerror- present instead ofmarkdownwhen the fetch failed. Never charged.
Conversion specifics that matter in practice:
- ATX headings (
#),-bullets, inlined links,**bold**,*italic*,~~strikethrough~~ - Fenced code blocks, with the language taken from
class="language-js",lang-jsorhighlight-js <table>rebuilt as a GFM pipe table, with|inside cells escaped<script>,<style>,<noscript>,<iframe>,<svg>,<link>,<meta>and elements hidden viadisplay:noneorhiddenare removed before conversion- Only
<body>is converted, so head metadata never leaks into the text - Relative links and images are rewritten to absolute URLs using the page URL (or
baseUrlfor raw HTML)
Example 1: raw HTML, showing what survives conversion
Input:
{"html": "<html><head><title>Release notes</title></head><body><h1>v2.1</h1><p>Ships <del>beta</del> <strong>stable</strong> support.</p><pre><code class=\"language-js\">const x = 1;</code></pre><table><tr><th>Flag</th><th>Default</th></tr><tr><td>retry</td><td>3</td></tr></table><script>alert(1)</script></body></html>"}
Output (real run, 2026-08-15):
{"ok": true,"url": null,"title": "Release notes","markdown": "# v2.1\n\nShips ~~beta~~ **stable** support.\n\n```js\nconst x = 1;\n```\n\n| Flag | Default |\n| --- | --- |\n| retry | 3 |","length": 114}
The <script> is gone, the <del> became ~~beta~~, the code block kept its js language hint,
the table is valid GFM, and the <title> was captured separately instead of being dumped into the
text.
Example 2: one live page
Input:
{ "url": "https://example.com" }
Output (real run, 2026-08-15):
{"ok": true,"url": "https://example.com/","title": "Example Domain","markdown": "# Example Domain\n\nThis domain is for use in documentation examples without needing permission. Avoid use in operations.\n\n[Learn more](https://iana.org/domains/example)","length": 167}
Note url is the URL after redirects. Any relative link on a page (/docs/install) is rewritten
against that final URL, so the Markdown still resolves when you store it somewhere else.
Example 3: bulk, for a docs migration
Input:
{"urls": ["https://example.com/docs/intro","https://example.com/docs/install","https://example.com/docs/api"],"maxUrls": 200}
One record per URL, each charged once. A URL that 404s becomes
{"ok": false, "error": "HTTP 404"} and is not charged. When urls is filled, the single url
field is ignored - you are charged for the pages you listed and nothing else.
Pricing
$0.0015 per page converted. No start fee. One event covers one page fetched and converted, or one raw HTML string converted, including the title extraction. A failed fetch (DNS failure, timeout, 4xx, 5xx) is recorded and never charged.
Honest comparison, prices read from the Apify Store API on 2026-08-07:
| Actor | Pricing | Cost of one page |
|---|---|---|
| This actor | $0.0015 per page, no start fee | $0.0015 |
| shoebill-dev27/html-to-markdown | $0.005 start + $0.002 per item | $0.007 |
| scrapeworks/pandoc-document-converter | $0.00005 start + $0.005 per result | $0.005 |
Those are single-page costs. On a 500-page docs migration the start fee amortizes, so the honest comparison there is per-item: $0.0015 against $0.002 and $0.005.
When NOT to use this
- JavaScript-rendered pages. This fetches server HTML. If the content only exists after the page
runs its scripts (most single-page apps, infinite-scroll feeds), you will get the shell, not the
article. Render it yourself with a browser actor and pass the result in as
html. - Pages behind a login or a bot wall. Requests are plain unauthenticated GETs with a normal User-Agent. There is no proxy rotation, no cookie jar, no CAPTCHA handling.
- PDFs, Word documents, or images. This is an HTML converter. Use a PDF text extractor for those.
- Pixel-faithful layout. Deeply nested tables and CSS grid layouts are flattened into valid Markdown, which is a lossy target by design.
- A single page, once, by hand. Browser extensions do that for free. This is worth paying for in a pipeline, across many pages, or as a tool an agent can call.
Honest limits
- Server-side HTML only, as above. 20 second fetch timeout per page.
- Up to 200 pages per run (
maxUrls, default 50). - Nested tables are simplified; a table inside a table cell will not round-trip.
- Raw HTML mode takes priority: if you pass
html, no URL is fetched in that run. PassbaseUrlwhen you want relative links inside that HTML resolved to absolute ones.
FAQ
How do I convert a web page to Markdown for an LLM or RAG pipeline?
Send {"url": "https://..."} and use the markdown field. It typically costs a fraction of the
tokens the raw HTML would, and it keeps the headings, lists and tables that chunking relies on.
Can I pass HTML I already fetched or rendered myself?
Yes, that is the html field, and it is the recommended path for JavaScript-heavy sites: render the
page with your own browser or a browser actor, then send the DOM here. Add baseUrl so relative
links resolve.
Does it keep code blocks and their language?
Yes. <pre><code class="language-js"> becomes a fenced block tagged js. Common class conventions
(language-, lang-, highlight-) are all recognized.
Are HTML tables converted to Markdown tables?
Yes, as GFM pipe tables, with a header separator row and | characters inside cells escaped so the
table does not break. Ragged rows are padded to the widest row.
How many pages can I convert in one run?
Up to 200. Put them in urls; each is one record and one charge, and one bad URL does not stop the
rest.
Do relative links break when I move the Markdown elsewhere? No. Links and image sources are resolved against the page's final URL (after redirects), so they come out absolute.
Why did a page come back with almost no Markdown?
Almost always JavaScript rendering: the server HTML really was near-empty. Check length - if it is
tiny for a page you know is long, render it first and pass html.
Use from code or AI agents
curl -s "https://api.apify.com/v2/acts/EliAI~html-to-markdown/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-X POST -H 'Content-Type: application/json' \-d '{"url":"https://github.com/apify/apify-sdk-js"}'
Agents: connect Apify MCP and call the EliAI/html-to-markdown tool.
- Capability: convert a page URL, a bulk list of URLs, or a raw HTML string into GitHub-Flavored Markdown
- Required input:
url,urls, orhtml - Returns: one record per page;
markdownandtitleare the payload - Bounded: 200 pages per run; failures isolate per page
- Side effects: none beyond fetching the pages you named
Related actors
- Markdown to HTML (
EliAI/markdown-to-html) - the inverse trip, with a table of contents and sanitized output.