Skip to content
Encoding2026-05-186 min read

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)

TraitHTMLMarkdown
Syntax complexityHigh (nested tags)Low (plain text)
Source readabilityMediumHigh
Styling / layoutFullAlmost none
Version control / diffNoisyFriendly
Typical usePages, email HTMLREADMEs, 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

  1. Blogs / static sites: Hugo, Jekyll, and many CMSes treat Markdown as source
  2. GitHub READMEs: lift structure from marketing HTML into the repo
  3. Email and forums: Markdown drafts ↔ pasteable HTML fragments
  4. Doc migration: rich-text export → maintainable .md
  5. API docs: OpenAPI description fields often allow Markdown

How to Use This Tool (UI truth)

Open the HTML/Markdown converter:

  1. Edit HTML on the left and Markdown on the right (two source editors—not a single auto-detect box)
  2. Click to Markdown: HTML → Markdown (Turndown)
  3. Click to HTML: Markdown → HTML (marked)
  4. 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 include gfm: 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
  • breaks defaults 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:

CapabilityStrict CommonMarkGFM (this site’s converter + preview)
Pipe tablesNoYes (both directions)
Task listsNoYes
StrikethroughNoYes
AutolinksLimitedMore aggressive

When dialects disagree, confirm the destination enables GFM before rewriting by hand or regenerating tables.

Safety Boundaries

  1. The converter treats HTML as editable text, not a sanitized preview sandbox
  2. HTML strings from marked may contain tags; if you paste them into production with innerHTML / unsanitized templates, you need your own allowlist or sanitizer
  3. For user-visible rendering, prefer Markdown Preview’s React path (see XSS notes in the preview guide)
  4. 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 &nbsp;, curly quotes, or &amp;. 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;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

  1. Convert a sample that includes a heading, list, link, fenced code block, and (if you care) a table
  2. Paste Markdown into preview; confirm structure
  3. If the table vanished on HTML→MD, rebuild with the table generator
  4. Diff against the previous revision of the doc before merging

Batch Pipeline Principles

  1. Idempotency: re-runs must not double-escape entities or re-wrap fences
  2. Sample Diff first: convert into a sibling directory; spot-check ~10 files with Text Diff
  3. Quarantine failures: isolate bad files instead of aborting the batch and silently dropping work
  4. 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?

NeedTool
See final GFM layoutMarkdown Preview
Obtain the other format as source textHTML ↔ Markdown
Author/import tablesTable generator

Further Reading


Written and maintained by ToolVault. The homepage collects more browser-local tools.