How to Fix Broken Internal Links Before They Hurt Rankings

Find and fix broken internal links before they hurt your Google rankings. Step-by-step guide with redirect examples for WordPress, Apache, and nginx. Free broken link audit available.

10 min read SEO

Every website accumulates broken internal links over time — pages get deleted, slugs get renamed, and HTTPS migrations leave behind a trail of outdated URLs. If you don't fix broken internal links regularly, you silently bleed PageRank, waste Googlebot's crawl budget, and send real visitors to dead-end 404 pages that drive them straight to a competitor.

This guide walks you through exactly how to find every broken internal link on your site and fix each one using the right method for your situation.

Want to find all broken links on your site instantly? Run a free WebsiteLinter scan — it crawls every internal link on your site and flags 404s, redirect chains, and broken anchors in one report.

Why Broken Internal Links Are an SEO Problem

Most site owners think of broken links as a minor housekeeping issue — something to fix when you get around to it. Google sees them differently. When Googlebot crawls your site and repeatedly hits 404 pages, several compounding problems occur simultaneously.

Crawl budget waste. Googlebot allocates a finite crawl budget to your site based on its authority and server response times. Every time a crawler requests a URL that returns a 404, that crawl slot is consumed without indexing anything useful. For large sites with thousands of pages, this is a meaningful problem — Googlebot may exhaust its budget on dead URLs before it reaches your most important new content.

Lost PageRank flow. Internal links are how PageRank — Google's measure of page authority — flows through your site. When an internal link points to a 404 page, that PageRank goes nowhere. The equity that should be flowing from your high-authority homepage or top blog posts to your product and service pages simply evaporates. Over time, this weakens the ranking power of your most important pages.

High bounce rate from poor UX. Real visitors hitting 404 pages leave immediately. There is nothing to read, no path forward, and no reason to stay. That spike in bounce rate on 404 pages is a negative user experience signal that Google factors into overall site quality assessments.

Site quality signals. Google has confirmed that a high rate of 404 errors can indicate a lower-quality, poorly maintained site. While a handful of 404s won't tank your rankings, a site with hundreds of broken internal links sends a clear signal that the content is not being actively maintained.

Common causes of broken internal links:

  • A post slug was changed after publishing without updating existing links to it
  • A page was deleted but internal links pointing to it were never removed
  • An HTTP-to-HTTPS migration left hardcoded http:// URLs in post content
  • A domain migration left references to the old domain in the database
  • A URL structure change (e.g., removing /category/ from post URLs) made old links invalid

The good news: all of these are fixable once you know where they are. For a broader look at how link health fits into overall site health, see our complete website SEO audit guide.

How to Find All Broken Internal Links on Your Site

Before you can fix broken internal links, you need a complete inventory of them. There are three primary methods, and using all three gives you the most complete picture.

Screaming Frog Spider (free for up to 500 URLs). Screaming Frog is the gold standard for site crawling. Download and install it, enter your domain, and run a full crawl. When it finishes, go to the Response Codes tab and filter for 404 status codes. The tool shows you not just which URLs are returning 404, but which pages contain links to those broken URLs — the "Inlinks" tab for any selected 404 URL shows you exactly where to go to fix the source link. For sites over 500 URLs, you'll need the paid license ($259/year), which is worth it for any serious SEO work.

WordPress Broken Link Checker plugin. If your site runs on WordPress, the Broken Link Checker plugin crawls your content in the background and flags broken links directly in the WordPress admin. Go to Settings → Tools → Broken Links to see a dashboard of all detected issues. You can edit the source link directly from this dashboard without opening each post individually. A note of caution: leave the plugin's always-on background scanning enabled only temporarily, as continuous scanning puts load on your server.

Google Search Console. In GSC, navigate to Pages → Not Found (404). This shows you every URL on your site that Googlebot encountered as a 404 — including pages linked from external sites. GSC is invaluable because it shows you real crawl data from Googlebot, not just a snapshot of your current site architecture.

Prioritization tip. Don't try to fix every broken link at once. Start with 404 pages that are linked from your highest-traffic pages — these are the ones costing you the most PageRank flow and causing the most user frustration. Use Screaming Frog's Inlinks data to find which source pages are pointing to broken destinations, then cross-reference against GA4 organic traffic.

Fix 1 — Create a 301 Redirect to the Correct URL

The best fix when the content you linked to exists at a new URL is a 301 permanent redirect. A 301 tells search engines "this page has moved permanently" and passes approximately 99% of the original page's link equity to the new destination. It also seamlessly redirects human visitors without them ever knowing a URL changed.

On Apache servers, add redirects to your .htaccess file in the site root:

# Simple redirect — use for a single renamed page
Redirect 301 /old-page/ /new-page/

# Pattern-based redirect using mod_rewrite — use for category restructures
RewriteEngine On
RewriteRule ^old-category/(.*)$ /new-category/$1 [R=301,L]

The [R=301,L] flags mean: respond with a 301 redirect and stop processing further rules. The (.*) capture group and $1 backreference preserve any subpath after the category, so /old-category/post-title/ redirects cleanly to /new-category/post-title/.

On nginx, add redirect rules inside your server block:

# Simple redirect
location = /old-page/ {
    return 301 /new-page/;
}

# Pattern-based redirect
location ~ ^/old-category/(.+)$ {
    return 301 /new-category/$1;
}

In WordPress, the Redirection plugin (free) provides a UI for managing 301 redirects without touching server config files. It also logs redirect hits so you can see how often each redirect is being used.

Fix 2 — Update the Source Link Directly

When you have direct access to the page containing the broken link and the destination page simply has a new URL, updating the link at the source is often the cleanest fix — no redirect infrastructure needed, and PageRank flows directly without any intermediary hop.

In the WordPress Block Editor: Open the post containing the broken link, find the linked text, click the link, and update the href to the correct URL. Save and update. For one or two broken links, this is the fastest approach.

For bulk updates with Better Search Replace: When dozens of posts link to an old URL, the Better Search Replace plugin does a database-wide find-and-replace. Enter the old URL in the Search field and the new URL in the Replace field, select all relevant tables, and run a dry run first to see how many replacements it would make before committing.

For power users — WP-CLI: If you have command-line access to your server, WP-CLI's search-replace command is the fastest and most precise tool for bulk URL updates. Always run with --dry-run first:

# Dry run — shows what would change without touching the database
wp search-replace '/old-slug/' '/new-slug/' wp_posts wp_postmeta --dry-run

# Actual replace — run only after verifying the dry-run output
wp search-replace '/old-slug/' '/new-slug/' wp_posts wp_postmeta

The command outputs a table showing each database table and the number of replacements made. Specifying wp_posts wp_postmeta limits the search to post content and meta fields — safer than running it across all tables when you're targeting post body links specifically.

Fix 3 — Restore or Recreate the Deleted Page

Sometimes a page was deleted that should not have been — a landing page that still has external links pointing to it, a pillar content piece that other posts reference heavily, or a product page that ranks for long-tail keywords. In these cases, a redirect to a different page is a poor substitute; the right fix is restoring the original page.

Check WordPress Trash first. WordPress soft-deletes posts and pages into the Trash for 30 days before permanently removing them. Go to Admin → Pages (or Posts) → Trash and look for the deleted page. If it's there, hover over it and click Restore. The page returns with its original slug intact.

Recreate from cache if trash is empty. If the page has been permanently deleted, you have two options for recovering the content:

  • Google's cached version: Search for the page in Google and view the cached copy from search results.
  • Wayback Machine: Visit web.archive.org and enter the old page URL to find an archived snapshot.

When recreating the page, use the exact original slug. This is critical — matching the original slug exactly means the restored page resolves all broken links immediately with no redirect infrastructure needed.

Fix 4 — Understanding and Fixing Redirect Chains

A redirect chain occurs when a URL points to another URL that itself redirects — Page A → 301 → Page B → 301 → Page C → 200. These chains are subtle performance and SEO problems that build up naturally when a site migrates, restructures content, or changes domains multiple times over the years.

Why redirect chains matter:

  • Each redirect hop adds latency — typically 100–300ms per hop
  • Each hop loses a small fraction of the link equity being passed through
  • Google's crawler may not follow chains longer than 3–5 hops, meaning the final destination may not receive full credit
  • They complicate your redirect infrastructure over time

To diagnose redirect chains, use the curl -IL command in your terminal. The -I flag fetches headers only and -L follows all redirects, printing each response in the chain:

curl -IL https://example.com/old-page/

A clean single redirect looks like this:

HTTP/2 301
location: https://example.com/new-page/

HTTP/2 200

A redirect chain looks like this — three hops before reaching a 200:

HTTP/1.1 301 Moved Permanently
Location: http://www.example.com/old-page/

HTTP/1.1 301 Moved Permanently
Location: https://www.example.com/old-page/

HTTP/2 301
location: https://www.example.com/new-page/

HTTP/2 200

The fix: update Page A's redirect rule to point directly to Page C, skipping Page B entirely. In .htaccess, change the existing Redirect 301 /old-page/ /intermediate-page/ to Redirect 301 /old-page/ /final-page/. Every URL in your redirect infrastructure should point in a single hop to a live 200 page.

Fix 5 — Handle Broken Links from HTTPS Migration

One of the most common sources of broken internal links is an incomplete HTTP-to-HTTPS migration. When you install an SSL certificate and switch your site to HTTPS, any hardcoded http:// URLs remaining in your post content, navigation menus, or widget areas will resolve via a redirect. Over time, these HTTP-to-HTTPS redirects accumulate and become redirect chains — which, as we covered above, bleed link equity.

For a complete walkthrough of the HTTPS migration process, see our guide on how to fix HTTP-to-HTTPS redirects. The short version for cleaning up existing HTTP URLs in your WordPress database:

# Always dry-run first to see the scope of changes
wp search-replace 'http://yourdomain.com' 'https://yourdomain.com' --all-tables --dry-run

# Run the actual replacement once you've reviewed the dry-run output
wp search-replace 'http://yourdomain.com' 'https://yourdomain.com' --all-tables

The --all-tables flag ensures the replacement runs across every table in the WordPress database, including theme options, widget settings, and navigation menus — not just post content. HTTP URLs hiding in widget areas or Customizer settings won't be caught by a post-content-only search.

The same approach applies to domain migrations. Run the same WP-CLI command with your old domain and new domain as the search and replace values. Cover both http:// and https:// variants of the old domain in two separate passes.

This issue is one of the most common findings surfaced by automated website audits.

Fix 6 — Set Up a Custom 404 Page That Retains Users

Even after a thorough broken link cleanup, some 404s are unavoidable. External sites link to pages you've deleted. Visitors misremember URLs. A well-designed custom 404 page turns these dead ends into recovery opportunities instead of exit points.

What a good 404 page includes:

  • Your site's full navigation menu so users can find what they're looking for
  • A prominent search box — the most direct path to relevant content
  • Links to your most popular posts or product pages
  • Friendly, on-brand copy that acknowledges the error without alarming the user ("Looks like that page moved — here's where to go next")
  • Your contact information or a link to /contact

In WordPress, create a custom 404.php template in your child theme, or use a dedicated plugin like Smart Custom 404 Error Page.

One thing a 404 page should never do: return a 200 HTTP status code. This is called a "soft 404" and is one of the most damaging technical SEO errors a site can have. Google's crawlers detect that the page content indicates a missing resource even though the server returned a 200, and they may deindex or deprioritize the page. Always confirm your 404 pages return a real 404 HTTP status.

Fix Broken Internal Links from HTTP-to-HTTPS Migration — Extended

When sites migrate from HTTP to HTTPS, there's often a subtler second layer of broken links that goes unfixed: links in serialized data stored in the WordPress wp_options table. Themes, page builders (Elementor, Divi, Beaver Builder), and plugin settings often store full URLs in serialized PHP arrays. A naive string replace on serialized data breaks the serialization format because PHP serialized strings include character counts (s:45:"http://yourdomain.com/page/").

WP-CLI's search-replace handles serialization correctly — it updates the character count automatically. This is one of the key reasons to use WP-CLI rather than running raw SQL UPDATE statements against your database directly.

# Safe serialization-aware replace — WP-CLI handles the character count update
wp search-replace 'http://yourdomain.com' 'https://yourdomain.com' \
  --all-tables \
  --report-changed-only \
  --dry-run

The --report-changed-only flag suppresses output for tables with no changes, making it easier to review what actually needs updating before you run the live replacement.

Build an Ongoing Broken Link Monitoring Routine

Finding and fixing broken internal links once is valuable. Building a repeatable process that catches new broken links quickly is what separates sites that compound their SEO gains over time from sites that drift into technical debt.

Monthly full crawl. Schedule a Screaming Frog crawl once a month and review the 404 report. For most small-to-medium sites, this takes 30 minutes and catches any new broken links before they accumulate.

Google Search Console crawl error alerts. In GSC Settings, enable email notifications for new crawl errors. When Googlebot encounters a new 404 on your site, you'll receive an alert within days rather than discovering it during your monthly crawl.

Post-migration audits. Any time you make a structural change — migrating to a new domain, changing your permalink structure, pruning old content, restructuring categories, or switching themes — run a full broken link audit immediately afterward. These events are the primary source of new broken links.

WordPress Broken Link Checker — scheduled mode. If you want ongoing automated monitoring within WordPress, configure the plugin to run on a schedule rather than always-on background scanning. The always-on mode is known to cause performance issues on shared hosting. Set it to scan weekly during low-traffic hours.

For a comprehensive approach to site health that covers broken links alongside performance, security, and accessibility — all in one automated report — WebsiteLinter was built specifically for this workflow.

Monitoring Method Frequency Best For
Screaming Frog crawl Monthly Full inventory, finds source pages
Google Search Console Ongoing (email alerts) Real Googlebot 404 data
WP Broken Link Checker Weekly scheduled WordPress sites, in-dashboard fixes
WebsiteLinter scan On demand / scheduled Full site health + broken links in one report

Monitor your internal links automatically. Run your free WebsiteLinter scan now → Get a full SEO, accessibility, performance, and security report — find broken links and 50+ other issues in one scan.

By Jake Lindsey — Lindsey Web Solutions, LLC