Free HTML to Markdown converter
HTML to Markdown, losses declared
Paste HTML — or copy a chunk of a rendered web page and paste that, which brings the real markup with it — and this free page converts it to Markdown with no account and no upload. Because HTML says more than Markdown can, one control decides what happens to the rest: drop it, keep it as raw HTML, or approximate it. Whatever is chosen, the page lists exactly what changed, so a nested table or a styled span never disappears silently. Up to 3 MB per conversion.
- 100% free
- No signup
- Up to 3 MB
- Reads pasted rich text
- Reports what changed
The Markdown lands here. Nothing is sent anywhere; the page is parsed by this tab’s own HTML parser.
How to convert HTML to Markdown
Paste, choose how lossy you are willing to be, and read the report.
Bring the HTML over
Select part of a rendered web page, copy it, and press Ctrl+V (⌘V) here — the clipboard carries a text/html flavour alongside the plain text, and this page reads that one, so you get the real markup rather than the stripped words. Pasting source directly, opening a .html file and dropping one on the box all work too.
Decide what happens to the untranslatable parts
The first control is the important one. Approximate maps a nested table onto a bullet list and a bold span onto asterisks; Keep leaves those fragments as raw HTML inside the Markdown, with the class and data attributes stripped; Drop discards the wrapper and keeps only the words. Set bullets, link style, tables and images underneath.
Read the loss report before you commit
Under the output is a line naming everything that did not survive — how many span wrappers were removed, how many tables were flattened, how many links had an unusable destination. Switch to “Rendered back” to see the Markdown re-rendered, which is the fastest way to spot a structure that quietly collapsed, then Copy or Save .md.
Technical specifications
| How the HTML is parsed | The browser's own DOMParser, so unclosed tags, implied tbody and odd attribute quoting resolve exactly as they do when the page is displayed |
|---|---|
| Clipboard support | Reads the text/html flavour of a copied selection and strips the wrapper a browser adds — the charset meta and the StartFragment comment |
| Elements mapped directly | h1-h6, p, ul, ol, li, blockquote, pre, code, hr, table, a, img, strong, em, del, br and their aliases b, i, s, strike, cite, samp |
| Elements with no equivalent | Nested and merged-cell tables, div and span wrappers, u, sub, sup, mark, kbd, abbr, details and definition lists — each follows the drop / keep / approximate setting |
| Attributes kept in raw HTML | href, src, alt, title, colspan, rowspan, align, style, start, type — class, id, data-* and event handlers are removed |
| Table output | GFM pipe tables with per-column alignment read from the align attribute or a text-align style |
| Link output | Inline destinations, or numbered reference definitions collected at the end of the document |
| Maximum input | 3 MB of HTML — a 90 KB article converts in about 25 ms, and the loss report counts every construct that changed |
| Processing location | Your browser — the page you paste is never uploaded |
| Price | Free, no signup, no limit on conversions |
Frequently asked questions
Why did my nested table become plain text?
Because a Markdown pipe table has no way to hold another table inside a cell — the syntax is one line per row, so anything containing a line break or a block element cannot go in. The same limit catches colspan, rowspan, a list inside a cell and a heading inside a cell, and this converter checks for all five before it commits to a pipe table. When one of them appears you get whatever the policy control says: a bullet list of “**Header:** value” pairs under Approximate, the original <table> element under Keep, or the cell text separated by em dashes under Drop.
What exactly does “keep the raw HTML” keep?
The element and its structure, minus every attribute that is not load-bearing: href, src, alt, title, colspan, rowspan, align, style, start and type survive, and class, id, data-*, aria-* and inline event handlers are stripped. That distinction is what makes the option usable — pasting a fragment of a modern site with Keep on would otherwise drop 400 characters of utility classes into your Markdown for every div. Raw HTML inside Markdown is legal and GitHub renders a filtered subset of it, so kept fragments usually still display where the file ends up.
I pasted from Google Docs or Word and lost most of the formatting — why?
Because those editors express formatting as inline styles on spans rather than as semantic elements: a heading is often a span with font-size:20pt, not an h2, and bold is font-weight:700 on a span rather than a strong. This converter reads font-weight, font-style and text-decoration and maps them to bold, italic and strikethrough under the Approximate policy, which recovers the emphasis, but a size-only heading has no equivalent it can trust and stays a paragraph. Pasting from a rendered web page usually goes much better, because browsers ship real h1-h6 and strong elements.
Why are there backslashes in front of characters in my output?
They stop text from being re-read as syntax: a literal asterisk, backtick, square bracket or angle bracket in the source page would otherwise turn into emphasis, code or a broken link when the Markdown is rendered, so each one is escaped. Line-leading characters get the same treatment — a paragraph that happens to start with “1. ” or “- ” would become a list item without it. Underscores are deliberately left alone, because inside a word they never open emphasis and escaping them would mangle every snake_case identifier on the page.
Can I give it a URL instead of pasting the HTML?
No, and it is not an oversight — this page has no server, so there is nothing that could fetch a URL on your behalf, and a browser cannot read another site's HTML directly because of the same-origin policy. The two routes that do work are copying the rendered selection, which brings the markup with it through the clipboard, and saving the page from your browser and opening the .html file here.
What happens to <u>, <sub>, <mark> and <kbd>?
None of those four exist in Markdown, so they follow the policy control like everything else. Under Approximate, mark becomes bold and kbd becomes inline code, while u, sub and sup keep their text and lose the presentation; under Keep, all four stay as their original tags; under Drop, each becomes plain text. Underline is the honest casualty here: Markdown has no underline at all, and mapping it to emphasis would be a lie about what the source said.
Why did all my <div> structure disappear?
Because a div carries no meaning that Markdown can represent — it is layout, and layout is exactly what Markdown throws away. Divs, sections, articles, headers, footers and navs are treated as transparent: their children are converted and the wrapper is discarded, with a count of how many were removed shown under the output. If a div's only content was inline text, it becomes a paragraph so the text does not run into its neighbours.
About the lossy direction
Markdown to HTML is a translation; HTML to Markdown is a summary. Markdown has roughly fifteen block constructs and eight inline ones, and HTML has well over a hundred elements plus arbitrary nesting, attributes and CSS — so the mapping only exists in one direction. Anything on the HTML side without a Markdown production has three possible fates and no fourth: throw the construct away and keep the words, leave the original markup embedded in the Markdown, or substitute the nearest thing Markdown does have and accept that it says something slightly different. Most converters pick one of those silently. This one asks, and then tells you how often it had to make the choice.
Where the input comes from changes the answer too. When you copy a selection from a rendered page, the clipboard carries two flavours: text/plain, which is the visible words, and text/html, which is the markup with the browser’s own bookkeeping wrapped around it — a charset meta and a pair of StartFragment comments. Reading the second is what lets a paste keep its headings, links and tables. It also means the quality of the result depends on how the source page was built: a site using real h2 and strong elements converts almost perfectly, while a document exported from a word processor arrives as spans carrying font-weight:700 and font-size:20pt, where emphasis can be recovered but heading levels genuinely cannot.
A last practical note about round trips: HTML → Markdown → HTML is not the identity function, and it is not supposed to be. Wrapper divs, class names, ids and inline styles are gone for good, which is usually the point of the exercise — you wanted the content, not the layout. If you need the result to render the same way it did on the source page, keep the awkward fragments as raw HTML and check the output through the Markdown to HTML converter, or read it in the Markdown preview first. Editing what came back is easier in the Markdown editor, where the source and the rendering sit next to each other.
What happens to the page you paste
Parsing and conversion both run inside this tab, so an internal wiki page or a customer email keeps to your machine — nothing is uploaded and nothing is logged. The clipboard is read only while you are pressing paste, and the result is discarded when you close the tab.