How to convert between HTML and Markdown

Paste HTML or Markdown into the field and press HTML to Markdown or Markdown to HTML. The converted text lands in the result pane below the buttons, ready for Copy, and Clear empties both panes before the next document. Input is a single text field and the output is text as well - there is no file upload and no batch mode - and the conversion runs in the browser: the text is not uploaded and the page keeps working after the network drops.

The Markdown written here is GitHub-flavoured - pipe tables, fenced code, nested lists - and the HTML written back is plain HTML without styling. A conversion rewrites the markup; it does not copy the rendered page, so CSS classes, inline styles and scripts are not part of the result.

  1. Paste the HTML or the Markdown into the field at the top of the page. Markdown example fills the field with a short sample if you want to see both directions before using your own text.
  2. Press HTML to Markdown to turn markup into Markdown, or Markdown to HTML for the opposite direction. Both buttons read the same field, so one document can be converted back and forth without reloading the page.
  3. Read the result pane under the buttons: it holds the converted text only, and Copy puts all of it on the clipboard.
  4. Press Clear to empty the field and the result pane. Pressing a conversion button while the field is empty prints a reminder in the page's own language instead of clearing the previous result.
  5. Keep the original text until the output has been checked: heading levels, tables, code fences and lists are rewritten by rule, and the escaping is not always obvious by eye.

What the converter rewrites, drops and escapes

From HTML to Markdown

Headings h1 to h6 become # to ######, paragraphs are separated by a blank line, <strong> and <b> become **, <em> and <i> become _, <del> becomes ~~, and a link becomes [text](href) with the title attribute in quotes. An image becomes ![alt](src) with its title; an image without a src keeps its alt text instead of stopping the conversion, and a link without an href keeps its text. A <br> is written as a two-space line break and an <hr> as * * *.

Lists keep their nesting and their markers: bullets stay -, an ordered list keeps its numbers and its start attribute, and a list item with two paragraphs is written as a loose item instead of being flattened. A <pre><code> block becomes a fenced block; the language is read from a class such as language-js, lang-js or brush: js, the fence grows longer when the code itself contains backticks, and inline <code> becomes a pair of backticks.

Comments, <script>, <style>, <head>, <title>, <meta>, <noscript>, <iframe>, <svg> and form controls such as <input>, <select>, <textarea> and <button> are dropped together with their contents, because they carry no meaning in Markdown. Empty <div> and <span> wrappers disappear as well, text inside an unknown or unbalanced tag is kept, and malformed markup no longer throws the error that used to leave the result pane empty.

From Markdown to HTML

In the other direction the page renders headings, paragraphs, emphasis, links, images, blockquotes, horizontal rules and nested lists as HTML. A fenced block becomes <pre><code> with the language as a class, a GitHub pipe table becomes a real <table> with the alignment applied, and an inline code span becomes <code>, so a sample such as <div> stays visible as text instead of disappearing into the page.

Raw HTML written inside the Markdown is passed through unchanged - the page neither escapes nor strips a <div> or a <script> you wrote yourself - and reference-style links ([text][1] with [1]: url underneath) are resolved. A bullet list followed by an ordered list stays two lists instead of being merged into one, so the numbers survive.

Tables, escaping and practical limits

A <table> becomes a GitHub pipe table: the first row is used as the header (from <th>, or from <td> when the table has no header row), column alignment is read from the align attribute or from a text-align style, and a pipe inside a cell is escaped as a backslash and a pipe. A <br> inside a cell is written as <br> so the row stays on one line.

Text that would be read as Markdown is escaped on the way out: * _ [ ] and backticks get a backslash, a line that begins with #, -, + or a number and a full stop is escaped, and < becomes &lt;. HTML entities are decoded, so &amp; arrives as &, while &nbsp; stays a non-breaking space. Typical uses are an HTML fragment that has to become Markdown for a README or a documentation folder, and the opposite when Markdown has to go into a CMS or a static site. Everything runs on your device, so a very large document is limited by the memory of the browser rather than by an upload quota, and above 50,000 characters the result pane shows plain escaped text instead of syntax colours.

Recent tools: