DataSwap Fast file & data format converters, no signup

HTML to Markdown Converter

Paste HTML below — clean Markdown appears instantly. Nothing you paste ever leaves your browser.

Real DOM parsing, then a straightforward tree walk

This tool hands your HTML to DOMParser — the same parser your browser uses for every page it renders — instead of trying to hand-write regular expressions over raw HTML text, which is exactly the kind of approach that breaks the moment it meets real-world markup with unusual nesting or unclosed tags. Once it has a correct DOM tree, it walks every node recursively: block tags like headings, lists, and blockquotes become their Markdown equivalent, inline tags like bold, italic, links, and code become their inline Markdown syntax, and plain text is carried through with whitespace collapsed the way a browser would render it. See the FAQ for exactly which tags are covered and which are deliberately out of scope.

Worked example

Input:

<h2>Shopping List</h2>
<p>Do not forget the <strong>milk</strong> and <em>bread</em>.</p>
<ul>
  <li>Milk</li>
  <li>Bread</li>
  <li>Eggs</li>
</ul>
<blockquote>Check the coupon before checkout.</blockquote>

Output:

## Shopping List

Do not forget the **milk** and *bread*.

- Milk
- Bread
- Eggs

> Check the coupon before checkout.

Frequently asked questions

Does this handle any HTML I throw at it?

It converts a documented, honest subset — the tags people actually use for everyday content: headings (h1–h6), bold (strong/b), italic (em/i), links, images, single-level unordered and ordered lists, blockquotes, horizontal rules, paragraphs and line breaks, and both inline code and fenced code blocks (pre / pre > code). It does not attempt tables, nested lists, definition lists, or layout markup like divs and spans used purely for styling — those either get skipped or have their text recursed into without any special Markdown syntax added. For a blog post, an article, or a snippet of formatted content, that subset covers the vast majority of real-world HTML; it's not a general-purpose HTML-to-Markdown compiler for arbitrary web pages.

Why does it use the browser's own DOMParser instead of a hand-written HTML parser?

Because HTML parsing is a genuinely hard problem that's already been solved correctly, for free, by every browser engine. Real-world HTML is full of edge cases — unclosed tags, implicit tag-closing rules, attributes without quotes, mismatched nesting — that the HTML spec defines precise recovery behavior for for exactly the reason that hand-written parsers routinely get subtly wrong. This tool parses with new DOMParser().parseFromString(html, "text/html") — the same engine your browser uses to render any page you visit — and then walks the resulting, already-correct DOM tree. That's a deliberate engineering choice: don't reinvent something notoriously easy to get wrong when a correct implementation is sitting right there in the browser.

Is my HTML uploaded anywhere?

No. Parsing and the entire tree walk happen locally, in your browser; nothing you paste is transmitted to, or stored on, a server. That's true for every tool on this site, and it matters here specifically because HTML you're converting is often an unpublished draft or content pulled from somewhere you'd rather not re-upload.

What happens with a nested list, like a <ul> inside an <li>?

It's outside this tool's documented scope, honestly. This converter reliably handles one level of list nesting — a straightforward ul or ol with li children. A list nested inside another list item isn't specifically detected, so its items get recursed into as plain text rather than reproduced as a properly indented, nested Markdown list. If you need pixel-perfect nested-list conversion, this isn't that tool; for the flat, single-level lists most everyday content actually uses, it converts cleanly.

Does it preserve exact whitespace and indentation from my HTML?

Only where it should. Outside of <pre> and code blocks, runs of whitespace in text — extra spaces, line breaks from pretty-printed source — are collapsed to a single space, the same way a browser renders ordinary HTML text; this stops indentation from your source HTML leaking into the Markdown as stray line breaks. Inside <pre> or <pre><code>, the original text content is read and reproduced exactly, whitespace included, because that's precisely the content a fenced code block is supposed to preserve.