HandyTools Hub

🔃 HTML to Markdown Converter

Paste HTML and get clean Markdown instantly

🔒 100% client-side processing

Moving content out of HTML and into Markdown is mostly mechanical, but the details decide whether the result is clean or full of stray tags. This converter walks the parsed DOM and emits inline-link Markdown: it keeps visible content, drops scripts and styles, and unwraps tags it does not recognize instead of leaking them into the output. Conversion happens locally in the browser, so pasted content stays on your machine.

How to Use

  1. Paste an HTML snippet or a full document into the input area, or load the sample to see the mapping.
  2. Read the Markdown output, which updates on every keystroke without a convert button.
  3. Copy the result to the clipboard, or download it as a .md file.

What the Converter Does to Each Element

HTMLMarkdown output
h1 to h6ATX heading with one to six #
pparagraph with a blank line
brsingle line break
hr--- rule
strong, b**bold**
em, i*italic*
codeinline backticks
prefenced code block
a[text](href), inline style
img![alt](src)
ul, ol, libullets or numbers, nested with two-space indents
blockquote> quoted lines
tablepipe table with a separator after row one

Tags such as div, section, article, header, and footer are treated as generic blocks: their children are rendered and a blank line is added. Unknown inline tags are unwrapped so their text survives.

A Worked Example

Input:

<h2>Release notes</h2>
<p>Version <strong>2.1</strong> adds a <a href="/docs">docs</a> link.</p>
<ul>
  <li>Faster build
    <ul><li>Incremental cache</li></ul>
  </li>
  <li>New CLI flag</li>
</ul>

Output:

## Release notes

Version **2.1** adds a [docs](/docs) link.

- Faster build
  - Incremental cache
- New CLI flag

The nested list picks up exactly two spaces of indent, the strong tag becomes double asterisks, and the link becomes an inline [text](href) pair.

Tables, Lists, and Nesting

Tables are rebuilt from their tr and td rows. Cell contents are flattened to a single line, literal pipe characters are escaped as \|, and the number of columns is taken from the widest row, with missing cells padded. Lists are rendered recursively: only direct li children are numbered or bulleted, and a list nested inside an item is pushed onto its own line with deeper indentation.

When Output Is Lossy

The converter favors clean text over pixel-perfect fidelity, so a few things are intentionally dropped or simplified:

  • Scripts, styles, noscript, template, and head content are removed entirely.
  • HTML comments never appear in the output.
  • colspan and rowspan are ignored, so merged cells become separate empty cells.
  • Nested tables can flatten, because every descendant row is collected into one table.
  • Complex whitespace is collapsed, and text inside pre is preserved except for leading and trailing blank lines.
  • Iframes and other embedded widgets carry no text, so nothing from them survives.
  • No Markdown escaping is applied, so source text containing *, _, `, or [ may change meaning on re-render.

If the output is going into a strict renderer, scan it once for stray asterisks or underscores around text that was literal in the original HTML.

Common Conversion Mistakes

A few surprises account for most of the complaints. Whitespace from source indentation collapses to single spaces, so anything that was aligned only by markup spacing loses that alignment. A link with no href is reduced to its text, which is usually harmless, but an image with no src disappears entirely. br tags become real line breaks, and whether those break a paragraph depends on the surrounding block. Because the converter never escapes Markdown syntax, a product name like 5*4*3 becomes emphasis when the output is rendered, and a stray underscore in a username can italicize the rest of a line. Checking these four things covers the large majority of rough edges.

Migrating Content From a CMS

The most reliable way to move an article is to work from the rendered HTML, not from the editor’s own export. Open the page, view the source or copy the article element, and paste the markup here. Then check the output in four passes: headings should line up with your target site’s structure, code blocks should be fenced and re-tagged with a language if you need syntax highlighting, tables should have the intended first row promoted to the header, and inline links should point at the URLs you expect. Save the result as a .md file and add the frontmatter your static site expects. Because the conversion is instant, it is practical to process one article at a time and eyeball each result rather than trusting a bulk run blind.

Why Convert to Markdown at All

Markdown is easier to read, diff, and review than HTML. In a Git repository, a one-word change to a Markdown paragraph shows up as a one-line diff, while the same edit in HTML can touch attributes and closing tags. Markdown is also portable: the same file renders in static site generators, note apps, README files, and documentation systems. HTML remains the better choice when you need precise layout, embedded widgets, or styling, which is exactly why converting in one direction while keeping the source in HTML is a common workflow. Convert once for archival or publishing, and keep the richer HTML wherever it is still needed.

Frequently Asked Questions

Do I need to paste a complete HTML document with html and body tags?

No. Both full documents and fragments work. The converter parses whatever you paste with the browser's own DOM parser, which tolerates unclosed and malformed tags, then reads the resulting body.

Why did my table gain a header separator after the first row?

The first row is always treated as the header, even if it contains td cells rather than th. A Markdown separator line is inserted after it. Tables with no header row will have their first data row promoted.

Are fenced code blocks given a language tag?

No. A pre element becomes a bare fenced block, and the language class on an inner code tag is not carried across. You can add the language yourself after conversion.

Does the converter escape Markdown special characters in my text?

No. A literal asterisk, underscore, hash, or bracket in the source text is emitted as-is, so text that was plain in HTML can act as Markdown syntax when the output is rendered again.

How are HTML entities such as amp and nbsp handled?

The DOM parser decodes them before conversion, so &amp; becomes a plain & and &nbsp; becomes a non-breaking space character. The non-breaking space is invisible but present, which can look like an odd gap.

How does the tool indent nested lists?

Each nesting level adds two spaces of indentation before the list marker. Ordered lists number from 1 within their own list, and mixed nested lists keep their own marker style.

Reviewed by the HandyTools Hub team · Last updated