Markdown to HTML

Convert Markdown to clean, sanitized HTML. Tables, task lists, strikethrough and fenced code all work, and the output uses plain semantic elements with no classes attached.

Markdown
HTML Output

1 Markdown to HTML example

Markdown

1
2
3
4
5
6
7
8
9
10
11
12
## Release notes

Shipped **2.4.0** on 10 September.

- [x] Store credit at checkout
- [ ] Partial refunds

| Change | Impact |
| ------ | ------ |
| New pricing API | breaking |

> Upgrade before the 30th.

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
<h2>Release notes</h2>
<p>Shipped <strong>2.4.0</strong> on 10 September.</p>
<ul>
  <li><input checked disabled type="checkbox"> Store credit at checkout</li>
  <li><input disabled type="checkbox"> Partial refunds</li>
</ul>
<table>
  <thead><tr><th>Change</th><th>Impact</th></tr></thead>
  <tbody><tr><td>New pricing API</td><td>breaking</td></tr></tbody>
</table>
<blockquote><p>Upgrade before the 30th.</p></blockquote>

2 The output is sanitized before you see it

Markdown lets raw HTML through by design, so a document from an untrusted source carries the same risk as untrusted HTML. This page runs the rendered HTML through DOMPurify, which removes script tags, inline event handlers such as onerror, and javascript: URLs before the output appears.

Sanitize user-submitted Markdown in your own code too. Marked, markdown-it and league/commonmark all pass raw HTML through by default, because the CommonMark spec allows it. If you render user Markdown on a server, sanitize the result or set the parser's own escape option. Without that step, a comment box becomes a stored XSS (a script saved in your database and served to every visitor).

3 Options

Format output

Indents the markup instead of emitting one line per block. The browser renders both the same way, but indented HTML is easier to review and diff.

Line breaks as <br>

CommonMark joins a single newline into the same paragraph, while GitHub comments turn it into a line break. Turn this on to get the GitHub-comment behavior.

No classes anywhere

Markdown has no syntax for classes, so you get semantic elements such as h2, table and blockquote. Style them from your own stylesheet.

Live preview is in the editor

The Markdown editor renders side by side as you type. Use this page for a one-off conversion.

How to use the Markdown to HTML tool

  1. Paste Markdown into the Markdown panel, or load a file with Upload .md.
  2. Leave Format output on to indent the HTML, or turn it off for one line per block.
  3. Tick Line breaks as <br> to make a single newline a hard break, the way GitHub comments work.
  4. Click Copy HTML, or Download to save the result as an .html file.

How to render Markdown to HTML safely

JavaScript / Node.js

// npm i marked dompurify jsdom
const { marked } = require("marked");
const createDOMPurify = require("dompurify");
const { JSDOM } = require("jsdom");

const DOMPurify = createDOMPurify(new JSDOM("").window);

const html = DOMPurify.sanitize(
    marked.parse(userInput, { gfm: true, breaks: false }),
);

// Markdown allows raw HTML through by design. If userInput came from a
// person, that sanitize call is the whole security boundary.

PHP

<?php
// composer require league/commonmark
use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\GithubFlavoredMarkdownExtension;
use League\CommonMark\MarkdownConverter;

$environment = new Environment([
    'html_input' => 'escape',        // the important line for user content
    'allow_unsafe_links' => false,
]);
$environment->addExtension(new CommonMarkCoreExtension());
$environment->addExtension(new GithubFlavoredMarkdownExtension());

echo (new MarkdownConverter($environment))->convert($userInput);

Python

# pip install markdown-it-py bleach
from markdown_it import MarkdownIt
import bleach

md = MarkdownIt("commonmark").enable(["table", "strikethrough"])
html = md.render(user_input)

ALLOWED = ["p", "h1", "h2", "h3", "h4", "strong", "em", "del", "a", "code",
           "pre", "ul", "ol", "li", "blockquote", "hr", "br",
           "table", "thead", "tbody", "tr", "th", "td"]

safe = bleach.clean(html, tags=ALLOWED, attributes={"a": ["href", "title"]})

Common errors and how to fix them

Single newlines vanish
CommonMark treats one newline as a space inside a paragraph. End the line with two spaces, or turn on the breaks option.
A table renders as text full of pipes
The |---|---| separator row is missing, or the parser does not have GFM enabled. Tables are a GFM extension and are not part of core CommonMark.
Raw HTML in the source disappeared
DOMPurify removed it on purpose. In your own code, check whether the parser escapes HTML input, and make sure it does for user content.
A nested list came out flat
The indentation does not reach the parent item's content column, which is two spaces for a dash and three for 1. Mixed tabs and spaces are the usual cause.

Good to know

CommonMark settled most of the ambiguity in the original 2004 description, and GitHub Flavored Markdown is CommonMark plus tables, task lists, strikethrough and autolinks. Footnotes, definition lists and YAML front matter are extensions that some parsers support and others ignore without an error. That is why the same document can render correctly in one tool and break in the next.

Specifications and references

This tool follows the specifications below. Read them when you need the exact normative wording, for example to settle an edge case between two implementations.

Frequently Asked Questions

Which flavor of Markdown is this?

CommonMark plus the common GitHub extensions: tables, task lists, strikethrough and fenced code blocks with a language tag.

Is the HTML sanitized?

Yes. Markdown lets raw HTML pass straight through, so the rendered output goes through DOMPurify, which removes script tags, inline event handlers and javascript: URLs before you see it.

Can I get pretty-printed HTML?

Turn on Format output and the markup comes out indented instead of as one long line per block. The browser renders both the same way; the indented version is easier to read and diff.

Why are there no classes on anything?

Markdown has no syntax for classes. You get semantic elements such as h2, table and blockquote, and you style them from your own stylesheet.

How do I get a live preview instead?

Use the Markdown editor, which renders side by side as you type. This page is for a one-off conversion where you only need the HTML.

Going the other way

HTML to Markdown does the reverse. For a side-by-side preview while you write, use the Markdown editor, and to tidy the resulting markup, the HTML formatter.

More Data Converters

Browse all data converters

Copied to clipboard!