HTML to Markdown — Convert HTML to Markdown Online

Convert HTML to clean Markdown instantly. Paste HTML code and get well-formatted Markdown output. Supports headings, bold, italic, links, images, lists, code blocks, blockquotes, tables, and paragraphs. Fully client-side — no data is sent anywhere.

Convert HTML to Markdown

How do you convert HTML to Markdown? Converting HTML to Markdown means replacing each element with its plain-text equivalent: <h2> becomes ##, <strong> becomes **bold**, <a href> becomes [text](url) and <li> becomes a dash. This tool does it by parsing your HTML into a real DOM tree with the browser's DOMParser, then walking that tree and emitting the matching Markdown for every node.

How to Use the HTML to Markdown Converter

  1. Paste the HTML you want to convert — A fragment is fine — you do not need a full document, and a stray unclosed tag will not stop the conversion because the parser repairs the tree the same way a browser does. Use Sample HTML to see a worked example covering headings, a list, a code block, a quote and a table.
  2. Read the Markdown as it appears — Output regenerates on every keystroke, so you can delete a wrapper and watch the result change. The Convert button re-runs the same conversion and is only needed if you paste with the mouse and the input event does not fire.
  3. Trim the page furniture first — For a full page, copy just the <main> or <article> subtree from your browser's element inspector. Navigation, footers and wrapper <div>s are unwrapped rather than removed, so their link text ends up as loose lines in the Markdown.
  4. Check the constructs Markdown cannot express — Colspans, nested lists, inline styles and <u> have no clean Markdown form. The table further down lists exactly what each tag becomes and what gets dropped, so you know where to look before pasting the result into a repository.
  5. Copy the resultCopy puts the output on your clipboard for a README, a docs page, or a Jekyll, Hugo or Docusaurus source file. The input is also mirrored into the page URL, so the tab can be bookmarked and reopened with the same HTML in place.

How the Conversion Works

The converter does not use regular expressions on your markup. It hands the text to the browser's built-in DOMParser with the text/html type, which runs the same parsing algorithm the browser uses for a real page: unclosed tags are closed, misnested elements are corrected, and entities such as &amp; are decoded. The result is a document tree rather than a string, which is why a messy CMS export or a half-copied fragment still converts instead of failing.

That parsed document is inert. It has no browsing context, so scripts never run, stylesheets are never fetched and image src URLs are never requested — the markup is inspected, not executed. From there the tool walks the tree depth-first from <body>. Each node converts its children first, then wraps that text according to its own tag, so nesting composes naturally: a <strong> inside an <li> inside a <ul> emerges as - **text** without any special case.

A final cleanup pass collapses runs of three or more blank lines down to one, trims leading and trailing whitespace and removes trailing spaces at the end of lines. Block elements deliberately over-emit blank lines during the walk so that this pass can normalise them, which is how you get consistent spacing from inconsistent input.

What each tag becomes

HTMLMarkdownNotes
<h1><h6># to ######ATX style only, never the underlined Setext form
<strong>, <b>**bold**Both map to the same output
<em>, <i>*italic*Both map to the same output
<u>__text__Markdown has no underline; most renderers show this as bold
<s>, <del>~~strikethrough~~A GitHub-flavoured extension, not in original Markdown
<code>Backtick spanEmitted as bare text when it sits inside a <pre>
<pre><code>Fenced blockA language-js class becomes the fence's language tag
<a href>[text](url)An empty href or # yields plain text; title is dropped
<img>![alt](src)Width, height and title are dropped
<br>Two spaces, then a newlineThe Markdown hard line break
<hr>---Always three hyphens
<blockquote>> on every lineApplied after the inner content is converted
<ul>, <ol>, <li>- or 1.Ordered numbers come from the item's position among its siblings
<table>Pipe tableThe first row with cells becomes the header row
<script>, <style>, <noscript>Removed entirelyTheir text never reaches the output
Any other tagIts children only<span>, <figure>, <div> and friends are unwrapped, text kept

What Markdown Cannot Carry Across

Markdown is a much smaller language than HTML, so a lossless conversion is impossible by definition. Knowing in advance which parts will not survive turns a surprise into a two-minute edit.

  • Nested lists flatten. A sub-list inside a list item comes out at the same level as its parent, because the cleanup pass strips leading whitespace and Markdown expresses nesting purely through indentation. Re-indent the child items by two or four spaces afterwards.
  • Indented code loses its indentation. The same whitespace trim applies inside fenced blocks, so a converted code sample keeps its line breaks but not its leading spaces. For code that matters, paste it back from the original rather than from the output.
  • Table alignment and merged cells are not carried over. Every column separator is written as plain ---, so align="right" or a CSS text alignment is lost. A colspan or rowspan is flattened into a single cell, which leaves rows with unequal column counts — those need fixing by hand.
  • Attributes and styling disappear. Classes, ids, inline styles, title text, target="_blank", image dimensions and data attributes all vanish, because Markdown has nowhere to put them. Keep them by leaving that fragment as raw HTML, which every Markdown renderer passes through.
  • Special characters are not escaped. A literal asterisk, underscore or leading hash in your text is emitted as-is and may be read as formatting when the Markdown is rendered. Scan the output for stray * and _ in prose and backslash-escape them.

Markdown is a superset of HTML in almost every renderer, so anything the converter cannot express can simply stay as HTML in the output file. Mixing a raw <table> into an otherwise Markdown document is normal practice, and usually a better answer than fighting the pipe syntax for one complicated table.

Frequently Asked Questions

Headings h1 to h6, paragraphs, bold and italic, underline and strikethrough, links, images, ordered and unordered lists, inline code, fenced code blocks, blockquotes, tables, horizontal rules and line breaks. Every other tag is unwrapped — the element disappears but its text is kept — except <script>, <style> and <noscript>, which are dropped along with their contents.

Only the grid. Rows and cells become a Markdown pipe table and the first row with cells is used as the header, but column alignment is not carried over: every separator is written as plain ---, so an align attribute or a CSS text alignment is lost. Merged cells are flattened to one cell each, which leaves rows with different column counts and needs a manual fix.

You can paste a whole document, but the result will include the navigation and footer text. Copy just the content subtree instead — in the element inspector, right-click the <main> or <article> node and choose Copy outer HTML. Anything in <head>, including the page title, is ignored because only the body is walked.

No. Parsing and conversion both happen in your tab using the browser's own DOMParser, and the parsed document is inert, so scripts in the pasted markup never execute and images are never fetched. One caveat: your input is also written into the page URL so the tab can be bookmarked, which means you should clear the box before sharing that link if the HTML contains anything private.

Markdown expresses list nesting through leading indentation, and the final cleanup pass strips leading whitespace from every line to normalise spacing from messy input. Sub-list items therefore land at the top level. Re-indent them by two or four spaces after pasting, or convert each list separately and assemble them by hand.

Use this tool when the source of truth needs to become plain text a human edits and Git can diff: moving CMS posts into a static site, turning generated docs into a README, or cleaning a rich-text paste. Use the Markdown to HTML converter for the opposite trip, when Markdown you already maintain has to be published as markup.

Yes, with one thing to check. Headings, links, images, lists, quotes, rules and fenced code are core Markdown and work everywhere. Tables and ~~strikethrough~~ are GitHub-flavoured extensions — universal on GitHub, GitLab, Obsidian and most static site generators, but not guaranteed by a strict CommonMark renderer. Fenced code language tags are also an extension, though an equally widespread one.

Pipe characters inside table cells are escaped as \| so they do not split a column — that backslash is intentional. Broken lines usually come from the opposite problem: an asterisk, underscore or leading # in ordinary prose is passed through unescaped and gets read as formatting when rendered. Search the output for those characters and escape them with a backslash.

Use Cases

Migrating a Blog Off a CMS

Export posts from WordPress or Drupal, drop each post's body HTML in here, and save the output as the Markdown source file a Jekyll, Hugo or Docusaurus build expects — leaving the front matter to be added on top.

Cleaning a Rich-Text Paste

Text copied out of Word, Google Docs or an email client arrives wrapped in dozens of <span> tags and inline styles. Round-tripping it through Markdown discards all of that and leaves the structure you actually wanted.

Turning Generated Docs into a README

Take the HTML a documentation generator or API explorer produced and convert the relevant section into the Markdown a repository README or wiki page needs, keeping the code fences and their language tags intact.

Making Content Reviewable in Git

Convert a page that currently lives as HTML so it can sit in a repository where a diff is readable line by line, instead of showing a wall of changed markup every time someone edits one sentence.

Filing Content into a Notes App

Grab the article body from a page you want to keep and convert it before pasting into Obsidian, Logseq or a wiki, so the note holds readable structure rather than a screenshot or an unformatted wall of text.