← Blog

Markdown to HTML: 3 methods compared (in-browser, CLI, library)

Three practical ways to convert Markdown to HTML — a web tool, a command-line one-liner, and library options for Node, Python, and Ruby. With sanitization gotchas.

Most static-site generators, blog engines, content APIs, and email tools accept HTML, not Markdown. So you write in Markdown — for the speed and readability — and convert to HTML at the boundary. This guide covers three practical ways to convert Markdown to HTML in 2026, with the gotchas that bite people in production.

The three methods

  1. Web tool — paste Markdown, copy HTML (or download). Zero install.
  2. Command linepandoc,cmark, ormarkdown-it CLI. Scriptable.
  3. Library in your stack — Node (markdown-it,marked,remark), Python (markdown,mistune), Ruby (redcarpet,kramdown), Rust (pulldown-cmark), etc.

Pick by what you're trying to do.

Method 1: Web tool

Paste Markdown intoMarkdown Tidy's editor — the preview pane shows the rendered HTML, Export → HTML downloads a standalone.html file you can drop into a web page or open in a browser.

Wins: zero install, the source is automatically cleaned and repaired before rendering (no AI-generated** artifacts in your output), runs locally in your browser. Best for one-off conversions or when you just need the rendered HTML for an email or a simple webpage.

Loses: not a programmatic pipeline. If you're converting 1000 files, the CLI or a library wins.

Method 2: Command line

The fastest one-liner if Pandoc is installed:

pandoc input.md -o output.html

By default, Pandoc emits a standalone HTML document with<html>,<head>, and<body>. To get just the body fragment (useful for embedding in a CMS):

pandoc input.md -t html --no-highlight

cmark (the CommonMark reference implementation) is lighter:

cmark input.md

Outputs HTML to stdout. Pipe it into a file:

cmark input.md > output.html

For GitHub Flavored Markdown (tables, task lists, strikethrough), usecmark-gfm:

cmark-gfm --extension table --extension tasklist --extension strikethrough input.md

Method 3: Library

Node.js

markdown-it is the de-facto choice. Fast, plugin ecosystem, used by Vue's docs and many other projects:

import MarkdownIt from 'markdown-it';
const md = new MarkdownIt();
const html = md.render('# Hello world');

Alternatives:marked (smaller, slightly faster, fewer plugins) andremark (the unified ecosystem — more power, more setup).

Python

The standard library ismarkdown:

import markdown
html = markdown.markdown('# Hello world')

For GFM features (tables, fenced code, etc.) enable extensions:

html = markdown.markdown(text, extensions=['tables', 'fenced_code'])

For speed at scale,mistune is faster but a smaller plugin ecosystem. SeeMarkdown in Python for the full comparison.

React / JSX

react-markdown renders Markdown as React components — nodangerouslySetInnerHTML, safer by default:

import ReactMarkdown from 'react-markdown';
<ReactMarkdown>{markdown}</ReactMarkdown>;

SeeMarkdown in React for the full picture (sanitization, custom renderers, code highlighting).

Ruby

kramdown is the de-facto standard for Ruby (used by Jekyll, Middleman, GitHub Pages historically):

require 'kramdown'
html = Kramdown::Document.new(text).to_html

Sanitization: the bit everyone forgets

This is the most-important paragraph in this guide.Most Markdown libraries do not sanitize HTML by default. If your Markdown source contains:

Some text.

<script>alert('xss')</script>

…most libraries pass that<script> tag through to the output. If that HTML ends up rendered in another user's browser, you have an XSS vulnerability.

Rules:

  1. Sanitize after rendering. UseDOMPurify (Node/browser) orbleach (Python) on the output HTML before storing or displaying.
  2. Configure the renderer to refuse raw HTML.markdown-it has{ html: false }.marked hassanitize: false — confusingly named, but the right setting isnot allowing raw HTML at all via themarkdown.html option.
  3. Don't trust the source. Even if you "wrote" the Markdown, if a user can submit Markdown that becomes part of an HTML page, sanitize.

Markdown Tidy's renderer defaults to refusing raw HTML in persisted output. Same goes for our public API.

GitHub Flavored vs CommonMark

Pure CommonMark doesn't include tables, task lists, strikethrough, or auto-linked URLs. If you write Markdown that includes any of those, you need a GFM-compatible renderer. SeeGitHub Flavored Markdown: what's different.

Most modern libraries support GFM via opt-in extensions; check the docs fortables,tasklist,strikethrough,autolink, andlinkify.

Quick picker

Your situationPick
One-off conversion, no installMarkdown Tidy → Export → HTML
Convert one file in your terminalpandoc orcmark-gfm
Render in a Node appmarkdown-it
Render in a Python appmarkdown (extensions enabled)
Render in Reactreact-markdown
Render server-side in Rubykramdown
Heavy programmatic load, no installMarkdown Tidy API — POST markdown, get HTML

Try Markdown Tidy free

Paste markdown, get a polished document — no signup required.