Broken Links Checker: Orphan Pages & Internal Linking Audit avatar

Broken Links Checker: Orphan Pages & Internal Linking Audit

Pricing

$2.00 / 1,000 page auditeds

Go to Apify Store
Broken Links Checker: Orphan Pages & Internal Linking Audit

Broken Links Checker: Orphan Pages & Internal Linking Audit

Broken links + orphan pages checker for your sitemap: find broken internal links, links to redirects/noindex, weak pages, click depth and anchor text, with a fix per page. First 25 pages free, then $0.002/page.

Pricing

$2.00 / 1,000 page auditeds

Rating

0.0

(0)

Developer

Umair Saleem Mohammad Saleem

Umair Saleem Mohammad Saleem

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

2 days ago

Last modified

Security

Limited permissions

Share

Internal Link Audit: Orphan Pages, Broken Links & Redirects

Answer first: this actor is an internal link audit and orphan page finder. Give it a sitemap (or a URL list). It crawls those pages and labels each one ORPHAN (no internal links in), WEAK (few links in), BROKEN_PAGE, REDIRECTED (the sitemap URL 301s), NOINDEX or CANONICAL_ELSEWHERE (should not be in the sitemap), HAS_BROKEN_LINKS, LINKS_TO_REDIRECTS (internal links that hit a 301/302) or OK. Each row has the pages that link to it, top anchor texts, click depth from the homepage and a fix. It also lists URLs that are linked but missing from your sitemap. First 25 pages free every run, then $0.002 per page.

Quick facts
Best forOrphan page audits, internal linking audits, broken internal links, internal redirects, sitemap clean-up after a migration, link depth / inlink counts
InputA sitemap URL (indexes followed) or a list of URLs (example.com/page without https:// is fine)
OutputOne row per page: issue, allIssues[], status, inlinks, clickDepth, redirectsTo, linkedFrom[], topAnchors[], brokenLinksOnPage[], redirectingLinksOnPage[], fix
PriceFirst 25 pages free every run, then $0.002 per page. No start fee
NeedsNo API keys, no proxies
Not includedJavaScript-injected links, external link checks

Why it matters

Orphan and weakly linked pages get crawled less, rank worse and are rarely cited by AI search. Internal linking is the cheapest SEO lever you control.

Input example

{
"sitemapUrl": "https://crawlee.dev/sitemap.xml",
"maxPages": 100,
"weakThreshold": 2,
"maxConcurrency": 5
}

Or pass a URL list instead of a sitemap:

{
"urls": ["https://example.com/", "https://example.com/about", "https://example.com/blog/post"],
"maxPages": 50,
"weakThreshold": 2,
"maxConcurrency": 5
}

Defaults: maxPages 50, weakThreshold 2, maxConcurrency 5, useHomepageAsRoot true. Sitemap indexes are followed (nested sitemaps up to depth 2). Provide either sitemapUrl or urls.

Issue types

IssueMeaning
REDIRECTEDThe listed/sitemap URL returns 301/302/307/308. redirectsTo has the final URL, and linksToOldUrl counts the pages still linking to the old one. Links to the final URL count as its inlinks
NOINDEXPage is in your sitemap/list but has noindex (meta robots or X-Robots-Tag)
CANONICAL_ELSEWHEREThe canonical tag points to a different URL
ORPHAN0 inlinks from other crawled pages
WEAK1…weakThreshold inlinks (default threshold 2)
BROKEN_PAGEPage itself returned HTTP ≥400, or the request failed (DNS, timeout, TLS); the error field says why
HAS_BROKEN_LINKSPage is fine but links to internal URLs that are ≥400 / failed
LINKS_TO_REDIRECTSPage links to internal URLs that return a redirect (listed in redirectingLinksOnPage with redirectsTo)
OKEnough inlinks and no broken internal outlinks

Each row has one main issue (priority BROKEN_PAGE → REDIRECTED → NOINDEX → CANONICAL_ELSEWHERE → ORPHAN → HAS_BROKEN_LINKS → WEAK → LINKS_TO_REDIRECTS → OK) and every issue that applies in allIssues. Rows are sorted in that order.

Output (one row per page)

url, issue, allIssues[], status, redirectStatus, redirectsTo, inlinks, linksToOldUrl, clickDepth, outlinksInternal, noindex, canonical, linkedFrom[], topAnchors[], brokenLinksOnPage[], redirectingLinksOnPage[], fix (+ error when a page could not be fetched)

  • clickDepth: clicks from the homepage through the crawled pages (0 = homepage, null = not reachable from crawled pages). Pages at depth 4+ are usually under-linked.
  • topAnchors: the anchor texts other pages use to link here (card links are reduced to their heading; image links use the alt text).

Input: {"sitemapUrl": "https://yoast.com/post-sitemap.xml", "maxPages": 30} (a WordPress site with trailing-slash URLs). Result: 30 pages, 23 ORPHAN, 6 WEAK, 1 LINKS_TO_REDIRECTS, 25 free + 5 billed = $0.01. These are the 30 oldest posts in the post sitemap, and most get no links from the other old posts or the homepage. Two rows (lists cut to 3):

[
{
"url": "https://yoast.com/how-to-remove-www-from-your-url/",
"issue": "ORPHAN",
"allIssues": [
"ORPHAN",
"LINKS_TO_REDIRECTS"
],
"status": 200,
"inlinks": 0,
"clickDepth": null,
"outlinksInternal": 51,
"linkedFrom": [],
"topAnchors": [],
"redirectingLinksOnPage": [
{
"url": "https://yoast.com/podcasts/",
"status": 301,
"redirectsTo": "https://yoast.com/podcast/"
},
{
"url": "https://yoast.com/jobs/",
"status": 307,
"redirectsTo": "https://yoast.com/careers/"
},
{
"url": "https://yoast.com/case-studies",
"status": 301,
"redirectsTo": "https://yoast.com/case-studies/"
}
],
"fix": "Link to this page from 3+ related pages (hub/category + body links), or remove it from the sitemap if it should not rank. Also point 6 internal link(s) that hit a redirect at their final URL."
},
{
"url": "https://yoast.com/online-marketing-tools/",
"issue": "WEAK",
"allIssues": [
"WEAK",
"LINKS_TO_REDIRECTS"
],
"status": 200,
"inlinks": 1,
"clickDepth": null,
"outlinksInternal": 58,
"linkedFrom": [
"https://yoast.com/email-performance-in-google-analytics/"
],
"topAnchors": [
"Tools to improve your online marketing campaign"
],
"redirectingLinksOnPage": [
{
"url": "https://yoast.com/podcasts/",
"status": 301,
"redirectsTo": "https://yoast.com/podcast/"
},
{
"url": "https://yoast.com/jobs/",
"status": 307,
"redirectsTo": "https://yoast.com/careers/"
},
{
"url": "https://yoast.com/case-studies",
"status": 301,
"redirectsTo": "https://yoast.com/case-studies/"
}
],
"fix": "Add contextual links from stronger related pages with descriptive anchors. Also point 8 internal link(s) that hit a redirect at their final URL."
}
]

SUMMARY.internalLinksToRedirects (top 4 of the run): links that every page carries, each costing users and crawlers an extra hop:

[
{
"url": "https://yoast.com/podcasts/",
"status": 301,
"redirectsTo": "https://yoast.com/podcast/",
"linkedFromPages": 31
},
{
"url": "https://yoast.com/jobs/",
"status": 307,
"redirectsTo": "https://yoast.com/careers/",
"linkedFromPages": 31
},
{
"url": "https://yoast.com/case-studies",
"status": 301,
"redirectsTo": "https://yoast.com/case-studies/",
"linkedFromPages": 31
},
{
"url": "https://yoast.com/werken-bij/",
"status": 307,
"redirectsTo": "https://yoast.com/careers/",
"linkedFromPages": 31
}
]

Trailing-slash URLs that answer 200 are not flagged. Only links that really return a 3xx are.

Real sample 2: redirected URLs in a list (run Nqbypg6HskxvJnly8, 20 Oct 2026)

Input: {"urls": ["https://crawlee.dev/docs/quick-start", "https://crawlee.dev/docs/introduction", "https://crawlee.dev/js/docs/examples", "https://crawlee.dev/js/docs/guides", "crawlee.dev/blog"]}. The two old /docs/ URLs now 301 to /js/docs/. Earlier versions reported them as ORPHAN with 0 inlinks. They are now REDIRECTED, and links to the new URL are credited to them:

{
"url": "https://crawlee.dev/docs/quick-start",
"issue": "REDIRECTED",
"status": 200,
"redirectStatus": 301,
"redirectsTo": "https://crawlee.dev/js/docs/quick-start",
"inlinks": 3,
"linksToOldUrl": 0,
"clickDepth": 2,
"linkedFrom": [
"https://crawlee.dev/docs/introduction",
"https://crawlee.dev/js/docs/examples",
"https://crawlee.dev/js/docs/guides"
],
"fix": "This listed URL 301-redirects to https://crawlee.dev/js/docs/quick-start. Put the final URL in your sitemap."
}

SUMMARY key-value: pagesAudited, freePages, billedPages, byIssue counts, homepageRoots, linkedButNotInList (internal pages linked from crawled pages but not in your sitemap/list, up to 200; files like .pdf/.json are left out), internalLinksToRedirects (link URLs that return 3xx, with redirectsTo and how many pages link them) and skippedInput (input values that were not URLs).

Pricing (pay per event)

First 25 pages in every run are free, then $2 per 1,000 pages ($0.002 per page audited).

What a run costs

Pages auditedYou pay
25$0 (free in every run)
100≈ $0.15
500≈ $0.95
1,000≈ $1.95
5,000≈ $9.95

(First 25 free each run.) Set a maximum charge per run in Apify run options; when the event spend cap is hit the actor stops cleanly (eventChargeLimitReached).

Notes

  • Inlinks are counted only among pages crawled in the run. For a full-site orphan check, raise Max pages to cover the whole sitemap.
  • Pages are read as server-rendered HTML (Cheerio). Links injected only by client-side JavaScript (SPA routers) are not seen — the same limitation most search and AI crawlers have.
  • Up to 150 linked-but-not-listed internal URLs are status-checked for broken links and redirects, using the exact URL as written in the link (HEAD first, then GET when a server rejects HEAD, so 405/403 replies are not reported as broken).
  • If the homepage is not in your list it is fetched once as a link source and depth root. It is not billed and not output (turn off with useHomepageAsRoot: false).
  • http/https, www./non-www and trailing-slash variants of the same URL are merged for inlink counts, so a page is never counted twice. Each spelling is still checked on its own, so a link to /page that 301s to /page/ is reported as a link to a redirect.

How it compares (live Apify Store prices, verified 20 Oct 2026)

List prices on the Apify Free plan, read from the Apify Store API on 20 October 2026.

ActorJob focusPriceFree pagesCost for 100 pages
cygnix_labs/internal-link-audit (this)Orphan + weak + broken internal + internal redirects + redirected/noindex sitemap URLs + click depth + missing-from-sitemap, fix per page$0.002 / pageFirst 25 every run$0.15
dabooti/internal-link-graph-analyzerInternal-link graph + orphan candidates$0.001 / page + $0.00005 startNo~$0.10
plainrows/broken-link-checkerBroken links, redirect chains, sitemaps$0.0015 / pageNo$0.15
clearfetch/broken-link-checkerBroken links + redirect chains$0.002 / page + $0.0005 / URL checkedNo$0.20 + URL checks
ib4ngz/internal-link-opportunity-finderContextual link opportunities (not an orphan audit)$0.0065 / pageNo$0.65
martinhida/haw-content-inventory-internal-linksContent inventory + internal link map$0.01 / pageNo$1.00
searchshark/domain-internal-link-crawler-screamingfrog-alternativeFull link crawl, one row per link$0.001 / result + $0.01 startNodepends on link count
logiover/website-link-graph-crawlerLink graph crawl$0.0075 / itemNodepends on rows
khadinakbar/broken-link-checkerBroken links, 404s and redirects (per link, not an orphan audit)$0.001 / link checked + $0.00005 startNodepends on link count
nexgenwatch/internal-link-architecture-verifierArchitecture checks$0.05 / page + $0.02 startNo$5.02

Honest take. dabooti is cheaper per page ($0.001 vs $0.002) and bills every page. Here a 25-page client check costs $0 and 100 pages cost $0.15 vs about $0.10 there. Choose this one for free spot checks and for the orphan, broken, redirect, click-depth and sitemap-gap labels with a fix per row; choose dabooti for very large crawls where only price matters.

For AI agents / MCP

When an agent should call this actor: the user asks to find orphan pages, check internal linking, find broken internal links or internal links to redirects, clean up a sitemap after a migration (redirected or noindex URLs), or see which pages are missing from the sitemap.

Connect the Apify MCP server with only this actor enabled (works in Claude, ChatGPT, Cursor, VS Code, Codex and any MCP client):

https://mcp.apify.com?tools=cygnix_labs/internal-link-audit

Or search for it with the default server: search-actors keywords such as internal links, orphan pages, broken links.

Example call-actor input:

{
"sitemapUrl": "https://example.com/sitemap.xml",
"maxPages": 200,
"weakThreshold": 2,
"maxConcurrency": 5
}

What to read from the result: rows are sorted by issue (BROKEN_PAGE first, OK last). Each has url, issue, allIssues, inlinks, clickDepth, redirectsTo, linkedFrom, topAnchors, brokenLinksOnPage, redirectingLinksOnPage and fix. SUMMARY has byIssue counts, linkedButNotInList (internal pages missing from the sitemap) and internalLinksToRedirects.

Cost control for agents: Keep maxPages at 25 for a free first pass; raise it to cover the whole sitemap for a true orphan check. Pass maxTotalChargeUsd in callOptions to hard-cap spend. This actor is pay-per-event, so it also works with Apify agentic payments (no Apify account needed for the agent).

Example prompt: "Audit internal links on example.com from its sitemap (200 pages) and list orphan pages and broken internal links with fixes."

FAQ

Can I cap my spend? Yes. Set a max charge per run; the actor stops when eventChargeLimitReached is returned and you are not billed beyond that cap. Do sitemap indexes work? Yes. Nested <sitemapindex> files are followed up to depth 2, collecting <loc> URLs until Max pages is reached. Are nofollow links counted? No. Anchors with rel containing nofollow are skipped for both outlink and inlink graphs. How polite is concurrency? Default maxConcurrency is 5 (max 20). Keep it low on production sites so you do not hammer your own server. Does it need proxies or API keys? No. It fetches your pages directly with a polite user-agent. JavaScript-only SPAs? Only links present in the server HTML are audited. Pre-render or use a sitemap of real URLs if the site is client-rendered.

How is crawl depth / click depth measured? Breadth-first from the homepage over the links found on crawled pages. clickDepth 1 = linked from the homepage. null means no crawled page chain reaches it, which is a strong orphan signal. Does a broken or malformed link crash the audit? No. Invalid href values are skipped, and a page that fails to load is reported as BROKEN_PAGE with an error instead of stopping the run. Are gzipped sitemaps supported? Yes, .xml.gz sitemaps and <![CDATA[...]]> URLs are read.

Does it follow redirects? Yes, up to 10 hops, by hand, so a sitemap URL that redirects is reported as REDIRECTED with its final URL instead of a false ORPHAN. Redirected rows are never flagged ORPHAN/WEAK. Can I paste URLs without https://? Yes. example.com/page is read as https://example.com/page. Values that are not URLs are listed in SUMMARY.skippedInput, and if none of your URLs are valid the run stops with nothing charged.

Why does a page show as ORPHAN when my menu links to it? Inlinks are counted only among pages crawled in the run. If the linking page was beyond maxPages, raise the cap. Links added only by JavaScript are not seen.

Integrations

Run via the Apify API, schedule weekly runs, or send results to Google Sheets, Make, Zapier, n8n, Slack or webhooks.

Changelog

  • 0.1.11 (2026-10-20): Fixes found in smoke runs: (1) sitemap/list URLs that redirect were reported as ORPHAN with 0 inlinks and status 200, because links to their new URL were not counted (repro run RLmwqj7umaqHpKm3N on crawlee.dev). They are now REDIRECTED with redirectsTo and linksToOldUrl. (2) URLs typed without https:// were silently dropped, and a list of only such URLs fell back to the demo sitemap. (3) http and https homepages of one site were both crawled as roots. New: LINKS_TO_REDIRECTS, NOINDEX and CANONICAL_ELSEWHERE checks, allIssues, redirectingLinksOnPage, SUMMARY.internalLinksToRedirects, and file URLs (.pdf/.json…) left out of linkedButNotInList. Price unchanged ($0.002/page, first 25 free).
  • 0.1.9 (2026-10-19, code fixes first shipped in build 0.1.8): Fixes: one malformed href no longer drops the whole page (it was reported as status 0); failed fetches are now BROKEN_PAGE with an error; servers that reject HEAD (405/403) are re-checked with GET instead of being reported as broken; http/https/www/trailing-slash variants are merged. New: clickDepth from the homepage, homepage fetched as a free link source, cleaner anchor text (no "- " prefixes, card links reduced to their heading, image alt), gzip and CDATA sitemaps. Real sample from a 19 Oct run; comparison re-verified 19 Oct 2026. Price unchanged ($0.002/page, first 25 free).
  • 0.1.6 (2026-10-18): README rewritten answer-first for search and AI agents: quick facts, comparison re-verified against 6 named actors on 18 Oct 2026, "For AI agents / MCP" section with example input. Price unchanged ($0.002/page, first 25 free).
  • 0.1.2 (2026-10-16): Stronger orphan / internal-links / sitemap-crawl opening.

More SEO and AEO tools by Cygnix Labs

Questions or a feature request? Open an issue on this actor's Issues tab. We answer within 24 hours.