What the result contains
What This Tool Provides
Convert Markdown to HTML in your browser, covering the CommonMark essentials plus the GitHub extensions people actually use: tables, task lists, strikethrough and autolinks. Raw HTML in the source is escaped by default and every link URL is checked against a scheme allowlist, because converting Markdown means producing HTML — and unescaped HTML from an untrusted document is a script-injection vector rather than a formatting convenience.
- Headings, paragraphs, emphasis, lists, blockquotes and fenced code blocks
- GitHub tables with column alignment, task lists, and strikethrough
- Raw HTML escaped by default, with a switch to pass it through deliberately
- A rendered preview inside a sandboxed frame that cannot execute scripts
How to Use This Tool
- Paste the MarkdownA README, release notes, a documentation page — anything written in Markdown.
- Decide about raw HTMLLeave escaping on for anything you did not write. Turn it off only for your own trusted source that deliberately contains tags.
- Copy the HTML or check the previewSwitch to the preview to see the rendering, then copy the HTML source when it looks right.
How It Works
Conversion runs in two passes. The block pass walks the source line by line and recognizes structure: fenced code blocks first so nothing inside them is interpreted, then rules, headings, blockquotes, tables, lists, and finally paragraphs, with lists recursing so a nested list becomes a nested element. The inline pass then runs over each block’s text, extracting code spans before anything else so their contents are never treated as markup, then images, links, autolinks, and finally the emphasis and strikethrough markers. HTML escaping happens before the inline pass, which is why a script tag in the source is already inert by the time any pattern sees it.
Worked Examples
A short document
- Input
# Release notes Fixes **two** bugs in `parse()`. - Faster on large files - Correct quoted fields- Output
<h1>Release notes</h1> <p>Fixes <strong>two</strong> bugs in <code>parse()</code>.</p> <ul> <li>Faster on large files</li> <li>Correct quoted fields</li> </ul>
Heading, paragraph and list become their semantic elements. The code span is extracted before emphasis runs, so nothing inside the backticks is reinterpreted.
A script tag is escaped, not executed
- Input
Hello <script>alert(1)</script>- Output
<p>Hello <script>alert(1)</script></p>
With escaping on, the tag becomes visible text rather than markup. This is the default because Markdown you did not write should never be able to inject a tag into your page.
A table with alignment
- Input
| Tool | Rows | | :--- | ---: | | CSV | 1200 |- Output
<table> <thead> <tr><th style="text-align:left">Tool</th><th style="text-align:right">Rows</th></tr> </thead> <tbody> <tr><td style="text-align:left">CSV</td><td style="text-align:right">1200</td></tr> </tbody> </table>
The colons in the divider row set per-column alignment, which is a GitHub extension rather than part of CommonMark.
Why Raw HTML Is Escaped by Default
Markdown was designed to allow raw HTML. That is a deliberate feature of the original specification and it is genuinely useful when you are writing your own document and need a construct Markdown lacks. It is also the reason a Markdown converter is a security boundary rather than a formatting utility.
The moment a document you did not write is converted with raw HTML passed through, its author chooses what ends up in your page. A script tag is the obvious case; the subtler ones are an image with an onerror handler, an iframe, a form posting somewhere else, or a style block repositioning an element over a real button. All of them are legal HTML and all of them survive a converter that does not escape.
So escaping is on by default, and turning it off is a deliberate act. When it is off, tags pass through untouched — which is exactly right for your own README containing a deliberate detail element, and exactly wrong for a comment body, a user-submitted description, or anything arriving from an API. Independently of that switch, link and image URLs are always filtered against a scheme allowlist, so a javascript: href never survives the conversion in either mode.
The Preview Runs in a Sandbox
A rendered preview is the obvious feature for a Markdown tool and the obvious way to undo all of the care above. Injecting converted HTML into the page would give the source document a foothold in this page’s origin — the definition of a self-inflicted cross-site scripting bug, and a particularly awkward one on a site whose promise is that your input never goes anywhere.
The preview here is an iframe carrying a sandbox attribute with no allow-scripts token. That combination disables scripting, form submission, plugins, popups and same-origin access inside the frame. The converted markup renders and cannot execute, so the preview is honest about the layout without inheriting any of the risk.
It is a good illustration of a general point about this kind of tool: the safe design is not to sanitize harder, it is to render in a context where the dangerous thing cannot happen. Escaping handles the output you copy; the sandbox handles the output you look at.
Which Markdown, Exactly
There is no single Markdown. The 2004 original was defined by its implementation, CommonMark later specified the ambiguous parts, and GitHub Flavored Markdown added tables, task lists, strikethrough and autolinks on top. Different tools implement different overlapping portions, which is why a document that renders correctly in one editor can look wrong in another.
This converter covers the CommonMark core — headings, paragraphs, emphasis, code spans and fences, lists including nesting, blockquotes, rules, links and images — plus the four GitHub extensions above. Not implemented: reference-style links, footnotes, definition lists, and setext headings underlined with equals signs. A document using one of those renders its source text rather than dropping it, so the gap is visible on screen instead of appearing as missing content later.
Two behaviors are worth knowing because they differ between tools. A single newline inside a paragraph is a space, not a line break, unless you end the line with two spaces — the optional switch here makes every newline a break, matching what chat applications do. And underscores inside a word do not create emphasis, so a snake_case_identifier survives intact, which the original implementation got wrong often enough to be a running joke.
Where the HTML Goes Next
One caution before publishing. Documentation examples are a notorious place for a real API key to sit in a code fence, because the person writing the example pasted a working one. Converting the document does nothing about that — if a live credential is in there, treat it as public and generate a replacement rather than editing the example and hoping.
Most conversions here end in one of three places: an email template, a CMS field that accepts HTML but not Markdown, or a static page. All three want the HTML source rather than the preview, which is why the copy button always copies the source regardless of which view is showing.
If the HTML is going into a JSON payload — a request body, a fixture, a CMS API call — it has to survive being embedded in a string, and unescaped quotes and newlines are the usual thing that breaks it. Formatting and validating that JSON after pasting catches the problem in seconds rather than at request time. If the destination expects the markup wrapped for transport, Base64 encoding it sidesteps the quoting question entirely, though it is an encoding step and not a security one.
The conversion runs both ways, and the return trip is the one that matters during a migration: converting existing HTML pages to Markdown is how documentation gets out of an old CMS and into a repository. Round-tripping is stable for what Markdown can express and lossy for layout markup, so it is a migration aid rather than a channel.
Two smaller things save time on documents headed for publication. Headings written by several people drift between title case and sentence case, and normalizing them in one pass is quicker than editing each one. And a link whose URL contains a space, a bracket or a non-Latin character will not survive as written — percent-encoding it first avoids a link that looks right in the Markdown and breaks in the HTML.
For laying out a template before the real copy exists, generating placeholder paragraphs gives you body text with realistic density to convert and drop in. And when two versions of a document render differently and it is not obvious why, diffing the two HTML outputs localizes the change far faster than comparing the Markdown, because the structural difference is explicit in the tags.
Important Edge Cases
- A single newline inside a paragraph becomes a space rather than a line break, unless the line ends with two spaces or the newline option is enabled.
- Underscores inside a word do not create emphasis, so snake_case identifiers are left alone.
- A link whose URL uses an unrecognized scheme renders as its literal source text rather than as a link, so nothing silently disappears.
- Text inside a fenced code block or a code span is never interpreted, including HTML tags and other Markdown syntax.
- A table needs its divider row of dashes to be recognized; without it the line is treated as an ordinary paragraph containing pipe characters.
Limitations
- Reference-style links, footnotes, definition lists, and setext headings are not implemented and render as source text.
- There is no syntax highlighting inside code blocks; a language class is added to the code element for a highlighter to use later.
- Turning off HTML escaping passes tags through unfiltered, which is unsafe for any document you did not write yourself.
- The output is plain semantic HTML with no styling, so it will inherit whatever CSS exists wherever you paste it.
- Input is capped at 500,000 characters, and very deeply nested lists are flattened beyond a few levels.
Input handling
Private Browser Processing
Your Markdown is converted in your browser by code shipped with this page. Nothing is uploaded, stored, or logged, and the rendered preview runs inside a sandboxed frame that cannot make requests or execute scripts.
Google Analytics records page visits and whether a tool finished or failed, but these tool implementations do not send field values, generated passwords, QR payloads, uploaded QR images, or camera frames to analytics or a Tiny Tiny Tools processing endpoint.
Safety note: Leave HTML escaping on for any document you did not write. Turning it off passes raw tags straight through, which is unsafe for user-submitted or third-party Markdown.
See the Privacy Policy for site-wide details.
Questions About This Tool
Why is my HTML showing as visible text?
Because escaping is on, which is the default. It is what stops a document you did not write from injecting tags. If the Markdown is your own and deliberately contains HTML, turn escaping off — but not for anything user-submitted.
Which flavour of Markdown is this?
The CommonMark core plus four GitHub extensions: tables, task lists, strikethrough and autolinks. Reference links, footnotes and definition lists are not implemented and render as their source text rather than disappearing.
Is the preview safe?
Yes. It renders inside an iframe with a sandbox attribute and no allow-scripts token, so scripts, forms and same-origin access are all disabled. The markup displays but cannot execute.
Why did my single line break disappear?
Markdown treats a single newline inside a paragraph as a space. End the line with two spaces for a hard break, or switch on the newline option to make every line break render as one.
Can it highlight code inside fenced blocks?
No. The language you write after the opening fence becomes a class on the code element, which is what a highlighting library expects, but no highlighting is applied here.
Is my document uploaded to convert it?
No. Conversion happens in your browser and the preview is sandboxed. There is no request while you convert, which the network tab will confirm.