scalpel@labs: ~/glossary/broken-link-checker.mdx5 sections

Broken Link Checker: Find Dead Links on a Page

A broken link checker requests each link on a page and reads its HTTP status code. A 404 means the page vanished; a 5xx means the server failed; a 2xx means it still works.

extension: Scalpel Linksupdated: 2026-08-14read_time: 3 min
less broken-link-checker.mdx

Why it matters

A 404 is a bad experience. Readers hit a wall. Crawlers waste budget on dead ends. Your site looks abandoned. Hand-checking 200 links takes an hour. A bulk checker takes seconds and tells you exactly which ones are dead.

That's the difference between knowing you have broken links and actually fixing them. Most sites accumulate dead links over years. A broken link checker is the baseline housekeeping that keeps a site healthy.

How it works

The checker requests each link and examines the HTTP status code:

2xx (success). The link works. Usually 200 OK, but 201, 202, and other 2xx codes all mean the page exists and is reachable.

3xx (redirect). The server sends you elsewhere. 301 is a permanent redirect (the page moved and won't come back). 302 is temporary (the page moved but might return). 307 and 308 are stricter variants. A redirect chain (A → B → C) works but wastes roundtrips. A checker flags long chains.

4xx (client error). You asked for something that doesn't exist or isn't allowed. 404 means the page is gone. 403 means forbidden (you don't have permission). 400 means the request was malformed. Most 4xx codes are dead links or permission issues.

5xx (server error). The server failed. 500 is a generic server error. 503 is temporarily unavailable (often a sign the server is overloaded). These are transient; a retry minutes later might succeed.

A polite checker uses HEAD requests first (just headers, no body). Some servers reject HEAD with 405 or 501, so a fallback to GET handles those cases. The checker also respects rate limits: firing 500 requests at once hammers the target server. A good checker limits parallel requests to 3–8 and backs off if responses slow down.

What does not matter

Every transient 5xx is a break. Server errors happen. A 503 on a first check might be 200 on a retry. A good checker reports the problem but doesn't alarm; transient errors are often temporary maintenance.

Redirects as failures. A 301 redirect is not a broken link; it's a working one with a detour. Crawlers follow redirects fine. Long redirect chains are less efficient (each hop adds latency), but a chain of two or three is normal and not a problem.

Credentials or authentication. A checker can't submit a login form or cookie. A link behind auth will return 401 or 403 from the checker's perspective, but the link works fine for logged-in users. That's not a defect in the link; it's a limitation of the check.

Code example

Checking a batch of links:

<!-- These links exist -->
<a href="https://example.com/about">About us</a>
<!-- Returns 200 -->

<a href="https://example.com/old-page">Old page</a>
<!-- Returns 301 to https://example.com/new-page -->

<!-- This link is dead -->
<a href="https://example.com/vanished">A deleted page</a>
<!-- Returns 404 -->

<!-- This is behind authentication -->
<a href="https://example.com/private">Private area</a>
<!-- Returns 401 Unauthorized (not a broken link, just auth-protected) -->

A checker would report:

  • /about200 OK (good)
  • /old-page301 moved to /new-page (working, not broken)
  • /vanished404 Not Found (broken)
  • /private401 Unauthorized (auth-protected, not broken)

In the link list, a "Check links" button runs the checker. Tick which links to check (or check all), click the button, and the checker requests each one. As requests complete, the link's status appears: a green checkmark for 2xx, a yellow arrow for 3xx redirects, a red X for 4xx, and an orange warning for 5xx.

The status code is shown in parentheses: (200), (301), (404), etc. Click a broken link to see more detail: the exact code, the target domain, and any error message from the server.

The checker respects your network: it limits concurrent requests and backs off if the target server gets slow. Nothing is sent to a server about the page you're auditing; only the link targets are requested.

Sources