FIRST CH TOOLS / Text / 57 HTML → Markdown
HTML → Markdown
Paste a page's HTML on the left and the Markdown appears on the right. Headings, lists, tables, links, images and code blocks are converted; script, style and presentational div / span wrappers are dropped. For moving existing web copy into Markdown, and for tidying up a page an agent has just fetched.
Paste and it converts as you type
The HTML you paste never leaves your browser — it is parsed and rebuilt on this page. Loading a file reads it locally; nothing is uploaded. Directly callable via URL parameters: /en/html-md/?html=%3Ch1%3EA%3C%2Fh1%3E / /en/html-md/?main=1&base=https://example.com/
What gets lost on the way to Markdown
Merged cells (colspan / rowspan) cannot be written
<td colspan="2">Total</td> | Total | | ← nothing to do but pad with an empty cell
Markdown tables have no merged cells. This tool fills a colspan with empty cells, writes a rowspan value on its first row only, and reports how many cells were affected. When the merging carries meaning — a two-level header on a summary table — either choose leave tables as HTML or redesign the table.
A cell cannot hold a list or a code block
<td><ul><li>A</li><li>B</li></ul></td>
A row of a Markdown table must fit on one line, so a cell can only hold inline content: emphasis, links, code spans. When a cell contains a list, a table, a code block or a quote, this tool leaves that whole table as HTML rather than emit a table that breaks halfway. A <br> inside a cell stays written as <br>.
Tables, task lists and strikethrough are not in CommonMark
| a | b | ← a GitHub (GFM) extension - [x] done ← a GFM extension ~~struck~~ ← a GFM extension
The Markdown standard (CommonMark) has no tables. Tables, task lists, strikethrough and autolinks are GitHub Flavored Markdown extensions, supported by GitHub, GitLab, Slack, Notion, Obsidian and most static site generators. If the destination only reads CommonMark, turn GFM off — tables stay as HTML and strikethrough stays as <del>.
Definition lists (dl / dt / dd) have no equivalent
**HTML** : HyperText Markup Language
This tool writes a <dl> as a bold term followed by a colon line. That is the Markdown Extra definition-list syntax, which is in neither CommonMark nor GFM, so a plain renderer will print the colon literally. Convert them to bullet lists if that bothers you.
sup / sub / mark stay as HTML (and some sites strip them)
m<sup>2</sup> / <mark>highlight</mark>
Superscript, subscript and highlighting have no Markdown syntax, so they are kept as HTML tags by default. But GitHub READMEs and npm descriptions sanitise the HTML they render and remove some of these. If they matter, set "No Markdown equivalent" to text only. <iframe>, <video> and <svg> are treated the same way.
Relative URLs always break somewhere else
<a href="/about/"> → [About](/about/) ← 404 on another site with a base URL → [About](https://example.com/about/)
The HTML you fetched is full of relative paths such as /about/ and ../img/a.png. Paste that Markdown anywhere else and the links and images point at nothing. Put the page's own address in Base URL and they are rewritten as absolute URLs; anchors (#name) and URLs that are already absolute are left alone. The number of remaining relative paths is reported under "What was read".
<br> becomes two trailing spaces — which you cannot see
line one·· ← "··" is two spaces, and that is the line break line two
A line break inside a paragraph is written as two spaces at the end of the line. They are invisible, and an editor set to "trim trailing whitespace on save" deletes them silently, joining the two lines. To keep them, switch the <br> style to a trailing backslash (CommonMark) or leave <br> as it is.
class, style and id are dropped (appearance is not preserved)
<p class="lead" style="color:#c8501f">Body</p> → Body
Markdown describes structure, not appearance. Classes, inline styles, colours, font sizes and centring all disappear. The one exception is column alignment in tables: the align attribute and text-align are read and written as :---:. Layout <div> and <span> wrappers are unwrapped and their content kept.
Navigation, headers and footers come along for the ride
A whole page → menus, breadcrumbs and footer text end up in the body
Paste a whole page and the global navigation and footer become Markdown too. "Main content only" keeps just what is inside <main> or <article> and drops header, nav, footer, aside and form. script, style and anything carrying hidden or display:none are removed regardless of that setting.
Ordinary punctuation turns into syntax
2 * 3 = 6 → 2 \* 3 = 6 [note 1] → \[note 1\]
If the prose contains *, _, [, `, or a line starting with #, - or 1., Markdown reads it as markup. This tool escapes them with a backslash — except for an underscore in the middle of a word (snake_case), which stays readable as it is. Turn "Escape Markdown characters" off if you would rather keep the text bare.
Heading levels are left exactly as they were
a page that starts at <h2> → Markdown that starts at ##
On many sites the h1 is the logo and the article starts at h2. This tool does not shift levels: doing so would break any page that legitimately has two h1 elements. Adjust the number of # afterwards to suit the destination.
Broken HTML does not stop it
<a href="x>link</a> ← the quote is never closed
This tool does not use the browser DOM (DOMParser or innerHTML); it parses the HTML itself. Unclosed elements are closed at the end and stray closing tags are dropped, the way a browser does. An attribute whose quote is never closed stops the tag there and is reported, because carrying on would swallow the rest of the document as one attribute value. Whatever was patched up is always listed under "What was read".
Supported: headings (h1–h6), paragraphs, line breaks, emphasis (strong / b / em / i), strikethrough (del / s), code (code / pre, with the language taken from class="language-*"), block quotes, horizontal rules, lists (ul / ol, nested, the start attribute, checkboxes), tables (thead / tbody / caption / align), links (a, optionally reference style), images (img, alt and title), definition lists (dl), figure / figcaption and details / summary.
How to Use
- Paste the HTMLPage source, HTML copied from devtools, or the body field out of a CMS — into the box on the left. You can also drop an .html file onto it.
- Set it up for the destinationTick "Main content only" when you pasted a whole page, and put the page's address in "Base URL" so links and images become absolute.
- Copy the MarkdownThe result appears on the right. Copy it or save it as .md. Anything left as HTML, and every table that could not be converted, is listed under "What was read".
About This Tool
The HTML is not parsed by the browser. Tools like this normally read HTML with DOMParser or innerHTML; this one carries its own tokeniser and tree builder. There are two reasons. First, the same logic runs inside an MCP server on Node.js, where there is no DOM — depending on one would make the browser and the agent disagree. Second, safety: putting pasted HTML into innerHTML lets things like <img onerror> execute on this page. An implementation that only parses never runs what you paste.
Broken HTML still produces a result. Real pages are full of unclosed <li> and <p> elements, closing tags with nothing to close, and unterminated quotes. Like a browser, this tool closes what was left open and discards stray closing tags and carries on — but it does not do so silently: the counts appear under "What was read". The one case it refuses to guess is an unterminated attribute quote, because continuing would swallow the rest of the document as a single attribute value.
Whatever Markdown cannot express is reported, not quietly dropped. Merged cells, definition lists, superscripts, iframes — there will always be elements with no Markdown equivalent. This tool lets you choose between keeping them as HTML, reducing them to text and removing them, and then tells you what happened every time. In a migration the dangerous outcome is not a failed conversion; it is losing something and not noticing until it is published.
Relative URLs are the most common casualty. A link to /about/ works perfectly inside its own page and points somewhere else entirely once the Markdown lands in a repository README or another domain's CMS. Give the tool a base URL and links and images are rewritten as absolute URLs, leaving anchors and already-absolute URLs untouched.
It is also a post-processing step for agents. Feeding raw HTML to an LLM spends most of the tokens on tags and attributes. Extracting the main content as Markdown usually cuts the length to a fraction of that while keeping the headings and tables intact. The same conversion is available as the MCP tool html_to_markdown, so an agent can call it without opening a browser.
Going the other way, Markdown → PDF and Marp Markdown → Slides turn Markdown into something you can hand over. For tables alone see Markdown Table Formatter, and for the special characters themselves see HTML Entity Escape.
From AI Agents
This conversion is also available as the html_to_markdown tool of the MCP (Model Context Protocol) server @first-ch/tools-mcp, so an AI agent can call it directly instead of driving a browser. Hand it the HTML of a page you fetched and it returns the main content as Markdown (it never touches the network itself — fetching stays on the agent's side). See Using these tools from AI agents for setup.
Install
claude mcp add firstch-tools -- npx -y @first-ch/tools-mcp
Examples
# An HTML fragment to Markdown html_to_markdown(html="<h1>Title</h1><p>Body</p>") # Keep the article only and make relative URLs absolute html_to_markdown(path="/tmp/page.html", main_only=true, base_url="https://example.com/blog/1/") # Prose only, for summarising: no links, no images html_to_markdown(html="...", links="strip", images="drop") # For a CommonMark-only destination (tables stay as HTML) html_to_markdown(path="/tmp/page.html", gfm=false, outputPath="/tmp/page.md")
Other Tools
- 01WebP Converter画像→WebP一括変換
- 02White Background RemoverWhite BG Remover
- 03WCAG Contrast CheckerContrast Checker
- 04Character CounterCharacter Counter
- 05llms.txt Generatorllms.txt Generator
- 06JSON-LD GeneratorJSON-LD Generator
- 07Markdown → PDFMD → PDF
- 08OGP Meta Tag WizardOGP Wizard
- 09Favicon GeneratorFavicon Generator
- 10TikTok PublisherTikTok Publisher
- 11Encoding & Line Ending ConverterEncoding Converter
- 12Batch Image → AVIF ConverterAVIF Converter
- 13Test Data GeneratorTest Data Generator
- 14Marp Markdown → SlidesMarp Slides
- 15Text & Code Diff CheckerDiff Checker
- 16Cron Expression ExplainerCron Explainer
- 17Base64 & Data URI EncoderBase64 & Data URI
- 18URL Parameter Editor & UTM BuilderURL Parameters
- 19HTML Entity Escape & UnescapeHTML Escape
- 20JSON ⇄ YAML ConverterJSON ⇄ YAML
- 21PX ⇄ REM / EM ConverterPX ⇄ REM / EM 単位変換
- 22Color Converter & AlphaColorコード変換&アルファ透過
- 23MD5 / SHA-256 Hash Generatorハッシュ生成
- 24JWT Decoder & Expiry CheckerJWTデコーダー&有効期限チェッカー
- 25User-Agent ParserUser-Agent解析&デバイス判定
- 26UUID & ULID GeneratorUUID (v4) & ULID 一括生成
- 27Aspect Ratio Calculatorアスペクト比計算&サイズ算出
- 28Markdown Table & CSV/TSV ConverterMarkdownテーブル整形&CSV/TSV変換
- 29SQL Query FormatterSQLクエリフォーマッター&整形
- 30QR Code GeneratorQR Code Generator
- 31Regex Tester正規表現テスター
- 32Unix Timestamp ConverterUNIXタイムスタンプ⇄日時変換
- 33New Tab Memo新規タブメモ帳
- 34Image Resizer & Cropper画像リサイズ&クロップ
- 35EXIF Viewer & RemoverEXIF情報の確認&除去
- 36robots.txt Generatorrobots.txt ジェネレーター
- 37Password Generator安全なパスワード生成
- 38Case Converter文字列ケース変換
- 39CSV/TSV ⇄ JSON ConverterCSV/TSV ⇄ JSON 相互変換
- 40PDF Merge, Split & ExtractPDF結合・分割・ページ抽出
- 41Full-width ⇄ Half-width Converter全角⇄半角変換&テキストクリーナー
- 42X (Twitter) Post CounterX(Twitter)投稿の文字ウェイト計算
- 43CSS clamp() Fluid Typography CalculatorCSS clamp() 計算機
- 44CSS Gradient GeneratorCSSグラデーションジェネレーター
- 45Image Colour Palette Extractor画像からカラーパレット抽出
- 46QR Code ReaderQRコード読み取り
- 47SVG Optimizer & Data URISVG最適化&data URI化
- 48Redirect Generatorリダイレクトルール ジェネレーター
- 49IP / CIDR CalculatorIPアドレス・CIDR計算機
- 50ICS Calendar Event GeneratorICS Generator
- 51cubic-bezier Easing Preview & ComparisonEasing Preview
- 52CSS box-shadow Generatorbox-shadow ジェネレーター
- 53Japanese Dummy Text Generator和文ダミーテキスト生成
- 54Social Media Image ResizerSNS画像サイズ一括書き出し
- 55Time Zone Converter & World Clockタイムゾーン変換・世界時計
- 56Date & Business Day Calculator日数・営業日計算