Advanced

Nuances & limitations

The edge cases and deliberate trade-offs behind the crawler, the rules and the reports.
  • URL dedup while crawling: the hash is dropped, the query is kept — faceted filters matter for crawl-budget analysis.
  • Tracking params are the exception: utm_*, gclid, gbraid, wbraid, fbclid, yclid, msclkid, _gl, mc_cid, mc_eid are stripped, so /a?utm_source=x and /a are one page; the other params keep their order.
  • A page that failed to load (timeout, network, TLS) → a snapshot with statusCode 0 + crawl:timeout; its page checks are skipped — no false "missing title". The crawler as a whole never dies.
  • Page checks are also skipped for 4xx/5xx snapshots (an HTML 404 for a dead /x.pdf link won't raise canonical:required or duplicate titles): the broken link itself is reported by links:no-broken on the linking page. Site checks still see these snapshots.
  • A page whose redirects end on another origin (an internal /l/x short link → apps.apple.com) is counted in crawlStats.external: it isn't audited and its links aren't crawled; links:no-redirect-chain and links:no-broken still check that link on the linking page. Links of a page redirected inside the site (/a → /b/) resolve against the final URL, and URLs leading to an already crawled final URL give one snapshot, reported under the final URL. An entry (crawl.entry / --url) that redirects to another origin (example.com → www.example.com, http → https) is a crawl:entry-redirect error with the origin to put into site.url / --url; the other entries are still crawled.
  • crawl.respectRobots (default true): <origin>/robots.txt is loaded once and links disallowed for * (or for the group matching crawl.userAgent) are not crawled; Google matching — *, $, longest rule wins, Allow wins ties. Missing or failing robots.txt blocks nothing. crawl.entry URLs (or --url) are always crawled; sitemap+sample samples go through robots.txt. Non-ASCII rules are percent-encoded and hex is compared case-insensitively. The count is crawlStats.disallowed and the crawl log line.
  • maxPages reached → truncated: true in the report — you can see the audit is partial.
  • The Nuxt dev server is not for full crawls: on-the-fly compilation × parallel tabs = worker OOM. Locally use --start against a build or lower concurrency/maxPages; full audits belong on deployed environments.
  • insecureTls sets Playwright's ignoreHTTPSErrors and NODE_TLS_REJECT_UNAUTHORIZED=0 for the process — dev/staging profiles only.
  • Lighthouse requires an installed Chrome (chrome-launcher) and doesn't work with self-signed TLS — run it against deployed environments.
  • The above-fold heuristic viewport is Playwright's default 1280×720 (or crawl.viewport). srcset-only images without src aren't measured.
  • http:x-robots-consistent is part of DevTools Level 1, but the panel has no headers — it's a no-op there.
  • Sitemap function sources are self-contained: no closures over nuxt.config variables.
  • A profile is applied as a defu patch: objects merge, scalars override.
  • One monitor run = one JSON; storage keys: timestamp (monitor) or commit SHA (MR).
  • DOM is parsed by linkedom (server) / DOMParser (panel) — the same rule code runs in both worlds.
  • One failing rule (internal:check-failed, info) never kills the audit; an unknown rule id in the config does — with did-you-mean.