Broken Internal URLs: How to Find and Fix Them at Scale

No Comments
Broken internal urls: how to find and fix them at scale

What this check flags

This check fires when a page links to another URL on your own domain that returns a 4xx or 5xx status, so the link is dead. Broken internal links waste crawl budget, leak the link equity you meant to pass, and drop visitors onto error pages, which is why they are worth hunting down and fixing at scale rather than one at a time.

What a broken internal link looks like

The link itself is ordinary HTML; the problem is what sits at the other end. Here is a snippet that passes markup validation but is broken in practice:

<!-- href resolves, but the target returns 404 -->
<a href="/guides/onboarding-checklist/">Onboarding checklist</a>

<!-- typo in the slug -->
<a href="/blog/2024/pricing-guide">Pricing guide</a>   <!-- real slug is /pricing-guide-2024/ -->

<!-- points at an old path that now 500s -->
<a href="/legacy/report.aspx?id=42">Full report</a>

You cannot tell any of these are broken by reading the HTML; you have to request each target and check the status code. A quick command-line probe confirms it:

curl -o /dev/null -s -w "%{http_code}  %{url_effective}n" 
  https://example.com/guides/onboarding-checklist/
# 404  https://example.com/guides/onboarding-checklist/

Once you have the status, the fix depends on why it broke: repoint the link to the live URL, restore or 301-redirect the moved page, or remove the link if the destination is genuinely gone. Never leave the link pointing at a 404.

Break type, cause, and the right fix

StatusTypical causeCorrect fix
404 / 410Page moved or deleted; slug typoRepoint link to live URL, or 301 the old path
403Auth or permission rule blocking botsUnblock the URL, or link to a public equivalent
500 / 503Server error or dependency downFix the endpoint; do not mask it with a redirect
Soft 404 (200 on an empty page)Missing content returned as OKReturn a real 404/410 or restore content, then relink
Redirect chain to a 404Old redirect now lands on a dead pagePoint the link at the final live URL directly

How to detect it on your own site

  1. Screaming Frog. Crawl the whole site, filter Response Codes to Client Error (4xx) and Server Error (5xx), then for each broken URL open the lower Inlinks pane to see exactly which pages link to it. Export Bulk Export > Response Codes > Internal > Client Error Inlinks to get a page-by-page fix list.
  2. curl in a loop. Feed a list of internal URLs through curl -o /dev/null -s -w "%{http_code} %{url_effective}n" to batch-check status codes without a GUI, useful in CI or a pre-deploy script.
  3. Search Console. The Pages (Indexing) report surfaces Not found (404) URLs Google has tried to crawl, and the Referring page detail shows where the link came from, which corroborates your crawl data with real Googlebot activity.

How to fix it

  1. Build one list of broken internal targets with their status codes and the pages that link to them.
  2. Group by cause: typos, moved pages, deleted pages, and genuine server errors each get a different fix.
  3. For moved content, update the link to the current URL. Do not rely on a redirect to paper over an internal link you control; point it straight at the destination.
  4. For deleted content, either remove the link or send it to the closest relevant live page.
  5. For server errors, fix the endpoint rather than hiding it behind a redirect.
  6. Re-crawl to confirm zero internal 4xx/5xx, and add a scheduled crawl so new breakage is caught early.

FAQ

Why fix internal links instead of just redirecting the broken URLs?

A redirect is a patch for URLs you do not control, like inbound backlinks. For links inside your own site, you can edit the href directly, which avoids an extra hop, preserves crawl efficiency, and keeps the link equity clean. Redirect only what you cannot edit.

Do broken internal links hurt rankings?

Not as a direct penalty, but they degrade the signals that do matter: crawlers waste budget on dead ends, PageRank that should flow to live pages is lost, and users bouncing off error pages send poor engagement signals. At scale that adds up.

How do I catch these before they ship?

Run a crawl in CI or on a staging build, or script a curl status check against your internal link list. Catching a 404 before deploy is far cheaper than finding it in Search Console weeks later.

What about links that redirect through a chain and then 404?

Those are the sneakiest, because the first hop returns a 3xx and looks healthy. Follow the chain to its final status and, if it ends in an error, repoint the original link to a live URL rather than leaving the chain in place.

Are broken internal and broken external links the same problem?

The symptom is similar, but internal links are entirely within your control to fix, while external ones depend on someone else's site. This check is scoped to your own domain.

For the wider workflow, see how to find and fix broken links and our HTTP status codes reference. To make the links you keep work harder, read internal linking: the complete guide. A frequent upstream cause of broken relative links is a malformed base URL.

Claude Vincent is a technical SEO consultant focused on crawlability, rendering, and AI-search visibility. He writes the field guides and case studies at SEO ProCheck, with a bias toward the durable, unglamorous work that decides whether search engines and AI answer engines can actually read and cite a site.

About SEO ProCheck

Technical SEO consulting and GEO strategy with 20 years of enterprise experience. Case studies, resources, and tools for search and AI visibility.

Work With Me

Technical SEO audits, GEO strategy, site migrations, and international SEO. Hourly consulting for teams who need hands-on support, not just reports.

Subscribe to our newsletter!

More from our blog