"Saved successfully" is not a link: verifying backlinks with a real fetch caught six false positives

2026年8月7日2 次浏览来源:Dev.to阅读原文

I keep a ledger of every profile, article, and directory entry that points at the sites I run.

For a while the ledger was updated the obvious way: do the work in the browser, see the success toast, mark the row .

Then I wrote a checker that fetches every recorded URL logged out and asserts that an anchor to the target domain actually exists in the returned HTML.

It immediately found six entries that were marked done and had no link at all.

None of them were mistakes in the sense of "I forgot to save".

Every one of them saved successfully.

The link just did not exist on the public page.

The six A dev community bio field.

The profile page shows the URL as text.

It is never wrapped in an anchor.

The form accepted it, the profile displays it, and it is worth exactly zero as a link.

The same site has a separate single "blog" field that is linkified — one slot, not the bio.

A Q&A site's "Website" field on a new account.

Saved fine.

On the rendered page: .

Low-reputation accounts get their website field stripped of the anchor as an anti-spam measure.

Reputation gate, invisible from the form.

A second Q&A platform's short bio.

Same shape, different reason.

An event platform's profile.

Displays as plain text.

A blog-ranking aggregator.

This one does linkify — through a redirector that is ed in the aggregator's .

So the link exists and is worth nothing.

A blogging platform where four posts saved with empty bodies.

The editor accepted the content in one view and posted an empty document.

Four published posts, zero links, all marked done.

The check Deliberately unglamorous.

Fetch as an anonymous client, parse, look for an anchor whose contains the domain, and record its : Four rules that mattered more than the code: Fetch logged out.

Logged in, some platforms render fields that anonymous visitors (and crawlers) never see.

Measure on a link to your target, not to the platform.

I got this wrong twice: I grabbed "the first anchor on the page", which was the platform's own navigation, and cheerfully recorded for a page where my link was .

Filter by destination first. varies per slot on the same service.

On one publishing platform, body links are but the author name — if you turn it into a link — is and followed.

On a product directory, the product page link is while the profile link is followed. "Platform X is dofollow" is not a fact; "slot Y on platform X is dofollow" is.

One fetch per URL, reused.

Re-fetching the same URL for every recorded row got me rate-limited on one blog host.

Fetch once, evaluate all rows that reference it.

Separating "broken" from "could not measure" The first version of the report collapsed exceptions into the same bucket as HTTP errors.

One flaky connection to one shared page turned into sixteen rows screaming "action required", which is how you train yourself to ignore a report.

Now: HTTP status errors (404, 410) → broken, immediately, no retry.

The server answered clearly.

Exceptions (timeout, DNS, connection reset) → up to 3 retries, then a separate unmeasurable section.

Nothing is ever dropped silently.

If it could not be measured, it says so in its own block.

That distinction is the difference between a report you read and a report you scroll past.

The uncomfortable part The checker exists because I wanted a number I could trust.

The number it produced on the first run was lower than the number in my ledger, and that gap was entirely made of work I had actually done.

Filling a form, getting a green toast, and seeing your URL on the resulting page proves the form worked.

It does not prove an anchor exists.

One of the domains tracked in that ledger is 占い霊感商法相談, a Japanese information site about overcharge trouble — it happened to be on three of the six rows above, which is why the discrepancy was big enough to notice.

If you maintain any kind of "where are we listed" spreadsheet: fetch it, parse it, and check for the anchor.

The spreadsheet is a claim.

The HTML is the evidence.

分享
Baike.dev

baike.dev helps you discover great languages, frameworks, databases, DevOps and cloud-native tools.

Quick links

About

Contribute

Found a great developer tool? Share it with the community.

Submit a tool
© 2026 baike.dev Developer EncyclopediaUpdated daily · Discover great developer tools