Free SEO Tools

Internal Link Checker

Crawl a starting page, map the internal links between pages, and find broken targets, thin anchors, and weakly linked pages.

Start from a hub or category page that links widely, rather than the homepage alone.

This crawls a capped sample of pages, so it is a spot check on one section rather than a full-site audit.

Internal link report

Enter a starting URL to map how a section of your site links together.

What the 12-page crawl covers

You enter one page. The checker fetches it, follows any redirects, collects every <a href> in the HTML, and keeps the links whose host matches the host the page ended on. It then visits those links breadth-first, in the order they appear in the source, and stops after 12 page requests. Because the queue fills from the start page first, the crawl is in practice the start page plus the first 11 different internal links in its HTML that have no query string. On most WordPress sites those are the logo link and the header menu.

On every page it reaches, it records each internal link: where it sits, where it points, its anchor text and whether its rel attribute contains nofollow. A linked page it visits but that returns 400 or higher, or does not load, is listed as a broken target instead of being crawled. Linked pages it did not visit, up to 40, get a status check: a HEAD request, retried as a GET when the server answers 403 or 405, with 7 seconds each and redirects followed. Links without a query string are checked first. A target counts as broken when the final status is 400 or higher, or when it cannot be reached at all.

What the crawl skips or merges

  • Links to any other host, including the www or non-www twin of the site. The host comes from where the start page ends up after redirects, so example.com for a site served at www.example.com works, but a link written as example.com on that site is skipped as external.
  • Links that are only a #fragment. A link to /recipe/#comments is merged with /recipe/.
  • Links added by JavaScript after the page loads. The checker reads the HTML the server sends.
  • Every page past the twelfth request. Only the first 900 KB of a page is read, and Notes says when a page was longer. A linked page that could not be loaded is listed under Broken internal targets.
  • Nothing about http versus https: an http:// link on an https:// site still counts as internal, because only the host is compared.
  • Links with a query string, such as ?add-to-cart=, ?replytocom= or ?orderby=price, are counted as links but not visited, so they do not use up the 12 requests. /shop/ and /shop/?orderby=price are still two different targets. Plain WordPress permalinks such as ?p=123 and ?page_id=45 are visited, since they are the pages themselves.

Choosing a starting URL

The start page is analyzed in full: every internal link on it is recorded and its uncrawled targets are status-checked. The other 11 pages are whatever it links to first, which on a WordPress theme is nearly always the header menu, because the header comes before the content in the HTML.

So pick the start page for its own links. Good choices are a cornerstone post you want to check, a category page whose links you just reorganized, or a post you suspect links to deleted pages. Starting from the home page mostly tells you about your menu, which you already know is linked from everywhere.

If the crawl stops below 12 pages, the start page has fewer than 11 internal links without a query string, or some links failed, redirected to a page already crawled or pointed to files such as PDFs. Failed links are listed under Broken internal targets.

Reading the summary numbers

The six numbers count links across every crawled page, so template links (header, footer, sidebar) are counted once per page they appear on.

NumberWhat it countsWhat a high count usually means
Pages crawledPages that loaded as HTML, from up to 12 requestsBelow 12: few links on the start page, or links that failed, redirected or pointed to files
Internal linksEvery same-host link on those pages, repeats and self-links includedMostly template links; a 40-link menu on 12 pages adds 480
Generic anchorsLinks whose whole text is one of 13 phrases, such as read more or click hereA theme’s Read more button on an archive, or habit in older posts
Empty anchorsLinks with no text inside themLinked images and icon links; see the section on empty anchors
Nofollow internalInternal links whose rel contains nofollowComment reply links or WooCommerce add-to-cart buttons, which are normal
Broken targetsLinked pages, crawled or status-checked, that returned 400 or higher or could not be reachedDeleted or renamed pages that links still point to

Anchor text: what counts as generic

Anchor text here is the text inside the link, with spaces collapsed and cut at 120 characters. Image alt text and aria-label attributes are not read. Text hidden with a screen-reader-only class is read, because it is in the HTML.

A link counts as generic when its whole text, ignoring case, is one of 13 phrases: click here, here, read more, more, learn more, this, link, this page, this post, this article, see more, find out more and continue reading. “Read more about proofing baskets” is not generic. A Read more link with a descriptive aria-label still counts, because the checker sees only the visible words.

Two sources make the case for descriptive anchors. Google’s link best practices ask for anchor text that is descriptive, reasonably concise and relevant to the page it links to. WCAG 2.4.4, Link Purpose (In Context), a Level A requirement, asks that each link’s purpose be clear from its text and surrounding context. Screen reader users often move through a page by its list of links, where twenty Read more entries sound the same.

Most used anchor text shows the 15 most common anchors across the crawl. Menu labels top it. Look below them for one phrase repeated on links to several different pages, or a keyword phrase used as the anchor on every link to one page.

A link in a post

Before: For the shaping steps, click here.

After: Follow our steps for shaping a sourdough loaf.

The anchor moves from “click here” to “shaping a sourdough loaf”, which tells readers and Google what the target page is about.

A theme’s archive button

Before: Read more

After: Read more: Sourdough starter in 7 days

Classic themes often build this text in a template file; in a block theme, the Read More block in the Query Loop sets it. Where the button text cannot include the title, the linked post title next to it already does the job, so leave the button alone.

Empty anchors and linked images

An empty anchor is a link with no text inside it. On WordPress sites nearly all of them are linked images (the logo, featured image thumbnails on archive pages, product images) and icon links (social icons, a search toggle, a cart icon).

Because the checker does not read alt text, a linked image counts as empty here even when its alt text is good. That matters, since Google uses a linked image’s alt text as its anchor text, and screen readers announce it as the link’s name. So treat Empty anchors as a list to verify, not a list of errors. The alt text checker flags exactly the case that is a problem: an image that is the only content of a link and has empty alt.

Icon links need a name too. The Social Icons block gives each icon a label setting for this. In a classic theme, the icon usually needs an aria-label on the link or hidden text inside it, which is a theme setting or a template edit.

Broken internal targets

Each entry reads status — URL, for example 404 — https://example.com/old-recipe/, with the crawled pages that link to it under Linked from. An entry with a message instead of a number could not be reached at all.

Linked from tells you where to look. When it lists every crawled page, the link is in the template: the menu, a widget, the footer, or a synced pattern. When it lists one or two pages, the link is in their content: open them in the editor and search for the slug. The broken link checker does the same for external links.

The best fix is to edit the link to point at the right page. If the old address has links from other sites or still gets search traffic, also add a 301 redirect from it: Rank Math SEO → Redirections, Yoast SEO Premium → Redirects, or the Redirection plugin under Tools → Redirection. Update your own links even after adding the redirect, so visitors skip the extra hop.

What this list does not catch, and false alarms

  • Redirected links are not flagged. A link to /old/ that 301s to /new/ passes. Run a link you suspect through the redirect checker.
  • Past 40 status checks, the remaining links are not checked, and Notes says so. Links with a query string are checked last, so they are the ones left out.
  • “The website took too long to respond.” means no answer within 7 seconds. Re-run before you change anything.
  • A 403 or 429 on pages that open in your browser is usually a firewall or rate limit refusing automated requests, not a broken page.

Orphan pages: why the report has no orphan list

An orphan page is one that no other page on your site links to. A crawl cannot find one: every page after the first is reached by following a link from a crawled page, and a link that redirects counts for the page it lands on. So the only row that can show an In of 0 is the start page, when no other crawled page links back to it.

The closest thing inside the crawl is a content page with an In of 1: only one of the pages reached links to it. That is worth a look when the page matters to you, as in the flour guide example above.

You find real orphans by comparing a full list of your pages with the pages that receive links. The sitemap URL extractor produces that list, and its guide walks through the comparison with Search Console’s Links report.

Crawl depth and how to shorten it

Crawl depth is the number of clicks from the home page to a page. This checker does not measure it, and Google publishes no depth limit. What Google does document is that it finds pages mainly by following links, so a page you care about should be linked from pages Google already crawls often, not only from page 14 of your blog archive.

You can estimate it by hand. From the home page, click your way to an older post the way a visitor would: menu, category, then Next page until it appears. Each click and each archive page is one level. If you pass page 3 of an archive, the post is deep, and it is probably linked from nowhere but that archive.

  1. 1.Link new posts from older, well-linked posts on the same topic. Old posts are crawled often and already rank.
  2. 2.Turn category pages into hubs: a short introduction and links to the best posts in that category, not only the ten most recent.
  3. 3.Show breadcrumbs. Yoast SEO and Rank Math output them, as does SEOPress Pro, and they give every post a link up to its category.
  4. 4.Use a related posts block that picks by category or tag, so each post links sideways to its neighbors.

Adding links across hundreds of old posts is slow by hand. RankHive reads your Search Console data, finds posts that should link to each other, and drafts the links with their anchor text; you approve each one before its plugin writes it into WordPress.

Checking the result in Google, and when to leave it alone

After you add links, re-run the checker from the same start page: the target’s In count should rise and your generic anchors fall. Google takes longer. In Search Console, Links → Internal links → Top linked pages shows how many internal links Google counts to each page, and it updates as Google recrawls the pages that now carry the link. URL Inspection on the target page lists a referring page under Discovery once Google has seen one.

If your links are added by JavaScript, check that Google sees them: run URL Inspection on the linking page, choose Test live URL, then View tested page, and search the rendered HTML for the link.

Leave these alone: nofollow on Reply and Add to cart links; empty anchors that are linked images with good alt text; high In counts on menu pages; and low In counts on pages that do not need to rank, such as privacy, terms and login pages.

FAQ about the Internal Links

How many pages does this crawl?

Up to 12 page requests, starting from the URL you enter and following internal links breadth-first in the order they appear in the HTML. Links with a query string are counted but not crawled. It also status-checks up to 40 linked pages it did not crawl.

Does it find orphan pages?

No. An orphan is a page no other page links to, and a crawl that follows links cannot reach one. A site-wide orphan check needs a full list of your pages, such as your sitemap, compared with the pages that receive links. Inside the crawl, content pages with an In of 1 are the ones with the fewest links.

Why does the report show 1 page and 0 internal links?

Usually the links are built by JavaScript, which the checker does not run, or the site writes its own links with the other host, such as example.com on a site served at www.example.com. The checker compares hosts exactly, with the host the start page ends up on after redirects, so those links look external. If the start page returned an error, Notes says so.

Does it follow nofollow links?

Yes. Nofollow links are crawled and counted like any other. The Nofollow internal number tells you how many carry the attribute.

Are menu, sidebar and footer links counted?

Yes, every <a href> in the HTML counts, wherever it sits. Google follows them too. They say little about how your content links together, which is why menu pages show high In counts and the content rows are the ones to read.

How many internal links should a page have?

Google publishes no number. Link where a reader would want to go next, with anchor text that says where. The patterns worth fixing are a post with no in-content links to other posts, and a cornerstone page that few posts link to.

Does it check links to other sites?

No. External links are skipped here. The broken link checker tests internal and external links together and shows the page each one sits on.