Back to News & Insights
SEO September 25, 2026 · 5 min read

A link is not a link until you have read its rel attribute

Four weeks of link prospecting, 106 candidate pages, and a 24-line script that reads one attribute. Plus the four nofollow links on our own site, which are all internal.

A link is not a link until you have read its rel attribute

Link building research has a shape that developers will recognise instantly: a long list of candidates, a conviction about which ones are good, and no measurement. We built the list for CogniPrep, 106 pages that already link to competitors, and then wrote 24 lines of Python before contacting any of them. The script reads one attribute per anchor.

rel on an anchor is the publisher telling search engines how to treat the link. No rel at all: an ordinary link, passes ranking signal. rel="nofollow": the publisher is declining to vouch for the destination. rel="sponsored": this was paid for. rel="ugc": a user wrote this, not the site.

A link that carries nofollow can still send you real visitors, and real visitors are worth having. What it cannot do is help you rank, which means it does not justify a campaign built on the premise that it will.

The important part is that you cannot tell which kind you are looking at from the destination, the anchor text, the design of the site, or its domain authority score. You have to read the attribute on the specific page you would be listed on.

It takes URLs on stdin, fetches each one with a browser user agent because a plain agent gets a different page or none at all, finds anchors whose href matches a competitor, and prints the rel value next to the destination. NONE(dofollow) is printed explicitly rather than left blank, because a missing attribute is the outcome you are hoping for and an empty column is easy to misread as "did not check".

Yes, it parses HTML with a regular expression. It is looking at one attribute of one tag, on pages it does not own, with a human reading every line of output. The failure mode of a bad match is a row that looks wrong and gets opened manually.

Every directory listing was nofollow. All of them, verified on the actual listing pages rather than assumed from the category of site. Weeks of submissions would have bought referral traffic and nothing else. Worth doing deliberately as a traffic play, not worth doing while believing it is an SEO play.

The same domain had different policies on different paths. One careers platform used by many universities serves /resources/ entries with nofollow and /blog/ posts without it. Same site, same template family, opposite value. The correct ask on those sites is therefore a blog post rather than a resource listing, and no amount of domain-level thinking gets you there. You get it by reading the attribute on both paths.

The channel that survived the filter was a different one entirely. University careers pages link out without nofollow, and each already lists four to twelve competitors, so the ask is a slot on a list that exists rather than a favour. That conclusion came out of the script's output, not out of anybody's intuition, and it is the only reason the work went anywhere.

Community posting was gated by account age, not by effort. Of 20 drafted forum posts, 3 could legitimately carry a link under the platform's own rules. The other 17 are worth posting without one or not at all, and knowing which is which before writing them saves the argument later.

The baseline for the whole exercise, from Search Console: 9 external links to the domain, all of them from directories. That number is also why none of this was left as a hunch.

Reading other people's rel attributes makes you think about your own. Ours are not where you would guess.

There are exactly four nofollow links on our privacy page, and every one of them is internal, pointing at /dashboard/settings:

That route is behind auth and disallowed in robots.txt. A crawler that follows the link gets a redirect to the login page, which is a wasted fetch and, in site audit tools, a crawl error to be triaged by a human every month. The nofollow is not a judgement about the destination, it is a request not to bother, and it sits alongside the other two layers: the path is disallowed in robots.txt, and the page itself sends noindex, nofollow.

The same page links out to three external sources: a subprocessor's privacy policy, and the two data protection authorities a reader might want to complain to. Those carry rel="noopener noreferrer" and no nofollow.

That asymmetry is the policy. noopener noreferrer is a security and privacy measure on anything opening in a new tab, applied everywhere. nofollow is a statement about whether we are vouching, and when a privacy policy tells a reader where to file a complaint, declining to vouch for the regulator would be absurd. Editorial links earn a real link. Plumbing gets nofollow.

One more thing the check turned up, and it is the reason to run it on your own pages rather than trusting the codebase.

The robots.ts file carries a comment explaining a belt-and-braces defence: individual game routes are disallowed there, they send noindex, nofollow themselves, "and the public pages that link to them use rel=nofollow".

Want to discuss this further?

Book a free strategy call with our team to see how these insights apply to your specific business goals.

Book a consultation