HTML to Markdown
Turn a page into Markdown, tables and all
HTML Input
Markdown Output
What most HTML to Markdown converters get wrong
You want a page as Markdown — for a README, for notes, for a docs migration. The conversion itself is well-trodden: headings become hashes, <strong> becomes asterisks, links become brackets. Two things go wrong often enough to be worth naming, and both were measured on the library behind this page before the corrections below were added.
Tables usually vanish. The standard converter has no table rule at all, so a two-column table with one row of data comes out as four loose paragraphs — a, b, 1, 2 — with the structure gone entirely. This page emits GitHub Flavored Markdown pipe tables instead, using the same extractor as HTML Table to JSON, so colspan and rowspan are laid out properly here too rather than only on the table pages.
Script and style content leaks into the text. The tags get dropped but their contents do not — an inline <script> and a <style> block converted to alert(1)p{} sitting in the middle of the prose. Copy a real page out of a browser and you get JavaScript source and CSS rules in your document. Those elements are removed here, contents included.
Everything else follows CommonMark: ATX headings, fenced code blocks and hyphen bullets. The markup is parsed into an inert document and only read from — nothing in it executes, nothing it references is fetched, and none of it is ever rendered.
Converting a page
- Paste the HTML – A whole page or a fragment. To grab part of a page, right-click the section, Inspect, then copy the outer HTML of the element you want.
- Read the output as you go – Conversion runs as you type, so you can trim the input and watch the Markdown shrink with it — usually faster than cleaning up the output afterwards.
- Check the tables – The badge counts how many were converted. A pipe table needs a header row, so a table without one gets empty header cells rather than losing its columns.
- Copy or download – Download writes a
.mdfile. Nothing is uploaded and nothing in the markup is executed.
Copying from a rendered page rather than from view-source brings the site's wrapper with it — navigation, cookie banner, share buttons. Selecting just the article element in the inspector saves more cleanup than any converter option could.
A table that would otherwise disappear
The default behaviour of the underlying library turns this table into four stray paragraphs, and puts the inline script's source into the text. Here the table stays a table and the script does not survive.
<tr><th>msisdn</th><th>iccid</th><th>rsrp</th></tr> <tr><td>447700900142</td><td>8901240544102066246</td><td>-92</td></tr> <tr><td>447700900377</td><td colspan="2">Suspended</td></tr>
## Network status Cells reporting **below threshold** as of 09:15. | cellId | tac | rsrp | | --- | --- | --- | | 21453 | 4102 | -92 | | 21454 | Offline — maintenance | Offline — maintenance | # the script and style contents are gone
When you would use this
Moving documentation out of a CMS
Wikis and content systems export HTML; static-site generators and repositories want Markdown. This is the step between, and tables are usually the part that makes a bulk migration painful.
Turning a page into notes
An article you want to keep, in a form you can search, diff and edit — without the site wrapper and without the styling.
Writing a README from existing material
A specification table on a web page becomes a pipe table you can paste straight into a repository. Checking the result in an online markdown viewer is a quick way to catch a flavour difference, since renderers vary in how strict they are about table alignment.
Just getting the data
If the table is the only part you care about, HTML Table to JSON and HTML Table to CSV skip the prose entirely.
What it does
- Real GFM tables. Pipe tables with a header and divider row, not the loose paragraphs the default conversion produces.
- colspan and rowspan laid out correctly, using the same grid logic as the HTML table pages — a merged cell fills the positions it covers rather than shifting every later column.
- Script, style and noscript content is removed, contents included, so no JavaScript source ends up in your document.
- Pipes inside cells are escaped, so a value containing
|cannot silently end its column early. - ATX headings and fenced code blocks, which is what almost every Markdown renderer expects.
- Nothing renders, nothing runs, nothing uploads. The markup is parsed inertly and only read from.
Questions people actually ask
Is it safe to paste markup from a site I do not trust?
Yes. The HTML is parsed into a detached document, which the specification defines as inert — scripts do not run and referenced resources are not fetched. The output is Markdown text in an editor, and at no point is any of the markup inserted into this page.
Why does my table have an empty header row?
Because the source table had no <thead> and no row of <th> cells, and a GFM pipe table cannot exist without a header. The alternative would be dropping the table back to paragraphs, which loses the columns — an empty header row is the smaller cost and it is one line to fill in.
Can I get tables as something other than Markdown?
Yes — HTML Table to CSV for a spreadsheet, or HTML Table to JSON for code. Both use the same extraction as the tables here, so the columns come out the same way.
The output has a lot of navigation junk in it.
That came from the input. A page copied whole includes its menus, footers and cookie banner, because they are genuinely in the markup. Copying just the article element in the inspector is far quicker than deleting it afterwards.
What happens to images?
They become standard Markdown image references pointing at their original URLs. Nothing is downloaded, so a relative src stays relative and will need fixing if the document moves.
Related tools
Worth reading
- GitHub Flavored Markdown – The tables extension this page targets, and how strict renderers are about it
- CommonMark – The base specification everything else extends