Broken Links (broken-links)
Summary
Fetches the target page, extracts links from HTML, and verifies them with HEAD requests; optional external link checks.
Classification
- Category:
SEO - Plugin id:
broken-links - Version:
1.1.0 - Target types:
WEBSITE,WEBSHOP - Weight class:
MEDIUM - Risk level: not set on plugin object
- Browser required: No (HTTP / Node — cheerio +
fetchTarget) - Tier / group: Tier 2 — Browser-adjacent crawl (HTTP-only implementation)
Schedule
- scheduleHints:
{ defaultInterval: '0 */3 * * *', priority: 4 } - Prerequisites: None declared on this plugin.
Configurable inputs
Public keys are derived from inputSchema: z.object({ ... }) (underscore-prefixed keys are runtime-only and omitted here).
| Field | Notes |
|---|---|
timeout |
Zod field in inputSchema — see source for defaults, min/max, and .describe(). |
maxLinks |
Zod field in inputSchema — see source for defaults, min/max, and .describe(). |
checkExternal |
Zod field in inputSchema — see source for defaults, min/max, and .describe(). |
crawlDelay |
Zod field in inputSchema — see source for defaults, min/max, and .describe(). |
samplePages |
Optional injected pages when Run on other pages is enabled on the target profile. |
Multi-page mode
When Run on other pages is enabled (Target → Settings → Testing), the worker injects up to 10 diverse URLs from the latest crawl or sitemap. The plugin fetches each page, merges unique links, and checks up to maxLinks total across all pages. Broken link evidence includes sourcePages showing which page(s) contained each link.
Runtime / injected config
- Prior throttle metrics may be injected for adaptive politeness.
Checks that produce findings
These checks run inside this plugin during a single test run. They are not separate tests in the database — each becomes a Finding linked to the Run for broken-links.
| Check | Typical severity | Why |
|---|---|---|
| Broken links summary (≥5 broken, or any 5xx on checked links) | INFO if 5–10 broken and no 5xx; WARNING if >10 broken or any 5xx | Broken links waste crawl budget, leak SEO equity, and erode trust; server errors point to backend failures, not stale URLs. |
| Link check was throttled (rate-limit / WAF signals detected) | INFO | Explains incomplete or slow scans when the site blocks bots — avoids misreading partial results as a clean bill of health. |
How each check works
- Fetch and parse — GETs the target URL and any injected
samplePages(default 15s timeout,TesteBotuser agent). Parses<a href>with cheerio on each page; skips#,mailto:,tel:, andjavascript:links. Merges unique URLs with source-page tracking. - Cap and probe — Collects unique URLs across all scanned pages, then checks at most
maxLinksglobally (default 50, max 10 000). - Probe — Each link gets a HEAD request (8s timeout). Status ≥400 or fetch failure counts as broken. Batches run with concurrency 3 (or 5 when
maxLinks > 200), separated bycrawlDelay(default 200ms) plus adaptive backoff viaAdaptiveThrottleManager(max delay 10s, seeds from prior run_priorThrottleHint). - Finding floor — 1–4 broken links produce no finding (reflected only in score). A finding is created when broken count ≥5 or any checked link returned 5xx (5xx alone triggers a finding even below the count floor).
- Severity — WARNING if any 5xx or broken count >10; otherwise INFO. Throttle finding is always INFO when
totalThrottleEvents > 0. - Score and status — Score =
(healthy / checked) × 100. Run status iswarningif any WARNING finding, elsepassed(this plugin never emits CRITICAL).
Caveats and concerns
- Homepage-only by default — Enable Run on other pages to scan links from crawled sample pages; JS-rendered links are still missed.
- HEAD vs GET — Some servers return 405 on HEAD while GET works, causing false broken reports.
- External links off by default — Stale third-party URLs are ignored unless
checkExternalis enabled. - Not a full crawl — Default 50 links is a sample, not a site-wide audit (
deep-404-scannercovers breadth). - Adaptive throttling — Slow scans after 429/403/WAF detection mean fewer links may be checked within the timeout window.
Source
packages/test-plugins/src/plugins/broken-links.ts