Markdown link checker

Updated

Paste a README or any markdown document and get every link listed with its line number — then check the external ones for dead pages and redirects, catch #anchors that no heading produces, and spot duplicate or undefined reference links before you publish.

1 ok0 redirected2 broken3 skipped6 unchecked
Links found: 12
LineKindTextURLResult
3linkinstallation guide#installation
anchor found
3linkAPI reference#api-reference
anchor missing

no heading produces #api-reference

7linkGitHubhttps://github.com/vercel/next.js
pending
8linkdocshttps://nextjs.org/docs
pending
9autolinkhttps://example.com/this-page-does-not-exist-404https://example.com/this-page-does-not-exist-404
pending
11bare URLhttp://github.com/vercel/next.jshttp://github.com/vercel/next.js
pending
15linkconfig.md./docs/config.md#options
relative — can't check from here
15autolinkmailto:team@example.commailto:team@example.com
not checked
17referencechangeloghttps://github.com/vercel/next.js/releases
pending
17referenceroadmap
undefined reference

no [roadmap]: url line

19imageArchitecture./images/architecture.png
relative — can't check from here
21linkNext.js docshttps://nextjs.org/docs
pendingduplicate

Parsing and anchor checks run in your browser. Only the external http(s) URLs are sent to docs-md.com's server, which fetches them on your behalf — your document text is never uploaded. Relative paths and mailto links are listed but not fetched.

Which kinds of links does the checker find?

All six ways a URL can appear in markdown: inline links [text](url), images ![alt](src), reference-style links [text][id] together with their [id]: url definitions, autolinks in angle brackets, bare URLs that GitHub turns into links automatically, and HTML <a href> or <img src> tags. Anything inside a fenced code block or inline backticks is ignored, since it is not rendered as a link.

What does each result mean?

  • 2xx, green — the page answered. 3xx, amber — it redirects; the final address is shown so you can update the link.
  • 4xx / 5xx, red — the page is missing, forbidden, or the server failed. 404 is a genuinely dead link; 403 often means the site blocks link checkers (see the FAQ).
  • Anchor missing — a #slug link that no heading in the document produces. The table of contents generator builds correct anchors from your headings.
  • Undefined reference[text][id] with no [id]: url line, which renders as literal brackets. The link generator writes reference links with matching definitions.
  • Duplicate — the same URL appears more than once; fine in prose, but in a link list it usually means a copy-paste slip.

How do I keep links from breaking in the first place?

Prefer permanent URLs (release pages, tagged docs) over “latest” links, link to headings by their generated slug rather than a guessed one, and keep reference definitions at the bottom of the file where they are easy to audit. Run the check again after editing: every problem row is clickable and selects the offending line in the editor. For a repository, add a link checker to CI as well — this page is for the quick pass before you commit.

What is sent to the server when I check links?

Only the list of external http(s) URLs. Parsing, anchor verification, duplicate detection, and reference checks all run in your browser; the markdown text itself never leaves your machine. The server fetches each URL once (HEAD, then GET if needed) and returns the status code.

Why does a link that works in my browser show 403 or an error here?

Some sites (Cloudflare-protected pages, LinkedIn, some publishers) block automated requests or answer HEAD requests with 403 or 405. The checker retries with GET, but a site that refuses non-browser traffic will still report an error. Treat a 403 on a page you know is public as "blocked by the site", not as a dead link.

How are #anchor links verified?

The checker builds the same heading slugs GitHub does (via github-slugger): lowercase, spaces to hyphens, punctuation dropped, and -1, -2 suffixes on duplicates. A link like #getting-started passes when a heading produces that slug, or when an explicit HTML id or name attribute defines it.

Why are relative links like ./docs/setup.md not checked?

The tool only sees the one document you pasted, so it cannot know whether a sibling file exists in your repository. Relative links are listed with their line numbers so you can verify them where the files live; anchors within the same document are checked.

Does a redirect count as broken?

No. A 301 or 302 is shown in amber with the final URL so you can decide whether to update the link. Permanent redirects are worth fixing in a README because each hop adds latency and some renderers refuse to follow them.

Is there a limit on how many links I can check?

Up to 100 unique external URLs per run, checked in batches of 25 with an 8-second timeout each, and 20 runs per 10 minutes per IP address. That covers a long README comfortably.

More markdown tools