What the result contains
What This Tool Provides
Convert HTML into clean Markdown in your browser. The conversion uses the browser’s own HTML parser rather than pattern matching, so unclosed tags recover the way they do in a real page and nested structures survive. Scripts, styles and embedded frames are discarded rather than converted, and the page reports exactly which tags it threw away.
- Headings, paragraphs, emphasis, lists, blockquotes and code blocks as Markdown
- Tables converted to GitHub pipe syntax
- Links and images with their titles and alt text preserved
- A list of tags that were discarded rather than converted
How to Use This Tool
- Paste the HTMLA full page, a fragment, or markup copied from a browser’s element inspector.
- Choose the Markdown styleHyphen or asterisk bullets, hash headings or underlined ones, and whether to keep tags with no Markdown equivalent.
- Check what was discarded, then copyThe summary names any tag dropped, so a missing section is visible rather than mysterious.
How It Works
The HTML is handed to DOMParser with the text/html content type, which builds an inert document: scripts do not run, event handlers do not fire, and images and stylesheets referenced in the markup are never fetched. The resulting tree is then walked node by node, with each element mapped to its Markdown equivalent and text nodes escaped so characters like asterisks and leading hashes do not accidentally become syntax. Using the real parser rather than regular expressions is what makes malformed input safe to handle: browsers have a specified recovery algorithm for unclosed and misnested tags, and this inherits all of it for free.
Worked Examples
A small article
- Input
<h1>Release notes</h1><p>Fixes <strong>two</strong> bugs in <code>parse()</code>.</p><ul><li>Faster on large files</li></ul>- Output
# Release notes Fixes **two** bugs in `parse()`. - Faster on large files
Each element becomes its Markdown equivalent, and the inline code span keeps its backticks rather than being treated as emphasis.
Scripts and styles are discarded, not converted
- Input
<p>keep</p><script>alert(1)</script><style>p{color:red}</style>- Output
keep (discarded: script, style)
Neither has a Markdown form and neither is prose. They are removed entirely and named in the summary so the removal is visible.
Text that would become syntax gets escaped
- Input
<p>Use the * character and _underscores_ carefully</p>- Output
Use the \* character and \_underscores\_ carefully
Without escaping, converting and then re-rendering would silently turn those characters into emphasis markers.
Why a Parser and Not a Pattern
Trying to convert HTML with regular expressions is the best-known bad idea in text processing, and the reasons are concrete rather than aesthetic. HTML nests to arbitrary depth, so a pattern cannot reliably match an element and its own closing tag. Attribute values may legally contain angle brackets. Tags may be unclosed, misnested, or implicitly closed by a following sibling, and every browser applies a specified recovery algorithm to sort that out.
DOMParser is that algorithm, already present in the browser, already correct. Handing it the markup gives back a tree that reflects what a browser would actually render, including all the recovery — so a fragment copied from a page with three unclosed list items converts the same way it displays. The conversion becomes a tree walk, which is a simple problem, instead of a pattern-matching problem, which is an impossible one.
The choice also has a security dimension. Parsing with the text/html content type produces an inert document: no script executes, no event handler runs, and nothing referenced in the markup is fetched. That matters because the input is usually copied from somewhere else, and a converter that rendered it live would be running someone else’s code on a page whose entire promise is that your input goes nowhere. Converting markup you did not write is safe here precisely because the parse is inert.
What Survives the Conversion and What Does Not
Markdown is a much smaller language than HTML, so this direction is lossy by definition. What matters is that the losses are predictable and visible rather than surprising.
Structure and prose survive: headings, paragraphs, emphasis, lists including nesting, blockquotes, code blocks with their language class, links with titles, images with alt text, and tables in GitHub pipe syntax. Presentation does not: classes, ids, inline styles, data attributes and layout wrappers have no Markdown equivalent and are unwrapped, keeping their contents and dropping the container.
Three categories are removed outright, because they are not prose at all: script and style elements, embedded frames and objects, and inline SVG and canvas. Each is named in the summary under the output. That reporting is the point — a converter that silently swallowed a whole section would leave you comparing two documents by eye to work out what went missing.
| Input | Result | Notes |
|---|---|---|
| Headings h1 to h6 | Hash headings | Or underlined, if ATX is switched off |
| Lists, including nested | Markdown lists, indented | Ordered lists honor a start attribute |
| pre with a code child | A fenced code block | The language- class becomes the fence language |
| Tables | GitHub pipe tables | Pipes inside cells are escaped |
| div, span, section | Unwrapped | Contents kept, container discarded |
| script, style, iframe, svg | Removed and reported | Not prose, and no Markdown form |
Escaping, and the Round Trip
A subtlety that separates a careful converter from a quick one: text taken out of HTML may contain characters that mean something in Markdown. A paragraph that literally reads "5 * 3 = 15" converts to Markdown that, when rendered again, turns everything between the asterisks into emphasis. So those characters are escaped with a backslash on the way out.
The escaping is deliberately narrow rather than exhaustive. Escaping every possible special character produces output littered with backslashes that is unpleasant to edit by hand, which defeats the purpose of converting to Markdown at all. Only inline emphasis characters and the markers that would start a block at the beginning of a line — a hash, a dash, a number followed by a period, a greater-than sign — are escaped.
Together with the reverse conversion, that makes a round trip mostly stable for the constructs Markdown can express. Mostly, not perfectly: HTML that used a div for layout comes back without it, and a table with merged cells cannot survive, because Markdown tables have no concept of a colspan. Treat the pair as a migration aid rather than a lossless channel.
What People Convert, and What Comes Next
Three tasks account for most conversions in this direction. Moving documentation out of an old CMS into a repository where it can live in version control. Turning a published page back into editable source when the original was lost. And capturing a fragment from a browser’s element inspector to paste into an issue or a pull request without dragging the styling along.
For the CMS migration in particular, the file names matter as much as the content: a title becomes a path, and turning each title into a clean slug is what keeps the URLs stable and readable after the move. Headings imported from several authors usually arrive in inconsistent capitalization too, and normalizing them in one pass is faster than editing each one.
Two cautions for migrated content. Code samples in old documentation frequently contain a credential somebody pasted in while it was working, and moving the page does not make it any less exposed — generate a replacement for anything live you find. And content pulled from an export rather than a page often arrives Base64-encoded rather than as plain markup, which looks like corruption until you decode it.
Two other things come up often enough to expect. Content pulled out of an API rather than a page usually arrives wrapped in JSON, so formatting and validating that payload is the step before conversion rather than after. And when a converted document differs from what you expected, diffing it against the previous version localizes the change immediately, which is much quicker than rereading both.
Important Edge Cases
- Text that would read as Markdown syntax is escaped with a backslash, so converting and re-rendering does not silently introduce emphasis.
- A code element inside a pre becomes a fenced block; the same element on its own becomes an inline span.
- A code span containing a backtick gets a longer fence around it, which is what Markdown requires.
- Unclosed and misnested tags are recovered by the browser’s own algorithm before conversion starts, so malformed markup usually still converts sensibly.
- A table with merged cells loses the merge, because Markdown tables have no colspan or rowspan.
Limitations
- The conversion is lossy: classes, ids, inline styles and layout wrappers have no Markdown equivalent and are discarded.
- Script, style, iframe, object, svg and canvas elements are removed entirely rather than converted.
- Definition lists, footnotes and reference-style links are not produced; nested structures beyond lists are flattened.
- Table alignment attributes are not carried across, only the cell contents and column structure.
- Input is capped at 500,000 characters, so a very large page is better handled by a script.
Input handling
Private Browser Processing
The HTML is parsed and converted entirely in your browser, using an inert document that runs no scripts and fetches nothing referenced in the markup. Nothing is uploaded, stored, or logged.
Google Analytics records page visits and whether a tool finished or failed, but these tool implementations do not send field values, generated passwords, QR payloads, uploaded QR images, or camera frames to analytics or a Tiny Tiny Tools processing endpoint.
See the Privacy Policy for site-wide details.
Questions About This Tool
Why use a parser instead of find and replace?
Because HTML nests arbitrarily deep and real markup is full of unclosed tags. Browsers have a specified recovery algorithm for that, and DOMParser is it. Using the real parser means malformed input converts the way it displays, which no pattern can promise.
Is it safe to paste HTML from a site I do not control?
Yes. Parsing with the text/html type builds an inert document: scripts do not execute, event handlers do not fire, and images and stylesheets in the markup are never fetched. The tags become data, not behavior.
Where did my divs and classes go?
Markdown has no equivalent, so layout containers are unwrapped — their contents are kept and the container is dropped. Elements that are not prose at all, like script and style, are removed entirely and named in the summary.
Why are there backslashes in my output?
They escape characters that would otherwise become Markdown syntax. Without them, a sentence containing asterisks would render as emphasis when the Markdown is converted back. The escaping is kept narrow so the output stays editable.
Can I convert back and forth without losing anything?
Only for the constructs Markdown can express. Headings, lists, links and code survive a round trip; layout divs, styling and merged table cells do not. It is a migration aid rather than a lossless channel.
Does it handle tables?
Yes, into GitHub pipe syntax, with pipes inside cells escaped. Merged cells cannot survive, because Markdown tables have no colspan or rowspan.