Toolvore

HTML to Markdown

Convert HTML markup into clean Markdown.

This tool runs entirely in your browser. Your data is never uploaded, never stored, and never leaves your device.

Strips HTML back down to Markdown, keeping headings, links, images, lists, blockquotes, code blocks and tables while dropping the tags, classes and inline styles that have no Markdown equivalent.

How to use it

  1. 1Paste your HTML — a fragment or a whole page body — into the HTML box. It takes markup, not a URL; nothing is fetched for you.
  2. 2The Markdown panel appears underneath as soon as there is something to show.
  3. 3Copy the Markdown into your README, CMS or static-site source.

Example

Input
<table><tr><th>Tool</th><th>Docs</th></tr><tr><td>curl</td><td><a href="https://curl.se">site</a></td></tr></table>
Output
| Tool | Docs | | --- | --- | | curl | site |

Look closely at that output: the link inside the cell has gone. Table cells are read as plain text, so a link, a bold run or inline code inside one is flattened to its characters — everywhere else in the document those all survive, it is cells specifically. The first row becomes the header whether or not it uses th, and there is no way to declare a table headerless. Elsewhere, structure comes from semantic tags: anything with no Markdown counterpart is unwrapped rather than turned into a block, so <div>One</div><div>Two</div> arrives as the single run OneTwo, while p, h1-h6, ul, ol and blockquote keep their shape. Ordered lists are renumbered from 1, so start="5" is ignored, and code fences come out bare even when the source said class="language-js" — add the language yourself. Links and image sources are copied across verbatim, so a relative /logo.png from someone else's page will be broken in your README.

What happens to your data

Conversion uses the browser's own DOMParser to build an inert document: the markup is parsed but never attached to the page, so script and style blocks are discarded rather than executed, and no image, stylesheet or font it references is fetched. Your markup is never uploaded, which is the reason to paste an internal wiki export or an email body here rather than into a server-side converter. Markup nested too deeply to walk fails with 'Could not convert that HTML' instead of silently returning nothing.

Last updated August 2026

You have a block of HTML and the place it needs to go takes Markdown — a README, a docs folder in a repo, a static-site source file, a post in a CMS that has dropped its old visual editor. Copying the rendered text out of a browser loses every link and heading; retyping it is worse.

Decide what you are converting before you paste. A whole saved page carries navigation, a cookie banner, a sidebar and a footer, and converting all of it gives you a Markdown file that is mostly menu. Open your browser's element inspector, find the element that wraps the article, and copy that subtree instead. Because you paste markup rather than an address, where the content starts and ends is your decision rather than a guess made for you.

The second thing to settle is what Markdown cannot hold. It has no attributes, so classes, ids, inline styles, colspan and rowspan have nowhere to land. It has no nested tables and no figure captions. Anything a page expressed through CSS — a two-column layout, a coloured callout, a font size — was never meaning in the markup and cannot survive as meaning. Where a table genuinely needs merged cells, the usual answer is to leave that one table as raw HTML, which most Markdown renderers pass straight through.

The common mistake is expecting a clean conversion to give you an identical page. It gives you a plainer one, which is the point of moving to Markdown.

How it works

Toolvore reads your markup with the browser's own HTML parser, then walks the resulting document once, tag by tag, writing Markdown as it goes: h1 through h6 become the matching number of hashes, strong and b become double asterisks, em and i single ones, del, s and strike become tildes, and blockquote puts an angle bracket in front of every line it produced. Runs of whitespace inside text collapse to a single space, which turns indented, pretty-printed source into ordinary prose. Two weak spots are worth knowing. A br is written as a hard line break, and then the same final tidy that collapses stacked blank lines strips the two trailing spaces that made it hard — so a br arrives as a bare newline, which a CommonMark renderer folds back into the paragraph. And a code element whose text contains a newline comes out with no backticks at all, on the reasoning that a multi-line span is not inline code; markup that wraps a block in code alone, with no pre around it, loses its formatting. Lists read only their direct li children, indenting each nested level by two spaces.

Common use cases

  • Moving a knowledge-base article out of an old CMS into a README
  • Turning a subtree copied from the element inspector into docs source
  • Cleaning up the HTML a word processor produces before it reaches a site
  • Converting an internal wiki export without sending it to a third party
  • Rewriting the body of an HTML email as a plain-text post
  • Getting a scraped page into a Markdown note vault

Frequently asked questions

How do I get the HTML of a page in the first place?

View Source gives you the document as the server sent it, which on a JavaScript-heavy site may not contain the article at all. The more reliable route is the element inspector: find the element wrapping the content, right-click it and pick Copy, then Copy outerHTML. That hands you the DOM as it stands after scripts have run, scoped to the part you care about. Reader mode is a third option, stripping the page down to the article at the cost of some structure. Either way, what you paste in is the tags themselves.

Which flavour of Markdown is this — CommonMark or GitHub Flavoured?

Headings, emphasis, links, lists and blockquotes are common to every flavour, so most of what comes out is portable anywhere. Three things are not: pipe tables, tilde strikethrough and triple-backtick fenced code blocks are extensions, popularised by GitHub Flavoured Markdown and since adopted by most renderers. The output uses all three, so it suits GitHub, GitLab, the common static-site generators and most note apps. A strict CommonMark parser with no extensions enabled shows your table as literal pipes instead. Check what your destination parses before committing a file full of tables.

Why did all the styling and layout disappear?

Markdown describes structure, not appearance. A heading says this is a heading; the size, weight, colour and spacing come from whatever renders it later. Everything a page did through CSS — the class on a callout box, the centred image, the brand font, the columns — lives outside the markup's meaning, and attributes are dropped with the tags that carried them, so nothing is left to translate. If a particular look matters at the other end, it belongs in that system's stylesheet rather than in the Markdown. Most of the time that flattening is exactly why people convert.

Is anything I paste sent to a server?

No. The whole conversion happens in the tab. Your markup goes to the browser's own parser, which builds a document never attached to the page, so nothing in it runs and nothing it references is loaded — no image, stylesheet, font or tracking pixel is requested, and script and style elements are discarded rather than executed. Open the network panel while you paste and it stays empty, and your text is gone when you close the tab. A server-side converter means a copy of your markup on someone else's disk and probably in their logs.

Why has my text run together into one long line?

Two causes. The first is whitespace collapsing: runs of spaces, tabs and newlines inside text become a single space, so source indented across forty lines arrives as one flowing paragraph. That is correct — HTML has always treated whitespace that way, and it is the renderer that decides where lines wrap, not the file. The second is br. It is recognised, but the final whitespace tidy removes the two trailing spaces that make a line break hard in Markdown, leaving a plain newline that many renderers join back up. Where separate lines matter, make them real paragraphs.

Can I put HTML inside a Markdown file?

Usually yes, and it is the standard escape hatch for anything the syntax cannot express — a table with merged cells, a details and summary toggle, an image with a set width, an embedded player. Leave a blank line above and below the block so the parser treats it as HTML rather than part of a paragraph. There are limits. Many platforms sanitise it, GitHub among them, stripping scripts, styles and most attributes; some static-site setups disable raw HTML outright; and Markdown syntax inside an HTML block is generally not parsed.

Can I convert the Markdown back into HTML afterwards?

Yes, and that is the easy direction — every static-site generator, most content systems and every Markdown note app do it as their day job. What you should not expect is a round trip that returns what you started with. Going to Markdown discards everything the format cannot hold, and converting back gives tidy markup for the structure that survived, not your original page with its classes and styling restored. Treat the Markdown as the new source of truth, and archive the original HTML in case you need what was dropped.

What happens to a table with merged cells, or a table used for layout?

A pipe table is a fixed grid: one header row, one separator row, then rows of equal length. There is no colspan, no rowspan, no nested table and no caption. A table relying on those has to stay as HTML or be split into simpler tables. Layout tables are the other case worth spotting early: older pages, and most HTML email, use tables as positioning scaffolding rather than to hold data, so converting one gives a grid of unrelated fragments. Neither problem shows up as an error, so read the result rather than trusting it.