HTML to Markdown Converter

Convert HTML to Markdown instantly in your browser. Preserves headings, bold, italic, links, images, code blocks with language, GFM tables, and nested lists. Free, no upload required.

  • Runs in your browser
  • Your data never leaves your browser
  • Free · No Sign-Up
Load the sample with headings, links, code, lists, a table and a quotation. It replaces the current HTML and converts immediately.
Clear both fields, the warning and copy feedback, and cancel pending conversion. Ctrl/⌘+L also clears the tool when focus is inside it.
Save the complete Markdown output as a UTF-8 file named output.md. Empty output is not downloaded.
Copy the complete Markdown output as text. Empty output is not copied.
Paste or type HTML. Conversion runs 300 ms after you stop typing. Input over 1,048,576 characters shows a warning and still converts.
Markdown Output Headings use ATX syntax and code blocks keep their language. A first row in THEAD produces a GFM table; a later TH row alone stays HTML. Check the Markdown before publishing.

Your converted Markdown will appear here.

Examples, details and FAQ Worked examples, how it compares with other tools, and answers to common questions.

Conversion Reference

HTMLMarkdown
<h1>Title</h1># Title
<strong>text</strong>**text**
<em>text</em>*text*
<a href=“url”>label</a>[label](url)
<img src=“url” alt=“alt”>![alt](url)
<code class=“language-js”> inside <pre>```js fence
<table>GFM pipe table
<blockquote>> quote
<hr>* * *
<br>two spaces and a line break
<ol start=“3”>3., 4. …

Examples

The outputs below come from the tool’s converter: Turndown 7.2.4 with the tables rule of turndown-plugin-gfm 1.0.2 and the options listed under “Output Style”.

A heading, inline code and a link with a title. Input:

<h2>Install</h2><p>Run <code>npm i turndown</code> and see the <a href="https://github.com/mixmark-io/turndown" title="repo">README</a>.</p>

Output:

## Install

Run `npm i turndown` and see the [README](https://github.com/mixmark-io/turndown "repo").

The title attribute is kept as a Markdown link title in quotes.

A table cell with a pipe and a line break. Input:

<table><thead><tr><th>Option</th><th>Values</th></tr></thead><tbody><tr><td><code>--format</code></td><td>json | yaml<br>default: json</td></tr></tbody></table>

Output:

| Option | Values |
| --- | --- |
| `--format` | json \| yaml<br>default: json |

GFM ends a cell at every unescaped |, and a table row cannot span two lines (GFM spec, Tables extension). The converter therefore writes \| and keeps the line break as <br>, so the row still has two cells.

A nested list and an ordered list that starts at 3. Input <ul><li>Step one</li><li>Step two<ul><li>Sub step</li></ul></li></ul><ol start="3"><li>Third</li><li>Fourth</li></ol> gives:

-   Step one
-   Step two
    -   Sub step

3.  Third
4.  Fourth

Output Style

  • Headings use # (ATX), bullets use - followed by three spaces, emphasis uses * and strong uses **.
  • A <pre><code class=“language-x”> block becomes a ```x fence. The language comes only from a language- class on the inner <code>; a class on <pre> or a data-lang attribute gives a fence with no language. A <pre> without an inner <code> is not fenced: its text is copied with its line breaks, so wrap it in a fence by hand.
  • Characters that would start Markdown syntax in plain text are escaped: 5 * 3 becomes 5 \* 3, _a_ becomes \_a\_.
  • Whitespace inside paragraphs is collapsed the way a browser renders it.

Limits

  • Strikethrough (<del>, <s>), highlight (<mark>) and task-list checkboxes are not converted; only their text remains.
  • colspan and rowspan are ignored, because GFM tables have no merged cells. A header cell with colspan=“2” becomes one header column above a two-column body, so fix the header by hand.
  • The text inside <script>, <style> and <title> is not removed. Paste only the part of the page you need.
  • Input over 1 MB (1,048,576 characters) shows “Input is very large — conversion may be slow.” The conversion still runs in the page.
  • An <img> without a src attribute is dropped without a trace. Pages that load images lazily often keep the address in data-src until the image scrolls into view; copy the HTML after the images have loaded, or rename the attribute first.
  • Relative links and image paths are copied as written. They resolve against the page where the Markdown is published, not the page you copied from.

To check the result, paste it into Markdown Preview; it shows raw HTML as text, so a <br> in a table cell or a table kept as HTML appears there as tags. To turn Markdown into a Word file, use Markdown to Word.

Common Use Cases

  • CMS migration: Export WordPress or Drupal content as HTML, then convert it to Markdown for a static site generator like Hugo or Astro.
  • README preparation: Scrape a web page and clean it up as Markdown for a GitHub README or documentation site.
  • LLM input: Convert a web page to Markdown to reduce token count and noise before feeding it to a language model.
  • Note-taking: Convert email HTML or rich-text snippets to clean Markdown for Obsidian, Notion, or similar tools.

FAQ

What HTML elements are supported?

All common HTML elements: h1–h6, p, strong/b, em/i, a, img, code, pre+code (with language class), ul, ol, li, blockquote, hr, table (GFM format), and br. Unknown elements, including del, s, mark and form inputs, fall back to their text content.

How are code blocks handled?

Inline <code> becomes backtick-delimited code. A <pre><code class="language-javascript"> block becomes a fenced code block with the language tag preserved: ```javascript. The language is read only from a language-* class on the <code> element; if there is none, a plain ``` fence is used.

Are GFM tables supported?

Yes, when the first row is inside thead or all of its cells are th. Such tables become GitHub Flavored Markdown (GFM) pipe tables with a separator row; a | inside a cell is written as \| and a <br> inside a cell stays <br>. Any other table is copied as HTML, because a GFM table needs a header row.

What happens with invalid or incomplete HTML?

The browser's built-in HTML parser is used for parsing, so it applies the same tolerance as any browser. Malformed HTML is corrected automatically where possible, and conversion proceeds on the resulting DOM, so the result can differ from what you expect: an unclosed <b>, for example, also makes the next paragraph bold.

Can I convert a full HTML page?

Yes, but remove what you do not want first. The converter has no rule that drops <script>, <style> or <title>, so their text appears in the Markdown output. Copy the article element from DevTools (right-click, Copy outerHTML) instead of the whole page.

Is my HTML sent to a server?

No. The page converts the HTML in your browser with the Turndown library and does not send it anywhere or save it in browser storage. The page's analytics record only a usage event (the tool name and the action convert) after you edit the input and move the focus out of it, or click Example, without any of the HTML or Markdown.