Markdown Link Check

Check README links without touching the network: bad syntax, missing reference definitions, duplicate labels, empty targets and broken #anchors are reported with line and column numbers.

Try:
Link report

About this tool

Markdown Link Check scans a pasted Markdown document and reports link problems that are fully decidable offline. It does not fetch URLs, read your filesystem or upload the document anywhere; the same Rust engine runs in the CLI, chat block and browser page.

Use it before publishing a README, changelog or docs page to catch the mistakes that normal spell checkers miss:

Fenced code blocks and inline code spans are ignored, so examples in snippets do not create noise. Line and column numbers are 1-based.

Worked example

Input:

# Install

See [setup](#setup), [site](https://example.com), and [missing][ref].

[ref]: https://example.com/one
[ref]: https://example.com/two

Output:

Issues
  3:5  error  ML007  broken anchor '#setup' — no heading in this document produces that id
  6:1  error  ML005  duplicate reference definition [ref] — the first definition wins, this one is ignored

2 error(s), 0 warning(s) in 3 link(s) checked.

Controls

Limits and edge cases

FAQ

Does this replace a network link checker?

No. It catches local Markdown mistakes before a network checker runs: malformed syntax, duplicate reference definitions and broken in-document anchors. It deliberately does not request external URLs, so it is fast, private and deterministic, but it cannot tell whether https://example.com currently returns 200 or 404.

Why are some relative file links only listed as links, not errors?

A relative target such as ./docs/install.md may be valid in your repository, but the browser page cannot see that repository. The tool classifies it as a relative link and can include it in JSON or show_ok output, while leaving filesystem existence to your docs build or CI checkout.

Which heading anchor style is used?

GitHub-style slugs: text is lower-cased, punctuation is dropped, spaces become dashes and duplicate headings get numeric suffixes (#usage, then #usage-1). The scanner also honors explicit {#custom-id} suffixes and raw HTML id="..." / name="..." anchors.

How do I use the JSON output in CI?

Set report format to JSON and parse the errors count. A non-zero count means the document has structural link errors. Warnings are separated so you can decide whether missing image alt text or http:// links should fail your own pipeline.

Developer & Automation Access

Run it from the terminal

Same engine as this page, headless — via the gizza CLI:

gizza tool markdown-link-check "# Install

See [setup](#setup), [site](https://example.com), and [missing][ref].

[ref]: https://example.com/one
[ref]: https://example.com/two"

New to the CLI? Get gizza →

Open it by URL

Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:

https://gizza.ai/tools/markdown-link-check/?markdown=%23%20Install%0A%0ASee%20%5Bsetup%5D%28%23setup%29%2C%20%5Bsite%5D%28https%3A%2F%2Fexample.com%29%2C%20and%20%5Bmissing%5D%5Bref%5D.%0A%0A%5Bref%5D%3A%20https%3A%2F%2Fexample.com%2Fone%0A%5Bref%5D%3A%20https%3A%2F%2Fexample.com%2Ftwo&link_kind=all&report_format=text&show_ok=true&check_anchors=true&flag_insecure=true

Machine-readable descriptor: tool.json — title + parameters JSON Schema for agents.