Our content audit flagged 123 posts for broken internal links on 29 October 2026. We checked every one. None of them was broken.
That is not a story about a bad tool. The audit was right that something was wrong with those links, and wrong about what. The gap between those two things is where most wasted SEO effort lives.
What the audit reported
123 findings, one per affected post, under a check labelled "Broken internal links (static)". Every other check on the same run came back clean: no thin content, no duplicate titles, no duplicate H1s, no missing meta descriptions, no missing canonicals, no missing FAQ schema.
So a single check accounted for 100% of the issues on the site. That alone is worth a second look. Real problems rarely cluster that neatly.
123 findings, 12 actual URLs
The first thing to do with a large finding count is collapse it. Those 123 posts contained 171 flagged link instances, written as 12 distinct link strings, which resolve to just 9 actual pages. The difference between 12 and 9 is that three of the strings are the same page written with the full domain instead of a leading slash.
Nine is a number you can check by hand in two minutes, and that changes the problem from "audit 123 posts" to "test 9 URLs".
| Target | Instances | Actual response |
|---|---|---|
| /product/site-audit | 37 | 308 redirect |
| /product/content | 34 | 308 redirect |
| /product/links | 28 | 308 redirect |
| /product | 18 | 200 OK |
| /product/reports | 8 | 308 redirect |
| /product/analytics | 6 | 308 redirect |
| /tools/hasten-linklens | 6 | 200 OK |
| /product/opportunities | 1 | 308 redirect |
| https://growthhasten.com/product/site-audit | 15 | 308 redirect |
| https://growthhasten.com/product/content | 10 | 308 redirect |
| https://growthhasten.com/tools/ai-humanizer | 6 | 200 OK |
| https://growthhasten.com/tools/hasten-linklens | 2 | 200 OK |
The last four are absolute URLs. Two are the same destination as a row above, written differently. One, /tools/ai-humanizer, appears nowhere else in the list: it is only ever linked with the full domain.
Zero 404s. Zero dead links. Every single flagged URL resolves to a real page.
Why the check was wrong
The check compares each internal link against two things: the list of published blog slugs, and a hardcoded allowlist of non-blog paths. A link that matches neither is reported as pointing at an unknown target.
That allowlist has gone stale. It contains the site's fixed pages, /about, /contact, /privacy-policy and a few others, plus whatever the product catalog currently defines as a pillar page. The comment above it still says "the nine code-driven product pages". The catalog now defines three. Bare /product is not in the list at all, and neither is anything under /tools/.
So the check is not blind to non-blog links in general. Links to /about and /contact pass cleanly. It is blind to the specific paths that were added or retired after the allowlist was last touched, which is why the flagged set is exactly /product, the six retired /product/* pages and the two /tools/* pages.
That is a more useful diagnosis than "the tool is wrong", because it tells you when it will happen again: every time the site gains a URL pattern that nobody adds to the list.
The real problem the audit walked past
Six of the eight root-relative targets return a 308, not a 200, and so do two of the four absolute ones. Those are retired per-feature product pages that now redirect to sections of a single product page. Counted by instance rather than by URL, 139 of the 171 flagged links point at something that redirects.
That is a genuine finding, and it is the one worth acting on. Internal links should point at the final URL. A link to a redirect costs an extra round trip for every crawler and every reader, and it accumulates silently because nothing ever breaks. Nobody files a bug for a link that works slightly worse than it should. For the difference between redirect types and when each is appropriate, we covered that separately in 301 vs 302 redirects.
The second real finding: 33 of the instances are written as absolute URLs with the domain included, rather than root-relative paths. They work, but they are harder to move, they break on staging, and they are inconsistent with the other 138.
Neither problem is what the audit said. Both were sitting inside the data it returned.
How to check a finding before you act on it
Three steps, and the whole thing took us under ten minutes.
- Collapse the count. Group findings by the thing they point at, not by the page they appear on. 123 became 9. A finding count tells you how widespread something is, not how big it is.
- Test the target directly. One request per unique URL, recording the status code. A redirect, a 200 and a 404 are three different problems with three different fixes, and a "broken link" label flattens all of them.
- Ask what the check can actually see. If it reports something as missing, find out what index it compared against. A checker that only knows your blog will treat your pricing page as nonexistent.
for url in /product /product/content /tools/hasten-linklens; do
echo "$url $(curl -s -o /dev/null -w '%{http_code}' https://example.com$url)"
done
This is the same discipline we applied when we tested whether AI crawlers could read our site: run the check, then verify what the check actually measured before believing the headline number.
What we changed
We are repointing the internal links that target redirects at their final URLs, and converting the absolute ones to root-relative. That is a content edit across a set of posts, not a code change.
We are not "fixing" the 123 findings, because there was nothing to fix. We are replacing the hardcoded allowlist with the real set of published URLs, so the check stops depending on somebody remembering to update a list. We expect that to take the count to zero without a single link changing, which is the tell that the findings were never about the links.
If you want the general version of this work rather than our specific case, how to find and fix broken internal links covers the standard process, and what internal link checkers can actually see covers why different tools disagree about the same site.
A finding count is not a problem count
Ours was 123 findings, 9 pages, 0 broken links and 2 real issues that the label never mentioned.
The instinct an audit creates is to work through the list. The more useful instinct is to spend the first ten minutes asking whether the list is describing what it claims to describe. On this run, acting on the headline would have meant editing 123 posts to fix nothing.
Method and limits
Run on 29 October 2026 against growthhasten.com, 166 published posts. The audit is a static check of internal links in post bodies against the published slug list. Each unique target was then requested once, following no redirects, and its status code recorded.
Two limits. Status codes were captured at a single moment, so a URL that is fine today could break later; this is a snapshot, not monitoring. And the check only looks at links inside post bodies, so links in navigation, footers and templates are out of scope here and need a crawler rather than a content audit.
Questions
Frequently asked questions
Why would an audit report a working link as broken?
Because the checker validates links against an index that does not cover your whole site. Ours compared internal links against the list of blog post slugs, so every link to a product or tool page had nothing to match and was reported as pointing at an unknown target. The links were fine; the index was partial.
How do I tell a false positive from a real broken link?
Request the target URL and read the status code. A 404 is a real broken link, a 301 or 308 is a link that should be repointed at its destination, and a 200 means the checker was wrong. Group findings by target first, since a large finding count usually collapses to a small number of URLs.
Do internal links pointing at redirects actually matter?
They are worth fixing but they are not urgent. Every request through a redirect costs an extra round trip for crawlers and readers, and because nothing visibly breaks these accumulate silently over years. Repoint them at the final URL when you are editing the page anyway.
Should internal links be relative or absolute?
Root-relative paths such as /blog/example are easier to move between environments and will not point at production from a staging build. Absolute URLs work, but mixing both in one codebase makes bulk edits harder and is the kind of inconsistency an audit will keep surfacing.

Written by
Anshuman Sinha
AI SEO Specialist, GrowthHasten
Anshuman Sinha is an SEO Specialist, organic growth strategist, and Computer Science Engineer specializing in Technical SEO, SaaS SEO, Answer Engine Optimization (AEO), Generative Engine Optimization (GEO), and AI-driven growth. He combines technical expertise, data-driven strategies, and content optimization to help businesses strengthen their digital presence and search visibility.
View profile
