Online HTML/Markdown Converter: Convert Between Document Formats
The Conversion Problem
HTML and Markdown both describe document structure, but they are not equal: HTML carries classes, merged cells, forms, and arbitrary nesting; Markdown deliberately keeps readable semantics. Conversion moves structure, not pixel-perfect styling.
Paste fragments into the HTML ↔ Markdown converter, then verify rendering with Markdown Preview when needed.
Markdown example
# Heading
## Subheading
This is **bold** and *italic* text.
- List item 1
- List item 2
[Link text](https://example.com)
`inline code`
HTML vs Markdown (selection intuition)
| Trait | HTML | Markdown |
|---|---|---|
| Syntax complexity | High (nested tags) | Low (plain text) |
| Source readability | Medium | High |
| Styling / layout | Full | Almost none |
| Version control / diff | Noisy | Friendly |
| Typical use | Pages, email HTML | READMEs, blog sources, notes |
To compare two conversion outputs or configs, use Text Diff. For structured data, use JSON/YAML tools—do not expect Markdown to preserve object semantics.
Why Convert
- Blogs / static sites: Hugo, Jekyll, and many CMSes treat Markdown as source
- GitHub READMEs: lift structure from marketing HTML into the repo
- Email and forums: Markdown drafts ↔ pasteable HTML fragments
- Doc migration: rich-text export → maintainable
.md - API docs: OpenAPI description fields often allow Markdown
How to Use This Tool (UI truth)
Open the HTML/Markdown converter:
- Edit HTML on the left and Markdown on the right (two source editors—not a single auto-detect box)
- Click to Markdown: HTML → Markdown (Turndown)
- Click to HTML: Markdown → HTML (marked)
- When Markdown has content, copy/clear from the toolbar; errors appear below the workspace
The tool does not auto-detect format on paste—you must click the matching button. If older copy said “auto-detect,” trust the current UI.
Implementation Notes: Turndown and marked
From src/tools/HtmlMarkdownTool.tsx:
HTML → Markdown (Turndown + GFM)
Logic lives in src/utils/tools/html-markdown.ts:
const turndownService = new TurndownService({
headingStyle: 'atx',
codeBlockStyle: 'fenced',
});
turndownService.use(gfm); // turndown-plugin-gfm: tables / strikethrough / task lists
- GFM plugin enabled: common HTML
<table>elements become pipe tables|...| <del>, task-list checkboxes, and related GFM tags are handled by the plugin- Merged cells / complex
colspan/rowspan/ styled layouts still drop or degrade—use the Markdown table generator when you need full control
Markdown → HTML (marked)
- Calls
marked.parse(markdown); current marked defaults includegfm: true - MD→HTML supports GFM tables, task lists, strikethrough, and friends
- Output is a string written into the HTML editor; this page does not execute that string as preview DOM
breaksdefaults to false: a single newline usually does not become<br>
Round-trip HTML → MD → HTML
Simple pipe tables round-trip; you still get a semantically approximate, style-stripped version: classes/ids, complex layouts, merged cells, and form controls disappear or warp.
Habit: after converting, paste Markdown into preview (react-markdown + remark-gfm) and confirm the structures you care about—especially tables.
How CommonMark / GFM Change the Answer
Which Markdown you target decides conversion and acceptance criteria:
| Capability | Strict CommonMark | GFM (this site’s converter + preview) |
|---|---|---|
| Pipe tables | No | Yes (both directions) |
| Task lists | No | Yes |
| Strikethrough | No | Yes |
| Autolinks | Limited | More aggressive |
When dialects disagree, confirm the destination enables GFM before rewriting by hand or regenerating tables.
Safety Boundaries
- The converter treats HTML as editable text, not a sanitized preview sandbox
- HTML strings from
markedmay contain tags; if you paste them into production withinnerHTML/ unsanitized templates, you need your own allowlist or sanitizer - For user-visible rendering, prefer Markdown Preview’s React path (see XSS notes in the preview guide)
- When user text enters HTML attributes or mixed markup, use the HTML entity encoder and the entity guide
Same Family in Code
JavaScript (same libraries as this site)
const TurndownService = require('turndown');
const { marked } = require('marked');
const turndown = new TurndownService({
headingStyle: 'atx',
codeBlockStyle: 'fenced',
});
const markdown = turndown.turndown('<h1>Heading</h1><p>Content</p>');
const html = marked.parse('**bold** and *italic*');
In production, add the GFM plugins and HTML sanitization you need—do not assume defaults equal this UI.
Python (illustrative)
import markdown
import html2text
html = markdown.markdown('# Heading\n\n**Bold** content', extensions=['tables'])
h = html2text.HTML2Text()
h.ignore_links = False
markdown_text = h.handle('<h1>Heading</h1><p>Content</p>')
Pitfalls That Look Like “Converter Bugs”
Entities and smart punctuation
CMS HTML often contains , curly quotes, or &. Turndown may keep some as characters and some as entities depending on the DOM path. If Markdown later goes through another HTML escape step, you can get double-encoded &amp;. Spot-check with Text Diff against a known-good snippet; use the HTML entity encoder when you intentionally need entity forms.
Images and relative URLs
<img src="/media/a.png"> becomes Markdown that still points at /media/a.png. That is correct relative to the original site and wrong relative to a Git repo root. Conversion does not download binaries—you still own path rewriting.
“Lossless MD→HTML” is about structure, not CSS
Every CommonMark/GFM construct maps to some HTML, but class names, inline styles, and layout wrappers never come back from a Markdown round trip. Do not use this tool as a CSS-preserving pretty-printer.
Preview vs converter disagreement
Markdown Preview uses react-markdown + remark-gfm. The converter’s MD→HTML path uses marked. Both speak GFM, yet attribute ordering, list tight/loose wrapping, and autolink edge cases can differ. When they disagree, decide which stack your destination uses—do not assume ToolVault preview ≡ marked string ≡ GitHub.
Thirty-second acceptance checklist
- Convert a sample that includes a heading, list, link, fenced code block, and (if you care) a table
- Paste Markdown into preview; confirm structure
- If the table vanished on HTML→MD, rebuild with the table generator
- Diff against the previous revision of the doc before merging
Batch Pipeline Principles
- Idempotency: re-runs must not double-escape entities or re-wrap fences
- Sample Diff first: convert into a sibling directory; spot-check ~10 files with Text Diff
- Quarantine failures: isolate bad files instead of aborting the batch and silently dropping work
- Keep HTML read-only: when a conversion bug appears months later, re-running from source beats editing corrupted Markdown
If the payload is really YAML/JSON, use YAML ↔ JSON / JSON formatter—not HTML↔Markdown.
FAQ
Is there one Markdown standard?
Not one behavior everywhere. CommonMark constrains the core; GFM is the de facto docs superset; wikis add private extensions. Pin the target dialect before converting.
Do tables exist in “standard” Markdown?
Strict CommonMark core has no pipe tables; GFM does. This site’s MD→HTML (marked) and HTML→MD (Turndown + GFM plugin) both handle common pipe tables; merged cells and complex layouts may still degrade.
Are styles preserved?
No. CSS, floats, positioning, and most classes do not become Markdown. What remains is structural signal: heading levels, lists, links, emphasis.
How does this split with preview?
| Need | Tool |
|---|---|
| See final GFM layout | Markdown Preview |
| Obtain the other format as source text | HTML ↔ Markdown |
| Author/import tables | Table generator |
Further Reading
- Markdown preview guide — remark-gfm, safe rendering, pitfalls
- Markdown table generator guide — pipe syntax and generator behavior
- YAML ↔ JSON guide — configs do not belong in HTML conversion
- JSON formatting guide — tidy example JSON before it enters docs
- Text Diff guide — sample before/after conversion
- HTML entity encoder guide — escaping when embedding into HTML
Written and maintained by ToolVault. The homepage collects more browser-local tools.
Related Tools
Related Articles
PDF to JPG: How to Pick the Right Resolution (DPI Guide + 3 Ways)
A complete guide to converting PDF pages to JPG: how DPI maps to sharpness, two-page and batch conversion, three approaches compared (in-browser local, command line, desktop software), plus a quality settings cheat sheet.
PDF Too Large for Email? How to Choose the Right Compression Quality (3 Local Levels)
How PDF compression works: lossy rasterization vs. lossless structure optimization, which of the three quality levels fits which use, and how to compare sizes before and after — entirely in your browser.
How to Split a PDF and Extract Pages: Range Syntax, Common Cases, and a Local Workflow
A complete guide to splitting PDFs by page range: the 1-3,5 range syntax, page-by-page extraction, and split-then-merge workflows — all in your browser, nothing uploaded.