<> HTML to Markdown Converter, Clean Markdown From Any HTML
By Shihab Mia ยท Updated 2026-07-29
This HTML to Markdown converter takes any block of HTML and rewrites it as clean Markdown you can drop straight into a README, a static site, or a docs page. It parses your input with the browser DOMParser and walks the document tree, mapping each tag to its Markdown equivalent: headings become "#" prefixes, strong and em become "*bold" and "italic*", anchors become "[text](href)" links, images become "", lists become "-" or "1." items, tables become GitHub Flavored Markdown pipe tables, and code blocks become fenced backticks. Everything runs locally in your browser, so nothing you paste is ever uploaded.
What is the HTML to Markdown Converter?
Markdown and HTML describe the same document in two different ways. HTML is verbose and explicit, wrapping every heading, paragraph, and link in angle-bracket tags. Markdown is a lightweight shorthand where a "#" means a heading and "*word*" means bold. Converting from HTML to Markdown means reading the structure the tags describe and writing the shortest text that reproduces that structure. This tool does exactly that: it does not use regular expressions to hack at your HTML string, it builds a real document object model and walks it node by node.
The parsing step matters more than it looks. When you call new DOMParser().parseFromString(input, "text/html"), the browser applies the same forgiving HTML rules a web page uses, so unclosed tags, stray whitespace, and nested inline elements are all normalized into a clean tree before any conversion happens. The converter then recurses through the body: block-level elements like h1 to h6, p, ul, ol, blockquote, pre, and table each become their own Markdown block separated by a blank line, while inline elements like strong, em, a, code, and img are rendered in place inside the text of their parent block.
Table conversion deserves special mention because it trips up a lot of simple converters. Standard Markdown, known as CommonMark, has no table syntax at all; the pipe-and-dash table format you see on GitHub is a GitHub Flavored Markdown, or GFM, extension. This tool reads each table row, uses the first row as the header, inserts the required "---" separator row, and pads each cell so the output is valid GFM. That makes it a genuine html table to markdown table converter, not just a heading and list converter, which matters if you are pulling pricing tables, comparison charts, or spec sheets out of a web page or a WordPress export.
A few rules keep the rest of the output tidy and portable. Runs of spaces, tabs, and newlines inside text are collapsed to single spaces, because in HTML that whitespace is not significant but in a text file it would create ragged output. Characters that carry meaning in Markdown, such as asterisks, backticks, and square brackets, are escaped in plain text so a literal asterisk in your content does not accidentally turn into italics. Inline code and fenced code blocks are the exception: their contents are copied verbatim so your code is never altered. Lists support simple nesting, indenting child items by two spaces per level, and ordered lists number themselves sequentially.
The result is Markdown that renders identically to your source in any CommonMark or GitHub Flavored Markdown viewer, minus the tags. It is ideal for pulling content out of a CMS or a rich text editor, cleaning up pasted HTML, or migrating a page into a Markdown-based system like a static site generator, an Obsidian vault, or a documentation tool. Because the whole conversion happens client side in plain JavaScript, there is no upload, no size limit imposed by a server, and no waiting on a round trip.
Worth knowing before you migrate a large batch of pages: Markdown flavors are not perfectly interchangeable. GitHub, Obsidian, and most static site generators accept GFM tables and fenced code without complaint, but Notion strips YAML frontmatter on import and renders some nested formatting differently, and plain CommonMark viewers will not render a pipe table at all. If your destination is one of those platforms, check its docs for what it actually supports before assuming the Markdown this tool produces will look identical everywhere.
When to use it
- Migrating articles or pages out of a CMS or WordPress export and into a Markdown-based static site like Astro, Hugo, or Jekyll.
- Cleaning up HTML copied from a rich text editor or email into portable Markdown for a README or docs page.
- Converting the HTML output of an API or scraper into Markdown for storage in Git or a knowledge base.
- Turning a styled web snippet into plain Markdown so it renders consistently on GitHub, GitLab, or a wiki.
- Converting an HTML pricing table, spec sheet, or comparison chart into a GitHub Flavored Markdown table.
- Preparing content for a Markdown-driven chat app, note app, or Obsidian vault by stripping HTML down to its structural essentials.
How to use the HTML to Markdown Converter
- Paste or type your HTML into the input box at the top.
- Choose whether unordered lists use "-" or "*" with the bullet-style checkbox.
- Read the converted Markdown in the output box, which updates live as you edit the input.
- Check any tables in the output render correctly as pipe tables if your source HTML included a table.
- Click the Copy button to copy the Markdown to your clipboard.
- Paste the Markdown into your README, static site, wiki, or docs tool.
Formula & method
Worked examples
A heading, a paragraph with a bold word and a link, and a two-item list.
- Input: <h1>Welcome</h1><p>This is a <strong>bold</strong> word and a <a href="https://toolnimba.com">link</a>.</p><ul><li>First item</li><li>Second item</li></ul>
- The h1 becomes "# Welcome" as its own block.
- The p becomes one line, with <strong> rendered as **bold** and the anchor rendered as [link](https://toolnimba.com).
- Each <li> in the <ul> becomes a "- " line.
Result: # Welcome This is a **bold** word and a [link](https://toolnimba.com). - First item - Second item
A blockquote and a fenced code block.
- Input: <blockquote><p>Stay curious.</p></blockquote><pre><code>npm install</code></pre>
- The blockquote renders its inner paragraph, then prefixes every line with "> ".
- The pre with an inner code element becomes a fenced block wrapped in triple backticks.
- The verbatim text "npm install" is preserved exactly, with no escaping.
Result: > Stay curious. ``` npm install ```
A two-column HTML pricing table pulled from a web page.
- Input: <table><tr><th>Plan</th><th>Price</th></tr><tr><td>Free</td><td>$0</td></tr><tr><td>Pro</td><td>$9</td></tr></table>
- The first row becomes the header row of a GFM pipe table.
- A "---" separator row is inserted directly under the header, one "---" per column.
- Each remaining row becomes a "|" delimited data row, aligned to the same column count.
Result: | Plan | Price | | --- | --- | | Free | $0 | | Pro | $9 |
How each HTML element maps to Markdown
| HTML element | Markdown output | Example |
|---|---|---|
| h1 to h6 | 1 to 6 "#" then a space | <h2>Title</h2> becomes ## Title |
| strong, b | **text** | <b>hi</b> becomes **hi** |
| em, i | *text* | <i>hi</i> becomes *hi* |
| a[href] | [text](href) | <a href="/x">go</a> becomes [go](/x) |
| img |  | <img alt="cat" src="c.png"> becomes  |
| ul > li | - item | each list item on its own line |
| ol > li | 1. item | items numbered in sequence |
| table | GFM pipe table | header row plus a "---" separator row |
| code (inline) | `text` | <code>x</code> becomes `x` |
| pre, pre > code | fenced code block | wrapped in triple backticks |
| blockquote | > line | every line gets a "> " prefix |
| hr | --- | a horizontal rule |
| br | line break | two spaces then a newline |
Markdown characters escaped in plain text (but not inside code)
| Character | Why it is escaped |
|---|---|
| \ | The escape character itself, so it stays literal. |
| ` | Starts inline code if left unescaped. |
| * | Starts bold or italic if left unescaped. |
| _ | Starts emphasis in many Markdown flavors. |
| [ and ] | Start a link or reference if left unescaped. |
| | | Would break a table column if a cell contains a literal pipe. |
Where the output Markdown will and will not render as expected
| Destination | Tables | Fenced code | Notes |
|---|---|---|---|
| GitHub, GitLab | Renders correctly | Renders correctly | Both are GFM, the format this tool targets. |
| Static site generators (Astro, Hugo, Jekyll) | Usually renders | Renders correctly | Most Markdown processors used by these tools support GFM tables. |
| Obsidian | Renders correctly | Renders correctly | Obsidian is CommonMark based with GFM tables and task lists. |
| Notion (paste into a page) | Renders as an inline table | Renders correctly | Importing a .md file instead can turn a table into a database with property columns. |
| Plain CommonMark viewer | Shown as literal text | Renders correctly | Tables are a GFM extension, not part of core CommonMark. |
Common mistakes to avoid
- Expecting inline CSS and classes to survive. Markdown has no concept of colors, fonts, or class names. Style attributes, class attributes, and span wrappers are dropped, and only the structural meaning of the HTML is kept. If a look depends on CSS, that look will not carry over to Markdown.
- Pasting a full page with head, scripts, and styles. The converter walks the document body, so navigation, script tags, and style blocks are ignored rather than turned into text. Paste the content region you actually want, not an entire saved web page, for the cleanest result.
- Assuming every Markdown flavor renders GFM tables. Pipe tables are a GitHub Flavored Markdown extension, not part of the core CommonMark spec. This tool outputs GFM tables because that is what GitHub, GitLab, most static site generators, and Obsidian expect, but a strict CommonMark-only renderer will show the pipes and dashes as literal text.
- Losing whitespace inside code you meant to keep. Only inline code and fenced pre blocks preserve exact spacing. Whitespace in ordinary paragraphs is collapsed to single spaces on purpose, so if indentation matters, wrap that content in a pre or code element before converting.
- Expecting merged or nested table cells to convert cleanly. GFM pipe tables have no concept of colspan, rowspan, or a cell containing its own nested table. Complex HTML tables with merged cells are flattened as best as possible, but visually complex tables usually need a manual pass after conversion.
- Importing the result into Notion and expecting frontmatter or exact formatting to survive. Notion strips YAML frontmatter on import with a warning, and it can turn an imported table into a database rather than an inline table. If your destination is Notion, paste the Markdown into an existing page instead of importing it as a file, and re-check tables afterward.
Glossary
- Markdown
- A lightweight plain-text formatting syntax where symbols like "#" and "**" stand in for HTML tags, designed to be readable as-is and to convert to HTML.
- HTML
- HyperText Markup Language, the tag-based language browsers use to describe the structure and content of a web page.
- DOMParser
- A built-in browser API that parses an HTML or XML string into a document object model tree that code can walk and inspect.
- CommonMark
- The standardized core Markdown spec that most parsers agree on, covering headings, emphasis, lists, links, and code, but not tables.
- GFM (GitHub Flavored Markdown)
- An extension of CommonMark used by GitHub that adds pipe tables, task lists, and strikethrough on top of the core spec.
- Block element
- An element such as a heading, paragraph, list, table, or blockquote that forms its own line or region, separated from other blocks by a blank line in Markdown.
- Inline element
- An element such as strong, em, a, or code that lives inside the text of a block and formats a span of characters.
- Fenced code block
- A block of code wrapped in triple backticks in Markdown, which preserves spacing and disables all other formatting inside it.
Frequently asked questions
How do I convert HTML to Markdown?
Paste your HTML into the input box and the tool instantly outputs the Markdown equivalent below it. It parses the HTML with the browser DOMParser and maps each tag to Markdown: headings become "#" prefixes, strong and em become bold and italic, anchors become links, tables become GFM pipe tables, and lists become "-" or numbered items. Then click Copy to grab the result.
Is this HTML to Markdown converter free?
Yes, it is completely free with no sign-up, no watermark, and no usage limit. The entire conversion runs in your browser using JavaScript, so there is no server cost and nothing to pay for.
Is my HTML sent to a server?
No. All parsing and conversion happen locally in your browser. Your HTML never leaves your device, which makes the tool safe to use for private or internal content.
Which HTML tags does it support?
It handles h1 to h6, p, strong and b, em and i, a, img, ul and ol lists, table, inline code, pre and pre code fenced blocks, blockquote, hr, and br. Unknown or purely stylistic tags like span and div are unwrapped so their inner content is kept.
Does it convert HTML tables to Markdown?
Yes. Each table becomes a GitHub Flavored Markdown pipe table: the first row becomes the header, a "---" separator row is inserted underneath, and remaining rows become data rows. Note that GFM tables do not support merged or nested cells, and a strict CommonMark viewer that does not support GFM will not render pipe tables at all.
Why did my inline styles and classes disappear?
Markdown only expresses structure, not styling. Class names, inline CSS, colors, and fonts have no Markdown representation, so they are dropped and only the underlying heading, list, link, and emphasis structure is kept.
Does it preserve my code snippets exactly?
Yes. Content inside inline code and pre or code blocks is copied verbatim, with no whitespace collapsing and no character escaping, so your code appears in the Markdown exactly as it was in the HTML.
Can I choose the bullet style for lists?
Yes. A checkbox lets you switch unordered list markers between "-" and "*", both of which are valid Markdown. Ordered lists always use sequential "1." style numbering.
Will the output work in Obsidian or Notion?
Obsidian works well because it is CommonMark based with full GFM table support, so pasted output renders as expected. Notion is less predictable: pasting into an existing page usually renders a table inline, but importing a .md file can turn a table into a database, and Notion strips any YAML frontmatter on import.
What is the difference between HTML to Markdown and Markdown to HTML?
This tool goes one direction, HTML into Markdown, for pulling structure out of rich content. The reverse direction, Markdown to HTML, is a separate conversion for rendering Markdown files as web pages, and ToolNimba offers that as its own dedicated Markdown to HTML converter.