Convert HTML to Markdown
Paste HTML on the left and read Markdown on the right. Parsing is done by the browser’s own HTML parser, so unclosed tags, stray attributes, and the messy markup that comes out of a CMS or a page inspector are normalized before any conversion rule runs.
The output is CommonMark with GitHub extensions: pipe tables, strikethrough from <del> and <s>, and task list items from <li> elements that start with a checkbox.
Heading, bullet, and emphasis style
Markdown has several spellings for the same construct, and the target parser or linter usually has an opinion about which one it wants.
- Headings:
# ATXwrites## Heading. Setext underlines the first two levels with===and---, and falls back to ATX forh3and deeper, since Setext has no third level. - Bullets:
-,*, or+. Ordered lists keep thestartattribute, so a list beginning at<ol start="5">numbers from 5. - Emphasis: asterisks or underscores. Strong text uses the same character doubled, so choosing
_gives_em_and__strong__.
Code blocks and language hints
A <pre> block becomes a fenced block by default. The fence grows past any backtick run inside the code, so a snippet that contains ``` does not terminate its own block early.
Language comes from the <code> element: a language-js, lang-js, or highlight-js class, or a data-lang attribute, becomes the info string after the fence. Highlight.js and Prism markup both use that convention, so code copied from a documentation site usually keeps its language. Switch to a 4-space indent when the destination does not support fences.
Tables a pipe table cannot hold
A GFM pipe table is a rectangle of inline content. When a table uses colspan or rowspan, has uneven row lengths, or holds a list, a nested table, or a code block inside a cell, no arrangement of pipes represents it.
The Tables control decides what happens then:
- Pipe tables converts what fits and keeps the original
<table>markup for what does not, which loses nothing. - Keep HTML always keeps the markup, which is the safe choice for documentation tables with merged header cells.
- Plain rows flattens every table to text rows separated by
|, which is readable but discards structure.
Column alignment comes from an align attribute or an inline text-align on the header cells, and becomes :---, :---:, or ---:.
Inline links vs a reference block
Inline links keep the destination next to the text. Reference style replaces each destination with a numbered label and collects the definitions at the end of the document:
See the [spec][1] and the [errata][2].
[1]: https://example.com/spec
[2]: https://example.com/errata
Reference style suits long prose with repeated or very long URLs, since it keeps paragraphs readable in a plain text editor. Identical destinations share one number. Text only strips the destination and keeps the anchor text, which is what you want when converting a page for a diff or a word count. Destinations containing spaces or parentheses are wrapped in angle brackets so they parse.
Escaping literal characters
Body text often contains characters that Markdown reads as syntax. A product name like *Star* or a price range like [10] would render as emphasis and a broken link reference. With escaping on, those become \*Star\* and \[10\], and a line starting with #, >, -, or 1. gets a backslash so it stays a paragraph.
Underscores are the exception: snake_case is far more common in technical text than intraword emphasis, so an underscore between two alphanumerics is left alone. Turn escaping off when the HTML already contains Markdown you want to survive intact.
Main content only
A saved page carries navigation, cookie banners, sidebars, and a footer, all of which become Markdown noise. With Main content only on, conversion starts at the first <main>, <article>, or role="main" element in the document and ignores everything outside it. Pages without any of those fall back to the full body.
What gets dropped
<script>, <style>, <noscript>, <template>, comments, and head elements are removed before the walk begins. Form controls produce nothing, apart from a list item’s leading checkbox, which becomes [x] or [ ].
Everything Markdown has no syntax for is either dropped or passed through as raw HTML, depending on the Keep unsupported HTML setting. That covers <iframe>, <video>, <audio>, <canvas>, inline <svg>, and inline tags such as <sup>, <sub>, <mark>, and <abbr>. Markdown parsers accept raw HTML, so keeping it is lossless, though some renderers strip it again on the way out.
Two conversions are approximations worth knowing about. Definition lists have no Markdown equivalent, so <dt> becomes a bold line and <dd> a paragraph under it. A <br> becomes a hard line break, written as two trailing spaces before the newline, which is invisible in a text editor and stripped by some formatters.