Questions
Why do different tools report different status codes?
Because the server is answering different requests. A status code is a response to one request from one client, and bot filters, geography, rate limits and authentication all change it. The most common case by far is a firewall refusing a request that looks automated while serving a browser normally — which means the checker is reporting honestly and the page is fine.
Reason one — the client looks automated
Bot management classifies requests by user agent, TLS fingerprint, header order and the absence of browser-like behaviour, and refuses the ones it does not like.
The refusal is usually 403, sometimes 503, and occasionally a 200 carrying a challenge page rather than the content.
A default `curl/` user agent is the easiest signature to filter. Comparing `curl -I <url>` against `curl -A 'Mozilla/5.0' -I <url>` identifies this in one step.
This is the explanation for most disagreements between a link checker and a browser, and it means the link is not broken.
Some filters answer differently on a second attempt from the same address, which is why one re-run is worth doing before concluding anything.
Reason two — where the request comes from
Geographic routing serves different infrastructure per region, and those can be in different states.
Content licensed by territory returns 403 outside its region by design.
Some sites block whole hosting and cloud address ranges, which is where most automated tools run from — so a tool in a data centre is refused while a laptop on a home connection is not.
A CDN serving a stale cached copy at one edge and a current one at another produces the same symptom without anyone blocking anything.
DNS answers can differ by region too, so two clients can genuinely be talking to two different servers under the same hostname.
Reason three — rate limiting
A checker crawling many URLs in quick succession can cross a limit partway through, after which every subsequent request is refused.
The signature is distinctive: the first requests succeed and everything after a certain point fails, and re-running produces a different cut-off point.
The correct refusal is `429 Too Many Requests`, but many implementations return 403 instead, which hides what is happening.
A single manual request afterwards succeeds, which is why the URL looks fine when checked by hand.
Published `RateLimit-*` headers on a successful response reveal the policy before you hit it, though many servers enforce a limit without advertising one.
Reason four — session and method
A browser carries cookies from a previous visit. An automated check does not, so a page behind a session returns a redirect to a login rather than the content.
Some servers answer `HEAD` differently from `GET`, or refuse `HEAD` entirely, and tools differ in which they send.
A tool that does not execute JavaScript sees the served HTML, while a browser shows the rendered page — which changes what appears, though not the status.
Consent and region interstitials can return a different status to a client that has never accepted them.
HTTP/2 and HTTP/1.1 clients can also be routed differently by some edge configurations, which changes which backend answers.
Which answer to trust
For whether a visitor can reach the page: a browser, in a private window, from an ordinary connection.
For whether a search engine can reach it: Search Console's URL Inspection, which reports what Google itself received. No third-party tool can answer this.
For whether your own monitoring is being filtered: the server's access logs, which show what actually arrived and how it was answered.
A third-party checker reports what that checker received. That is a fact about the checker's request, and it is still useful — it is how you discover that your site refuses automated clients.
What a scan reports, and its own limits
VeriFixScan reports `availability.status_classification` for the entry URL and `availability.broken_links` for every link followed, with the status each returned.
`infrastructure.waf` reports when a firewall is detected, which is the context that explains a 403 from an otherwise healthy page.
The scan is one client from one network without a session, so it is subject to every cause on this page.
That is why a 403 in a report is worth confirming in a browser before treating a link as broken — and why a 403 that also affects Googlebot is a genuine indexing problem rather than a reporting artefact.
Frequently asked questions
- My link checker says 403 but the page works. Is the link broken?
- Almost certainly not. The destination refused an automated request. Confirm in a browser before changing or removing the link.
- Why do the first URLs pass and later ones fail?
- That pattern is rate limiting. The correct response is 429, though many implementations return 403 instead.
- Which tool tells me what Google sees?
- Only Search Console's URL Inspection. It reports what Google's own fetch received, which no third-party checker can observe.
Sources
Related
VeriFixScan crawls a site and applies its checks to every page it reaches, keeping the evidence behind each finding. Scanning one website is free.
Scan a website