Free Markdown Previewer Online

Write Markdown on the left and see a live rendered preview on the right. Supports headings, bold, italic, code blocks, tables, lists, and more.

Editor (Markdown)
Preview (Rendered)

Markdown Cheat Sheet

# Heading 1 · top-level heading
## Heading 2 · sub-heading
**bold** · bold text
*italic* · italic text
~~strike~~ · strikethrough
`code` · inline code
[link](url) · hyperlink
![alt](url) · image
- item · unordered list
1. item · ordered list
> quote · blockquote
--- · horizontal rule

A Short History of Markdown

Markdown was created by John Gruber, the writer behind the Daring Fireball weblog, with substantial design feedback from Aaron Swartz. The first public release, version 1.0, was announced on Gruber's site on 9 March 2004; version 1.0.1, the canonical reference release, followed on 17 December 2004 and is still the version linked from daringfireball.net/projects/markdown. Markdown is two things at once: a plain-text formatting syntax and the original Perl script that converts that syntax to HTML. Gruber's stated goal was that the source text should be readable as-is, a Markdown document opened in a plain-text editor should look like a thoughtfully formatted email, not a tag soup. That readability constraint is the philosophical line that separates Markdown from XML-based formats and from heavier markup like LaTeX, and it is the reason every later extension has had to argue for itself in terms of how badly it disrupts the source.

Gruber credits Swartz at length in the Markdown acknowledgements: "Aaron Swartz deserves a tremendous amount of credit for his feedback on the design of Markdown's formatting syntax." Swartz had earlier written a related lightweight markup called atx (2002), which contributed the now-familiar # and ## heading style, sometimes still called "atx-style headings" inside parser specs. Swartz's involvement is a piece of his broader legacy: he co-built RSS 1.0 as a teenager, was a co-owner at Reddit until 2007, and continued to influence open web standards until his death in 2013. A piece of trivia worth getting right: the file extension .md is now near-universal, but Gruber's original tool used .text: the migration to .md was a community convention that took hold once Markdown left the blogging niche.

Why Markdown Won the Web

A markup language wins by being adopted by the platforms that publish most of the world's text. In a tight five-year window, Markdown was adopted by the platforms that came to dominate long-form discussion, code collaboration and developer documentation. Stack Overflow launched on 15 September 2008 with Markdown as the formatting syntax for questions, answers and comments, using an editor called WMD (Wysiwym Markdown) by John Fraser of AttackLab; the Stack Overflow team later rewrote it as the open-source PageDown editor maintained at github.com/StackExchange/pagedown. Reddit, founded by Steve Huffman and Alexis Ohanian in 2005 with Aaron Swartz joining shortly after, shipped Markdown for comments not long after launch and carried the syntax to a much broader, non-developer audience. GitHub launched in 2008 and within a year was rendering Markdown in README.md and issue comments; in 2009 it began documenting and shipping its own dialect, GitHub Flavored Markdown. Discord, launched in May 2015, picked up a Markdown-flavoured chat syntax for bold, italic, strikethrough, inline code, code fences and blockquotes, what most non-developers under 25 now think of as "putting stars around something." The skill compounds: a writer who learns Markdown once can write blog posts in Jekyll/Hugo/Eleventy, documentation in MkDocs/Docusaurus/Read the Docs, presentations in Marp and Reveal.js, notes in Obsidian/Bear/Logseq/Notion, chat in Slack and Discord, and source-code documentation in essentially every modern open-source project.

CommonMark, Fixing the Underspecification

Gruber's original 2004 syntax description was famously informal, a prose document with examples, not a grammar. It left dozens of edge cases unspecified ("how does emphasis interact with underscores in the middle of a word?"; "does a list inside a blockquote close the blockquote?"; "what counts as a tight versus loose list?"), and Gruber never released a reference parser other than his Perl script, whose behaviour was idiosyncratic in ways other implementers had to either copy or override. The result by the early 2010s was that GitHub, Reddit, Stack Overflow, Pandoc and the Discount C parser all rendered the same Markdown source slightly differently, and the same input could break across platforms.

In 2012, Stack Overflow co-founder Jeff Atwood (by then running Discourse) and Pandoc author John MacFarlane began an effort to write a real, testable specification. They were joined by David Greenspan (Meteor), Vicent Marti (GitHub), Neil Williams (Reddit) and Benjamin Dumke-von der Ehe (Stack Exchange). The project launched publicly in September 2014 as "Standard Markdown"; within days Gruber objected to the name in private email, Atwood wrote a public post explaining the change, and the project was rebranded "CommonMark." The first numbered release came on 25 October 2014. The current published version is CommonMark 0.31.2, released 28 January 2024, a "1.0" was promised for 2019 and has not arrived because a small number of pathological edge cases (notably around emphasis parsing and HTML embedding) have not produced unanimous resolutions. In practice 0.31.2 is treated as production-stable. The CommonMark spec is unusual in that it is itself a CommonMark document, with 600+ executable test cases inline; a parser claims conformance by passing those tests.

GitHub Flavored Markdown, Five Extensions on Top

The formal GFM specification, published in 2017 and most recently versioned as 0.29-gfm on 6 April 2019, defines five extensions on top of CommonMark: tables (pipe-delimited blocks with a delimiter row using dashes and : for per-column alignment); task list items (list entries that begin with [ ] for unchecked or [x] for checked, rendered as disabled HTML checkboxes, GitHub additionally lets logged-in users toggle these by clicking, which is a UX layer on top of the spec, not part of the spec itself); strikethrough (wrapping text in ~~ produces <del>: CommonMark itself does not specify this); autolinks extension (bare URLs and email addresses in running text are auto-linked, where CommonMark only does so for explicit angle-bracket autolinks); and disallowed raw HTML (a security restriction that strips <script>, <iframe>, <style>, <title>, <plaintext>, <textarea>, <xmp>, <noembed>, <noframes> and a handful of other dangerous tags). A sixth feature commonly attributed to GFM but worth treating carefully is fenced code blocks with language identifiers: fenced code blocks are part of CommonMark itself; the language hint after the opening fence is also CommonMark; the syntax-highlighting GitHub then applies based on that hint is GitHub's rendering behaviour, not the spec. GitHub's renderer also runs additional post-processing, HTML sanitization via its in-house html-pipeline gem, emoji shortcode expansion (:smile:), @user and #issue autolinking, none of which are in GFM itself.

The Major Parsers

marked.js was created by Christopher Jeffrey, with the original copyright dated 2011, and has been maintained by the markedjs GitHub organisation since 2018. It is a single-pass, lexer-then-parser design that prioritises raw speed; the docs explicitly position it as a "low-level compiler for parsing markdown without caching or blocking." It is the parser this previewer currently uses for the live render. Marked is small, fast, extensible through token hooks, and one of the most-starred markdown projects on GitHub (~36k stars).

markdown-it was launched in 2014 by Vitaly Puzrin and Alex Kocharin. The two had previously contributed almost all the code to a parser called Remarkable; when leadership disputes blocked progress they re-organised the same authorship around markdown-it. The project advertises 100% CommonMark conformance with optional GFM toggles for tables and strikethrough, plus an aggressive plugin ecosystem (markdown-it-footnote, markdown-it-emoji, markdown-it-attrs, markdown-it-anchor, markdown-it-task-lists and several hundred others). It is the parser used by VS Code's built-in Markdown preview, GitLab's web UI, and a long list of static-site generators including Eleventy.

remark / unified.js is not a single parser but a tree-transformation framework. The unified collective, started around 2014, defines an abstract syntax tree spec called mdast (Markdown Abstract Syntax Tree); remark parses Markdown into mdast, plugins manipulate the tree, and remark-rehype converts mdast to hast (the HTML AST) for emission. The model is slower than marked but vastly more composable. Notable users include Prettier (which formats Markdown using remark), Gatsby, MDN, the Node.js documentation pipeline, and the alex inclusive-language linter. The unified collective lists 312 projects and roughly 6.3 billion monthly npm downloads across all its packages.

MDX, first committed in late 2017 by John Otander and others connected to the Compositor design tools company, was publicly announced at ZEIT Day 2018 and shipped 1.0 on 11 April 2019. MDX combines Markdown content with JSX components, so a writer can drop a <Chart /> or <Tweet id="123" /> directly into prose. It powers Next.js docs, Docusaurus and most React-based documentation sites. MDX has its own parser distinct from CommonMark; v1 was based on remark, v2+ uses a dedicated MDX grammar to handle JSX expressions correctly inside paragraph context.

Pandoc, The Universal Converter

Pandoc was released by John MacFarlane, then a philosophy professor at the University of California, Berkeley, on 10 August 2006. It is written in Haskell, and its design centres on parsing any of about 30 input formats (Markdown, reStructuredText, HTML, LaTeX, DocBook, Textile, MediaWiki and DokuWiki markup, Org-mode, Microsoft Word .docx, OpenDocument, EPUB, JATS XML, Jupyter .ipynb and others) into a shared abstract document model, then rendering that model into about 40 output formats (HTML, PDF via LaTeX or wkhtmltopdf, .docx, .odt, ePub2/3, slide formats including Beamer and reveal.js, and many more). It is ubiquitous in academic and technical publishing because it carries citations through CSL JSON / BibTeX and resolves them into formatted references for any of the major citation styles. The Markdown dialect Pandoc parses by default ("Pandoc Markdown") is itself a CommonMark superset with extensions for footnotes, definition lists, fenced divs, math (LaTeX-style $...$ and $$...$$) and table captions. Pandoc is GPL v2-or-later licensed and is what most academic departments use to compile Markdown manuscripts into journal-ready Word documents.

MultiMarkdown, Markdown Extra, and SmartyPants

Two earlier extension dialects pre-date CommonMark and influenced both GFM and Pandoc. MultiMarkdown was created by Fletcher T. Penney with an initial release in May 2007 (project work began 2005-2006), motivated by academic writing, Penney wanted Markdown capable of producing a publishable manuscript with footnotes, citations, mathematics, definition lists and YAML-style document metadata. MultiMarkdown introduced or popularised pipe-character tables, [^id] footnote markers, math notation, document-level metadata blocks at the top of files, and image and table captions. Markdown Extra was created by Michel Fortin (PHP Markdown author) in 2005-2006 and added pipe tables, fenced code blocks with ~~~ (later also ```), footnotes, definition lists, abbreviations, and the {#id .class} attribute syntax for headings. Its most distinctive contribution was the relaxation of Markdown-inside-HTML rules, the markdown="1" attribute that lets you nest Markdown inside an HTML block. Several CommonMark and GFM design choices around fenced code and tables trace back to Markdown Extra. Separately, SmartyPants: Gruber's own 2002 typography companion, performs typographic substitutions: straight ASCII quotes become curly quotes, double and triple hyphens become en- and em-dashes, three periods become a true ellipsis. Markdown handles structure; SmartyPants handles polish; many parsers bundle SmartyPants-style behaviour as a post-processing step (markdown-it-smartypants, remark-smartypants), and Pandoc has it built in behind a --smart flag.

Common Pitfalls, Ten Things That Bite New Writers

A live previewer makes most parsing surprises obvious immediately, but understanding why they happen helps a writer get the source right first time.

  1. Smart-quote conversion that breaks code samples. SmartyPants-style filters happily convert quotes inside what looks like prose (including, sometimes, inside inline code spans or HTML attribute values) leaving you with broken markup. Most modern parsers exclude code spans from typographic substitution, but blog platforms with custom pipelines often do not.
  2. List-marker detection is whitespace-sensitive. Mixing -, * and + inside the same list, indenting list continuation paragraphs by less than the marker requires, or putting a blank line between list items can flip a tight list into a loose list (each item wrapped in <p> tags), a difference invisible in the source but dramatic in the output.
  3. Autolink overzealousness. GFM-style autolinking turns any bare URL into a link, which is usually what you want, but it can also mangle URLs inside what should have been a code span, or URLs containing parentheses (Wikipedia URLs especially). The rule for "where does this URL end?" varies between parsers.
  4. Code-fence language hints. The text after the opening triple-backtick, ```js versus ```javascript versus ```ts versus ```typescript: is a hint, not a spec. Different syntax highlighters recognise different aliases; Highlight.js, Prism, Shiki and the GitHub renderer each have their own language dictionaries.
  5. Tables that need escaping. Pipe characters inside table cells must be escaped as \|, otherwise they are read as column separators. Catches anyone trying to put a one-line code example inside a table cell.
  6. Hard line breaks. Inside a paragraph, a single newline is treated as whitespace and the lines are joined; you have to either put two trailing spaces at the end of the line, or use a backslash, depending on the parser. CommonMark allows both. Some older parsers require an explicit <br>.
  7. Mixed Markdown and HTML. Markdown was designed to pass arbitrary HTML through, so dropping a <div class="callout"> into a Markdown file works. But the moment you put Markdown syntax inside an HTML block, parsers diverge: CommonMark treats most HTML blocks as opaque; Markdown Extra introduced markdown="1" to opt in to nested parsing.
  8. HTML entities and character escapes. An ampersand & in a URL needs no escaping inside a Markdown link, but the same & outside a link will be passed through to HTML and may need to be &amp; for strict HTML5 conformance. Most renderers handle this automatically; some do not.
  9. Heading IDs. GitHub auto-generates URL fragment IDs from heading text using a slugify rule; many parsers do too, but the slugify algorithms differ. Same heading, different anchor across platforms, a perennial cause of broken intra-document links when content moves between systems.
  10. Trailing whitespace and editor settings. Editors that strip trailing whitespace on save will silently delete Markdown's two-trailing-spaces line-break syntax. Editors that convert tabs to spaces (or the reverse) will break code blocks that depend on indentation.

Markdown and Security, XSS and Sanitization

Markdown is dangerous in one specific way: every mainstream parser passes raw HTML through unchanged. That is by design (it is what makes Markdown useful for hand-coded callouts and embeds) but it also means a Markdown previewer that injects parser output directly into the DOM is, by default, an XSS vector. Pasting <img src=x onerror="alert(1)"> into a Markdown editor and rendering the output without sanitization will execute the alert. Two layers of defence are standard. First, parser-level configuration: marked.js, markdown-it and remark all expose options to disable raw HTML or escape it on output (markdown-it has html: false by default; remark/rehype has rehype-sanitize). GFM additionally specifies the "disallowed raw HTML" extension that strips a hard-coded list of dangerous elements. Second and more robust, HTML sanitization after parsing: DOMPurify, written by the Berlin security firm Cure53 starting in February 2014, is the de facto JavaScript sanitizer. It takes an HTML string, parses it into a DOM, walks the tree allowing only a configurable safe subset of elements and attributes, and serialises the result. DOMPurify removes <script>, blocks inline event handlers, strips javascript: URLs, and handles a hundred subtle XSS bypasses (SVG <use> abuses, MathML attribute polyglots) that a naive regex sanitizer will miss. The recommended pipeline for any browser-based previewer that accepts raw HTML is: markdownString → parser → htmlString → DOMPurify.sanitize() → innerHTML. CommonMark also explicitly requires parsers to refuse javascript: URIs in autolinks; most parsers extend that rejection to all link forms.

Markdown vs reStructuredText vs AsciiDoc

Markdown is the dominant lightweight markup language but not the only one. reStructuredText (reST) was first released in June 2001 by David Goodger as part of the Python Doc-SIG, evolving out of an earlier Zope format called StructuredText. It became Python's official documentation format in 2002 and is the input language for Sphinx, the documentation generator behind nearly all Python project docs (the official Python language docs, NumPy, SciPy, Django, Flask, scikit-learn, pandas, the Linux kernel documentation since 2016, CMake, LLVM). RST's design philosophy is essentially the opposite of Markdown's: it accepts more visual noise in the source in exchange for more semantic precision in the output. RST has a built-in extension mechanism via "directives" (.. note::, .. code-block:: python) and "roles" (:func:, :ref:) that lets a project define domain-specific markup without leaving the format. AsciiDoc was created in 2002 by Stuart Rackham as a Python tool that deliberately targets DocBook XML semantics (every AsciiDoc document maps cleanly to DocBook) making it the markup of choice for projects that need publication-quality books, technical specifications and manuals. AsciiDoc is what the Git project's documentation is written in, what O'Reilly Media uses for many of its books, what Red Hat and Mozilla use for several product documentation sets, and what GitHub and GitLab support natively as a README.adoc alternative. The original Python implementation has been superseded by Asciidoctor, a Ruby implementation released in 2013. Practical guidance: choose Markdown for blog posts, READMEs, chat, notes and most documentation; reStructuredText for Python documentation processed by Sphinx; AsciiDoc for long-form books or specifications that need to render to DocBook, PDF and EPUB simultaneously with full semantic fidelity.

Frequently Asked Questions

Which Markdown dialect does this previewer use?

CommonMark with the most common GFM extensions enabled, tables, fenced code blocks with language hints, strikethrough via ~~text~~, autolinks for bare URLs, and task list items via [ ] and [x]. The renderer is marked.js, the same parser the editor's "preview while you type" experience uses across many open-source markdown apps. Headings, bold, italic, links, images, lists, blockquotes, horizontal rules and inline code all work as you would expect on GitHub.

Will the rendered HTML look the same on GitHub?

The structural HTML (paragraphs, lists, tables, headings) will match GitHub's rendering for any input that is valid CommonMark + GFM. Two layers will differ: GitHub applies its own CSS theme and syntax-highlighting CSS, so colours, fonts and spacing will look different; and GitHub layers post-processing on top of the spec (emoji shortcodes like :smile:, @user mentions, #issue auto-linking, repository-relative image paths) that no spec-compliant previewer reproduces. If you copy the rendered HTML out of this tool, it will paste cleanly into any HTML context, but it will not carry GitHub's themed appearance.

Can I export the rendered HTML?

Yes. The "Copy HTML" button copies the parser's HTML output to your clipboard, ready to paste into a CMS, an email, an Obsidian or Notion document, or anywhere else that accepts HTML. For the rendered visual output (with paragraph spacing, code formatting, etc.) you can also right-click the preview pane and use your browser's "Inspect" or "View Source" feature.

Is my text saved or sent anywhere?

No. The Markdown parser runs entirely in your browser via JavaScript. Nothing is uploaded, no API is called, no logs are written. Close the tab and the text is gone. If you want to keep what you wrote, copy it out before leaving the page. You can also use the page offline once it has loaded once, service-worker caching means the parser stays available without an internet connection.

Does the previewer sanitize raw HTML?

The parser passes raw HTML through, which is the standard CommonMark behaviour, useful for embedding the occasional <div> or <details> block. Because the input comes from your own browser session and the output is only rendered in your own tab, this is safe for the one-person preview use case it is built for. If you are publishing the output on a multi-user system (a CMS, a forum, a documentation site that accepts user submissions) you should always run the rendered HTML through a sanitizer like DOMPurify before injecting it into a public page, Markdown plus raw HTML is an XSS vector in any system where the writer and the reader are different people.

Are there limits on file size?

No hard limit. The parser handles tens of thousands of lines of Markdown without issue on a typical laptop. The live re-render does run on every keystroke, so very large documents (a full book in a single file) will start to feel sluggish on slower devices. Splitting into chapters, or pasting content in to render once and then editing offline, is the workaround. The page will not freeze your browser, marked.js is one of the fastest Markdown parsers available.

Related Tools