FormatterHQ

HTML to Markdown Converter

Turn HTML into readable Markdown for READMEs, wikis, static sites and notes. Headings, emphasis, links, images, lists, code blocks and tables are converted.

Input HTML
Output MARKDOWN
Ready.

How to use the HTML to Markdown Converter

  1. Paste the HTML you want to convert.
  2. Choose the heading style, bullet character, code block style and emphasis delimiter.
  3. The Markdown updates automatically as you edit the HTML or the options.
  4. Copy the Markdown or download it as a .md file.

Why convert HTML to Markdown?

Markdown has become the default writing format for documentation, READMEs, static site generators, wikis and note-taking apps. When content exists only as HTML (an old blog, a CMS export, a web page you want to keep), converting it by hand is slow. This HTML to Markdown converter, built on the Turndown library with GitHub-style extensions, produces tidy Markdown you can edit comfortably.

Example

<h1>Getting Started</h1>
<p>Install the <strong>CLI</strong> and run your <em>first</em> build.</p>
<ul><li>Fast</li><li><del>Slow</del></li></ul>
<pre><code class="language-bash">npm install -g my-cli</code></pre>
<table><tr><th>Flag</th><th>Meaning</th></tr><tr><td>-v</td><td>verbose</td></tr></table>
<p>See <a href="https://example.com">the docs</a>.</p>
# Getting Started

Install the **CLI** and run your _first_ build.

- Fast
- ~~Slow~~

```bash
npm install -g my-cli
```

| Flag | Meaning |
| --- | --- |
| -v | verbose |

See [the docs](https://example.com).

Style options

  • Heading style – ATX (# Heading) works for all levels and is the common choice. Setext underlines headings with === or ---, but only exists for levels 1 and 2.
  • Bullet character – -, * or +. They are equivalent; pick the one your linter or style guide prefers.
  • Code blocks – fenced blocks keep the language from a language-* or lang-* class for syntax highlighting; indented blocks (four spaces) are the classic alternative.
  • Emphasis – _underscores_ or *asterisks* for italics. Bold always uses **.

How special content is handled

  • Tables become GitHub-style pipe tables. Markdown tables cannot contain merged cells or block content, so complex tables are simplified.
  • Strikethrough (del, s, strike) becomes ~~text~~.
  • Numbered lists keep a custom start number, and nested lists are indented correctly.
  • Scripts, styles, noscript and templates are removed entirely.
  • Elements with no Markdown equivalent, such as div and span, are reduced to their content. Classes, inline styles and colors are lost, because Markdown has no syntax for them.
  • Special characters that would otherwise trigger Markdown formatting, such as a leading # or * in normal text, are escaped with a backslash.

Common use cases

  • Migrating a blog from WordPress or another CMS to a static site generator such as Hugo, Jekyll, Astro or Eleventy, which store posts as Markdown files.
  • Moving documentation from an HTML help system into a Git repository or a docs platform.
  • Saving articles as notes in Markdown-based apps like Obsidian or Joplin.
  • Preparing text for AI tools and chat apps, where Markdown keeps structure with far fewer characters than HTML.

Tips for converting web pages

  • Convert only the main content (usually the <article> or <main> element) to avoid navigation menus and footers in your Markdown.
  • Make image and link URLs absolute before converting if the Markdown will live somewhere else.
  • If the source HTML is messy, run it through the HTML formatter first; well-structured HTML converts more cleanly.
  • Finally, tidy the result with the Markdown formatter.

To check the result, preview it in the Markdown viewer, or convert it back with Markdown to HTML to compare. Conversion happens entirely in your browser.

Convert HTML to Markdown in Python

The standard library has no HTML to Markdown converter, so the usual choice is the markdownify package, which parses the HTML with Beautiful Soup and writes Markdown. Its defaults surprise people: h1 and h2 come out underlined with = and - characters instead of as # headings, and list items start with *. Pass heading_style="ATX" and bullets="-" to get the style most Markdown files use, which is also what this page produces by default.

# pip install markdownify
from markdownify import markdownify

html = """<h1>Getting Started</h1>
<p>Install the <strong>CLI</strong> and run your <em>first</em> build.</p>
<ul>
  <li>Fast builds</li>
  <li><a href="https://example.com/plugins">Plugin</a> support</li>
</ul>
<pre><code>npm install -g acme-cli</code></pre>"""

markdown = markdownify(html, heading_style="ATX", bullets="-")
print(markdown)

Paste the same HTML above to compare the two results, or turn the Markdown back with Markdown to HTML.

Frequently asked questions

Are HTML tables converted to Markdown?
Yes, into GitHub-style pipe tables. Merged cells and block content such as lists inside cells cannot be represented in Markdown tables, so those parts are simplified.
What happens to CSS classes and inline styles?
They are dropped, because Markdown has no syntax for styling. Only the structure and text formatting, such as headings, bold, italics and links, are kept.
Why do some characters get a backslash?
Characters like #, * and _ have special meaning in Markdown. When they appear in normal text, they are escaped so they display literally instead of creating formatting.
Which heading style should I use?
ATX headings with # are the most common and support all six levels. Setext headings, underlined with = or -, only exist for the first two levels.
Can I convert a whole web page?
Yes, but navigation, sidebars and footers will be converted too. For clean results, paste only the HTML of the main article.

Last updated October 3, 2026

Related tools