guidetutorial14 min read

Markdown to HTML: The Developer's Complete Guide (2026)

Three rendering engines. One clean output. Everything a developer needs to convert markdown to HTML without surprises.

Mohammed AgratUpdated May 26, 2026

Markdown to HTML is the oldest export route in the format — the one John Gruber shipped first, in 2004, as a single Perl script. Twenty-two years later there are dozens of engines, three competing dialects, and a long tail of bugs nobody warned you about. This is the developer’s guide to picking the right one and rendering clean.

TL;DR

  • Quick answer: for a one-off, paste into mdclaudy’s live converter and copy the HTML. For code, use markdown-it with GFM presets. For a static site, use whatever your generator ships with.
  • Three engines worth knowing: CommonMark (the spec), GFM (the de-facto default), Markdown-It (the extensible JavaScript one).
  • Render server-side unless the markdown comes from a user after page load.
  • Sanitizeany markdown you didn’t write yourself — both CommonMark and GFM pass raw HTML through by spec.
  • HTML is semantic, not visual. You still need a stylesheet. prose, github-markdown.css, or your own type scale.

What does “markdown to HTML” actually mean?

Markdown to HTML is the process of taking a .md file written in markdown syntax and producing the equivalent HTML markup — # Heading becomes <h1>Heading</h1>, **bold** becomes <strong>bold</strong>, and so on. The output is plain semantic HTML; styling is a separate layer you bring with CSS.

Every static site generator does this. Every wiki engine does this. Every chat surface that supports markdown — Slack, Discord, GitHub comments — does this in real time. The job is mature, but the choice of engine still matters because the dialects don’t agree on every edge case.

The three rendering engines you should know

Pick one based on what your input looks like and how strict you need to be. Most projects end up on GFM — it’s what GitHub renders, what ChatGPT outputs, and what most writers expect.

EngineTablesFootnotesUse it for
CommonMarkNoNoSpecs, parsers, anything that needs deterministic behavior
GFMYesVia extensionBlogs, READMEs, most general-purpose rendering
Markdown-ItYesYes (plugin)Apps that need plugins (math, diagrams, custom syntax)

CommonMark — the spec

CommonMark is the standardization of markdown that John MacFarlane and Jeff Atwood started in 2014 because Gruber’s original specification was ambiguous on enough edge cases to give every parser a different opinion. It defines 17 block-level rules and a handful of inline rules with a 600-page reference. Reference implementations exist in JavaScript (commonmark.js), C (cmark), Go (blackfriday), and Python (commonmark-py).

Strict CommonMark has no tables, no task lists, no strikethrough, no footnotes. If your markdown contains any of those, you need GFM or a Markdown-It plugin.

GFM — GitHub Flavored Markdown

GFM is CommonMark plus five extensions: tables, task lists, strikethrough, autolinks, and fenced code with language identifiers. It’s the dialect ChatGPT speaks, the dialect every reasonable notes app speaks, and the dialect you almost certainly want unless you have a strict reason otherwise.

The reference implementation is cmark-gfm, a fork of cmark that GitHub maintains. Most static site generators ship it by default — Hugo’s Goldmark, Astro’s remark-gfm, Next.js’s remark ecosystem.

Markdown-It — the plugin engine

Markdown-It is the JavaScript engine that powers Stack Overflow, the Visual Studio Code preview, and a long list of npm packages. It’s CommonMark-compliant out of the box and adds a plugin API for every extension under the sun: markdown-it-footnote, markdown-it-katex, markdown-it-deflist, markdown-it-anchor for heading IDs, markdown-it-attrs for custom HTML attributes inline.

If your app renders markdown and you anticipate any custom syntax ever, Markdown-It is the safer choice than locking yourself into a more rigid engine.

What survives the conversion (and what doesn’t)

Standard markdown elements all map cleanly to HTML — headings, paragraphs, links, images, lists, blockquotes, inline code, fenced code blocks. The places it gets interesting are the extensions.

Tables (GFM) become <table>, <thead>, <tbody> with semantic markup. Task lists become <input type="checkbox"> inside <li>. Footnotes become a numbered list at the bottom with bidirectional anchor links — Pandoc and Markdown-It both handle this; GFM does not by default.

Math (KaTeX or MathJax syntax) is not in any markdown spec. You wrap it in $...$ for inline or $$...$$ for block, and rely on a client-side library to render it after the HTML lands. Same story with Mermaid diagrams — ```mermaid becomes a code block; a runtime in the page turns it into SVG.

Custom HTML inside markdown passes through verbatim in all three dialects. If you write <div class="callout"> in your markdown, the renderer will leave it alone. That’s useful, and it’s also why sanitization matters for any input you didn’t write.

Server-side or client-side rendering?

Render on the server. The reasons:

  • Search engines and AI crawlerssee fully formed HTML. Google’s renderer does execute JavaScript, but it does so on a delay and inconsistently. AI crawlers (GPTBot, Claude-Bot, PerplexityBot) mostly do not execute JavaScript at all.
  • Time to first byte drops. The browser receives finished HTML and paints immediately, instead of waiting for the markdown library to download, parse, and render.
  • Bundle size stays small. Markdown-It with a couple of plugins is 50KB minified — not catastrophic, but unnecessary if the markdown never changes after the page renders.

Render on the client when the markdown is genuinely live — a comment box, a chat surface, a live preview pane. In those cases you have no choice; the source isn’t in the page until the user types it.

How the major frameworks handle this

Next.js renders markdown at build time (for static pages) or at request time (for dynamic) via the remark/rehype plugin family. Use remark-gfm for GFM, rehype-pretty-code or rehype-shiki for syntax highlighting.

Astro ships a markdown integration that does GFM by default. Drop .md files into src/pages and they render as routes.

Hugo uses Goldmark, a Go CommonMark+GFM engine. Jekyll uses Kramdown. Eleventy uses Markdown-It by default.

SEO notes: rendering markdown for the web

If your blog or documentation site is markdown-sourced, three SEO details matter for the converted HTML:

  • Heading IDs. Every <h2> and <h3> should have an idattribute for anchor links and Google’s “jump to” features in the SERP. Use rehype-slug in remark/rehype or markdown-it-anchor.
  • Image alt text. Markdown’s ![alt](src) syntax maps to alt attributes directly. Use them.
  • Semantic structure. Headings should descend in order (h1 → h2 → h3) without skipping. Most markdown writers accidentally do this right because the syntax encourages it.

AI search engines like Perplexity and ChatGPT extract heavily from clean semantic HTML — tables, headings, lists, definition lists. Markdown-sourced HTML tends to score well on this because the input format itself enforces structure.

Markdown is HTML’s shorthand. The converter is the decompression algorithm.

Security: when raw HTML in markdown bites

Both CommonMark and GFM allow inline HTML by spec. That means this markdown:

# My post

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

Some content.

Will render the <script>tag verbatim. If you’re building a comment system, a forum, or any surface where users supply markdown, sanitize the HTML output before injecting it into the DOM.

The two standard tools are DOMPurify (browser/Node) and sanitize-html (Node). Both ship sensible defaults that strip <script>, onerror= handlers, javascript: URLs, and other classic XSS vectors while leaving normal markup intact.

Markdown-It has a built-in html: false option that disables inline HTML entirely — the simplest defense if your users have no legitimate need for it.

Real code: the three most common renders

Node.js with markdown-it

import MarkdownIt from 'markdown-it';

const md = new MarkdownIt({
  html: false,
  linkify: true,
  typographer: true,
});

const html = md.render('# Hello, world');

Python with python-markdown

import markdown

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

Pandoc on the command line

pandoc -f gfm -t html input.md -o output.html

# With a CSS stylesheet baked in:
pandoc -f gfm -t html5 --standalone \
       --css=style.css input.md -o output.html

# Just want the HTML body, no <html><head>?
pandoc -f gfm -t html input.md

Pandoc is the heavyweight option — it’s a universal document converter that happens to do markdown to HTML as one of its dozens of format pairs. It’s overkill for a single page but invaluable if your pipeline also produces PDF, DOCX, EPUB, or LaTeX. We cover the PDF route in detail in our markdown to PDF guide.

Online converters worth knowing

For one-off conversion, paste-and-copy tools are still the fastest path. The current shelf:

  • mdclaudy /tools/markdown-to-html — paste markdown, get clean semantic HTML. GFM-compliant. No signup, no watermark, no ads. Use the toggle to wrap output in a stylesheet preset.
  • markdowntohtml.com — the EMD incumbent. Renders to a styled preview. Output HTML is unstyled by default.
  • Dillinger — full live editor with HTML export. More editor than converter, but the export is solid.
  • StackEdit — same lineage as Dillinger; runs in the browser, syncs to Google Drive.
  • CloudConvert / Vertopal / Zamzar— generic file converters. They work, but the HTML is generic and the queue is shared with a hundred other format pairs. Use them if you’re batch-converting many files.

The mdclaudy way: markdown stays the source

mdclaudy is a markdown editor built around the principle that markdown is the artifact, and HTML, PDF, DOCX are renders of that artifact. The same document exports to all three without reformatting. The HTML output is clean: semantic tags, heading IDs, no inline styles, no framework cruft. Drop it into a Next.js page, a WordPress post, a Substack draft, anywhere.

If you also need the PDF version — for a client deliverable, an archive, a print run — the same draft exports through fifteen designed templates. We wrote about that side of the product in our templates showcase and the head-to-head Word vs PDF guide.

Frequently asked questions

How do I convert markdown to HTML?

Three options. Online: paste your markdown into a converter like mdclaudy’s /tools/markdown-to-html, copy the HTML. Command line: install Pandoc, run pandoc -f markdown -t html input.md -o output.html. In code: use a library like markdown-it (Node), markdown (Python), or commonmark(Go). For most people, the online tool is the right answer — it’s zero setup and produces clean, semantic HTML.

What's the difference between CommonMark, GFM, and Markdown-It?

CommonMark is the strict reference spec — 17 core rules, no extensions. GFM (GitHub Flavored Markdown) adds tables, task lists, strikethrough, autolinks, and fenced code with language hints. Markdown-It is a JavaScript engine that ships CommonMark by default and lets you bolt on plugins for footnotes, definition lists, math, and more. Pick GFM unless you have a reason not to.

Should I render markdown on the server or in the browser?

On the server, almost always. Server-side rendering ships clean HTML to the client and lets search engines and AI crawlers read the page without running JavaScript. Render in the browser only when the markdown source itself is user-generated and changes after page load — a comment box, a live preview, a chat surface. Next.js, Astro, Hugo, and Jekyll all do this for you by default.

Is markdown to HTML safe? Can it be XSS'd?

Raw HTML inside markdown is the attack surface. CommonMark and GFM both allow inline HTML by spec — which means <script> tags will pass through unless you sanitize. For user-generated markdown (comments, forum posts), run the rendered HTML through DOMPurify or sanitize-html before injecting it into the DOM. For your own markdown, sanitization is optional — but defense in depth never hurt anyone.

Does markdown to HTML preserve tables, code blocks, and footnotes?

Tables and fenced code: yes, on any GFM-capable engine. Syntax highlighting requires a second pass with highlight.js, Prism, or Shiki. Footnotes are GFM-extended and require either Markdown-It with the footnote plugin, or Pandoc, which handles them natively. Mermaid diagrams and KaTeX math need their own client-side runtimes after the HTML lands.

What's the best markdown to HTML converter for blogs?

For a static blog, your static site generator already does this — Hugo uses Goldmark, Jekyll uses Kramdown, Astro and Next.jsuse remark/rehype. For a one-off conversion, mdclaudy’s online tool outputs clean semantic HTML you can paste into any CMS. For WordPress, the Jetpack plugin renders markdown server-side on save.

Can I convert HTML back to markdown?

Yes — turndown (JavaScript) and html2text (Python) are the standard tools. Round-tripping is not perfect, though: complex HTML structures collapse to approximations, and any styling beyond what markdown can express is lost. If round-trip fidelity matters, keep markdown as your source of truth and treat the HTML as derived output.

Why does my markdown to HTML output look unstyled?

Because HTML is semantic, not visual — the converter produces <h1>, <p>, <ul>tags and leaves styling to your CSS. Wrap the output in a container with a typographic stylesheet (Tailwind’s prose class, GitHub’s github-markdown.css, or your own type scale) and it will look like the page you expected.

One thing to remember

Markdown to HTML is solved. The engines are fast, the dialects are stable, and the bugs are mostly in your CSS. The only real decision is whether you render server-side (almost always) or in the browser (when the markdown is live). Pick GFM, render on the server, ship a stylesheet, sanitize anything user-generated.

For everything else — when the same markdown also needs to leave your computer as a designed page — that’s the moment a tool like mdclaudy starts pulling its weight. The HTML stays clean; the PDF looks typeset.

─── try mdclaudy ───

Write markdown. Ship a designed PDF.

Fifteen hand-built templates. Optional AI. Free up to 50 documents.

No card. 50 documents included.
─── Related reading