Broken Links Checker: Orphan Pages & Internal Linking Audit
Pricing
$2.00 / 1,000 page auditeds
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
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
2 days ago
Last modified
Security
Limited permissionsShare
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 for | Orphan page audits, internal linking audits, broken internal links, internal redirects, sitemap clean-up after a migration, link depth / inlink counts |
| Input | A sitemap URL (indexes followed) or a list of URLs (example.com/page without https:// is fine) |
| Output | One row per page: issue, allIssues[], status, inlinks, clickDepth, redirectsTo, linkedFrom[], topAnchors[], brokenLinksOnPage[], redirectingLinksOnPage[], fix |
| Price | First 25 pages free every run, then $0.002 per page. No start fee |
| Needs | No API keys, no proxies |
| Not included | JavaScript-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
| Issue | Meaning |
|---|---|
| REDIRECTED | The 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 |
| NOINDEX | Page is in your sitemap/list but has noindex (meta robots or X-Robots-Tag) |
| CANONICAL_ELSEWHERE | The canonical tag points to a different URL |
| ORPHAN | 0 inlinks from other crawled pages |
| WEAK | 1…weakThreshold inlinks (default threshold 2) |
| BROKEN_PAGE | Page itself returned HTTP ≥400, or the request failed (DNS, timeout, TLS); the error field says why |
| HAS_BROKEN_LINKS | Page is fine but links to internal URLs that are ≥400 / failed |
| LINKS_TO_REDIRECTS | Page links to internal URLs that return a redirect (listed in redirectingLinksOnPage with redirectsTo) |
| OK | Enough 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 thealttext).
Real sample 1: internal links to redirects + old orphan posts (run kppMkYzW3xgU1YDzH, 20 Oct 2026)
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 audited | You 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-wwwand 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/pagethat 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.
| Actor | Job focus | Price | Free pages | Cost 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 / page | First 25 every run | $0.15 |
| dabooti/internal-link-graph-analyzer | Internal-link graph + orphan candidates | $0.001 / page + $0.00005 start | No | ~$0.10 |
| plainrows/broken-link-checker | Broken links, redirect chains, sitemaps | $0.0015 / page | No | $0.15 |
| clearfetch/broken-link-checker | Broken links + redirect chains | $0.002 / page + $0.0005 / URL checked | No | $0.20 + URL checks |
| ib4ngz/internal-link-opportunity-finder | Contextual link opportunities (not an orphan audit) | $0.0065 / page | No | $0.65 |
| martinhida/haw-content-inventory-internal-links | Content inventory + internal link map | $0.01 / page | No | $1.00 |
| searchshark/domain-internal-link-crawler-screamingfrog-alternative | Full link crawl, one row per link | $0.001 / result + $0.01 start | No | depends on link count |
| logiover/website-link-graph-crawler | Link graph crawl | $0.0075 / item | No | depends on rows |
| khadinakbar/broken-link-checker | Broken links, 404s and redirects (per link, not an orphan audit) | $0.001 / link checked + $0.00005 start | No | depends on link count |
| nexgenwatch/internal-link-architecture-verifier | Architecture checks | $0.05 / page + $0.02 start | No | $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
RLmwqj7umaqHpKm3Non crawlee.dev). They are nowREDIRECTEDwithredirectsToandlinksToOldUrl. (2) URLs typed withouthttps://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,NOINDEXandCANONICAL_ELSEWHEREchecks,allIssues,redirectingLinksOnPage,SUMMARY.internalLinksToRedirects, and file URLs (.pdf/.json…) left out oflinkedButNotInList. 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
hrefno longer drops the whole page (it was reported as status 0); failed fetches are nowBROKEN_PAGEwith anerror; 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:clickDepthfrom the homepage, homepage fetched as a free link source, cleaner anchor text (no "- " prefixes, card links reduced to their heading, imagealt), 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
- Redirect Checker & Bulk URL Status (chains, loops, 301 map QA)
- Website SEO Audit + AEO/GEO Checker (full-site crawl)
- AEO & GEO Audit + llms.txt Checker (URL list)
- Content Decay Audit (Search Console)
- Keyword Cannibalization Checker (Search Console)
- Keyword Clustering + Content Briefs
- Search Intent Classifier
- Free local SEO MCP server: cygnix-seo-mcp (
npx -y cygnix-seo-mcp)
Questions or a feature request? Open an issue on this actor's Issues tab. We answer within 24 hours.