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-itwith 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.
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 anidattribute for anchor links and Google’s “jump to” features in the SERP. Userehype-slugin remark/rehype ormarkdown-it-anchor. - Image alt text. Markdown’s
syntax maps toaltattributes 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.mdPandoc 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
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.