Check Markdown structure before publishing

Paste a README or a documentation draft to see its heading outline and what the checker found: heading jumps, repeated anchors, unclosed code fences, empty or unresolved links and trailing whitespace. Markdown is read as text here, never rendered, and no link is opened.

Runs locally in your browser
This tool processes all data locally in your browser.
Markdown sourceChecks structural issues without rendering, uploading or opening links.

How to check a Markdown document before publishing

The checker reads the Markdown you paste as text and answers with three things: the heading outline, the counters for headings, links and code fences, and the structural findings it can prove from the source. It never renders the document, never uploads it and never opens a link, so a draft that is not ready to share can be checked in place.

Everything runs on the page. In a measured session the only requests that left the browser were the site's own analytics: the draft, the links and the outline stayed in the tab, which is also why the checker keeps working with the network disconnected.

  1. Paste the README, guide or documentation draft into Markdown source, or press Load example to start from a document that already contains a repeated heading and an empty link.
  2. Press Check Markdown. The outline lists every heading with the anchor it generates and its line number, the report lists what each rule found, and the counters show the heading, link and code fence totals.
  3. Read the findings from the top: a heading level jump, a heading anchor used twice, an unclosed fenced code block, a link with empty text or no destination, a reference link whose definition is missing, a line ending in whitespace that is not the two-space hard break, a heading marker with no space after it, and a document with no level-one heading.
  4. Press Copy for the plain-text report, or Download to save it as markdown-report.txt next to the source file.
  5. Press Clear to empty both panes before the next document.

What the checker reads, and what it leaves alone

What counts as a link

Inline links are counted with an optional title, as in [text](https://example.com "title"), and with one level of parentheses inside the destination, which is what Wikipedia-style URLs need. Reference links count when the document defines the label anywhere: the full form [text][ref], the collapsed form [text][] and the shortcut form [ref] all resolve against a line such as [ref]: https://example.com, with or without a title. Autolinks — <https://example.com> and <mailto:docs@example.com> — count as well.

Three things that look like links are deliberately left out: images written as ![alt](image.png), link syntax inside inline code such as `[text](url)`, and HTML tags such as <a href="https://example.com">, which are markup rather than autolinks. A reference link whose definition is missing is reported instead of being counted.

How headings, fences and front matter are read

Both heading styles are recognised: ATX (# to ######, with up to three spaces of indentation and an optional closing run of #) and setext (a paragraph line underlined with ==== for level one or ---- for level two). Anchors are generated the way static site generators do it — lower case, punctuation dropped, spaces turned into hyphens — so “Install now!” and “Install now?” collide on #install-now, and the second one is reported as a repeated anchor.

A fenced block opened with ``` or ~~~ hides its content from every other rule, and a closing fence at least as long as the opening one closes it; an unclosed block is reported on the line where it opened. A document that starts with a --- line is read as YAML front matter up to the next --- or ... line, so the colons, brackets and trailing spaces of the metadata are not reported as prose.

What the checker does not do

It does not render Markdown, so it cannot show how the page will look, and it does not request link targets, so an unreachable URL is never reported. It checks the rules listed here and nothing else: line length, list marker style, blank lines around blocks, table alignment and the other style rules of a full linter are out of scope, and a code block indented by four spaces is read as ordinary text rather than code.

A 4000-line document holding 4000 links was analysed in about 0.6 s in a desktop browser, and the work happens when you press the button rather than while you type. For a check across a whole repository with a fixed rule set, a command-line linter remains the better tool; this page answers for one draft, without uploading it.

Recent tools: