HTML to Markdown Converter, Tables Included
Convert HTML to clean, readable Markdown. Headings, lists, links, images, fenced code blocks, tables and strikethrough are supported, powered by the Turndown library.
What this HTML to Markdown converter does
The converter parses your HTML in the browser and rewrites it as Markdown with Turndown 7.2 and the turndown-plugin-gfm 1.0.2 extension. Headings, paragraphs, emphasis, links, images, lists, blockquotes and code blocks map to standard Markdown; tables, strikethrough and task lists use GitHub Flavored Markdown (GFM) syntax. <script>, <style>, <noscript>, <template> and <title> elements are removed together with their content.
HTML can express far more than Markdown can. There is no Markdown for colours, classes, underlining, column spans or most layout, so the converter keeps the text of such elements and drops the markup. That trade-off is the point: you get plain, portable text with its structure intact.
How to use the converter
- Paste HTML into the HTML Input pane — a fragment or a whole page — or load it with File or URL. A URL only loads when the server allows cross-origin requests, which most websites do not; saving the page and using File is usually easier.
- Click Convert. Unlike the Markdown to HTML page there is no live update, so convert again after editing or loading a file.
- Copy the result, Download it as
converted.md, or Clear both panes.
Output style
The converter is set up with ATX headings (## Heading), fenced code blocks and - as the bullet marker. The other choices are Turndown’s defaults:
| HTML | Markdown output |
|---|---|
<h2> | ## Heading |
<strong> / <b>, <em> / <i> | **bold**, _italic_ |
<ul><li> | - item (marker plus three spaces); nested lists indented by four |
<ol><li> | 1. item |
<pre><code class="language-python"> | A ```python fenced block |
<div class="highlight highlight-source-js"><pre> | A ```js fenced block (GitHub’s highlighted code) |
<del>, <s>, <strike> | ~text~ (one tilde, which GFM accepts) |
Checkbox inside <li> | - [x] done |
| Table whose first row is a header | GFM pipe table, with --: for align="right" |
<a href title>, <img alt> | [text](url "title"),  |
<br>, <hr>, <blockquote> | Two trailing spaces and a newline, * * *, > quote |
<span>, <u>, <mark>, <sup>, <div> | Text only; tags dropped |
Comments, <iframe> | Removed |
Characters that would otherwise be read as Markdown are escaped with a backslash: 1. Not a list becomes 1\. Not a list, and * and _ in text become \* and \_. Entities are decoded, so © becomes © and becomes a non-breaking space character.
Example
<h1>Install</h1>
<p>Run <code>npm i</code>, then <strong>restart</strong> the <em>server</em>.</p>
<ul><li>One</li><li>Two<ul><li>Nested</li></ul></li></ul>
converts to:
# Install
Run `npm i`, then **restart** the _server_.
- One
- Two
- Nested
Converting an HTML table to a Markdown table
Paste the table on its own or inside a whole page: every table whose first row is a header becomes a GitHub-flavoured Markdown (GFM) pipe table, the format GitHub, GitLab, most static site generators and many note-taking apps render. Links, bold text and code inside cells are converted too, and align="right" becomes --: in the separator row.
<table>
<thead><tr><th>Format</th><th>Typical use</th><th align="right">Size</th></tr></thead>
<tbody>
<tr><td><strong>JSON</strong></td><td>APIs and config</td><td align="right">small</td></tr>
<tr><td>CSV</td><td>Spreadsheets and exports</td><td align="right">smaller</td></tr>
</tbody>
</table>
converts to:
| Format | Typical use | Size |
| --- | --- | --: |
| **JSON** | APIs and config | small |
| CSV | Spreadsheets and exports | smaller |
The header row is required because a Markdown table cannot exist without one. If your table has none, make the first row <th> cells before converting, or keep the table as HTML, which most Markdown renderers display as it is. Merged cells (colspan and rowspan) have no Markdown equivalent either, so such a table is best kept as HTML. A pipe character (|) inside a cell is written as \|, so it stays in its cell instead of starting a new column. To go the other way, from spreadsheet cells to HTML, use the HTML table generator.
Common problems and fixes
| Problem | Cause | Fix |
|---|---|---|
| A table stays as HTML | Pipe tables need a header row. Only tables whose first row is in <thead> or made of <th> cells are converted. | Turn the first row into <th> cells, or keep the HTML table — most Markdown renderers display it. |
| A pipe table is broken across lines | A cell contains <br>, a paragraph or a | character, which a one-line table row cannot hold. | Simplify those cells first, or keep that table as HTML. |
| Code lost its formatting | A <pre> without an inner <code> element is output as plain text. | Wrap the content in <code> before converting. |
Text like <tag> disappears when rendered | Escaped <tag> is decoded to <tag>, which Markdown renderers treat as raw HTML. | Put it in backticks: `<tag>`. |
| Navigation and footer text in the output | The whole page was pasted, and Turndown converts all visible content. | Copy only the article: in your browser’s developer tools, right-click the element and copy its outer HTML. |
Frequently asked questions
Why do list items have three spaces after the dash?
That is Turndown’s default list layout, which lines up the item text with a four-character indent. Markdown renderers treat - item and - item the same; a formatter such as Prettier can normalise the spacing.
Are class names, IDs and inline styles kept?
No. Markdown has no syntax for attributes, so only href, src, alt, title the language-* class on code blocks, a list’s start number and table column alignment carry over. Tables without a header row are the exception: they are kept as HTML with their attributes.
Can I use it to move a blog from WordPress to a static site generator?
Yes, page by page. Paste the post’s HTML, convert, and save the result as a .md file. Shortcodes, embeds and custom blocks will need manual attention because they have no Markdown form.
Is the pasted HTML executed?
No. It is parsed into an inert document that is never added to this page, so scripts and event handlers such as onerror do not run. Scripts and styles are removed from the result as well.
Is my HTML uploaded?
No. Turndown runs in your browser. The page loads the library from the jsDelivr CDN, but the HTML you paste is not sent anywhere.