Backlink Monitor & Lost Link Alerts
Pricing
from $3.00 / 1,000 backlink checkeds
Backlink Monitor & Lost Link Alerts
Monitor backlinks you already earned or paid for. Detect removed links, dofollow-to-nofollow changes, anchor edits, redirects and noindex pages with structured before/after data.
Pricing
from $3.00 / 1,000 backlink checkeds
Rating
0.0
(0)
Developer
Vadim Bezrukov
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
10 days ago
Last modified
Categories
Share
Monitor backlinks you already earned or paid for. This Actor re-checks a
watchlist of known placements and tells you when a link disappears, becomes
nofollow, changes anchor text, picks up sponsored/ugc, moves behind a
redirect, or lands on a noindex page.
It is not an Ahrefs replacement, a backlink discovery database, or a site crawler. You supply the referring pages.
What changes it catches
| Code | Meaning |
|---|---|
BASELINE | First successful observation for a placement |
LINK_LOST | Link still missing after two-strike confirmation |
LINK_RESTORED | A previously lost link is present again |
ANCHOR_CHANGED | Visible anchor text changed |
TARGET_CHANGED | Matched href changed |
TARGET_REDIRECT_CHANGED | Target redirect destination changed |
DOFOLLOW_TO_NOFOLLOW / NOFOLLOW_TO_DOFOLLOW | Effective follow signal flipped |
SPONSORED_ADDED / SPONSORED_REMOVED | rel=sponsored appeared or left |
UGC_ADDED / UGC_REMOVED | rel=ugc appeared or left |
PAGE_NOINDEXED / PAGE_REINDEXABLE | Page robots/noindex flipped |
SOURCE_HTTP_STATUS_CHANGED / TARGET_HTTP_STATUS_CHANGED | Observed HTTP status changed |
One observation can carry several codes. SUSPECTED_LOSS is a status, not a
confirmed loss.
Who should use it
SEO agencies, link-building agencies, affiliate/PR teams, companies that bought guest posts, and freelancers watching several client portfolios. The job is: I paid for or earned these links. Tell me immediately when one disappears or loses value.
Example tasks
Three unpublished examples live in examples/. Replace the sample URLs before
a real watchlist, and keep monitorKey stable across scheduled runs.
| Task | What it shows | Dataset view |
|---|---|---|
| Paid backlink link-loss monitor | A paid placement disappeared | Lost / degraded links |
| Guest-post dofollow change monitor | Rel or anchor changed | Changes |
| Agency backlink portfolio watchlist | Several clients in one batch | Current status |
30-second example
{"monitorKey": "client-a","placements": [{"id": "guest-post-001","sourceUrl": "https://www.python.org/","expectedTarget": "https://docs.python.org","label": "python.org link to the Python docs"}],"mode": "changesOnly","baselineMode": "emitBaseline","confirmLossAfter": 2}
The Console demo uses mode: all, returning BASELINE first and NO_CHANGE
on an unchanged repeat. The monitoring example above stores last-good state
and emits BASELINE on its first run. Schedule the same
input daily. Unchanged placements stay quiet unless mode is all.
Example LINK_LOST
{"recordType": "CHANGE","status": "LINK_LOST","placementId": "guest-post-001","changeTypes": ["LINK_LOST"],"changes": {"linkFound": { "previous": true, "current": false },"matchedTarget": { "previous": "https://iana.org/domains/example", "current": null }},"lossConfirmationCount": 0}
Example DOFOLLOW_TO_NOFOLLOW
{"recordType": "CHANGE","status": "CHANGED","placementId": "guest-post-001","changeTypes": ["DOFOLLOW_TO_NOFOLLOW", "ANCHOR_CHANGED"],"changes": {"rel": { "previous": [], "current": ["nofollow"] },"anchorText": { "previous": "Learn more", "current": "example.com" }}}
Input watchlist
Each placement needs a stable id, sourceUrl and expectedTarget. Optional
expectedAnchor and expectedRel choose which link to watch when the page
has more than one match; label is copied onto every row. A repeated id is
checked once: later placements with that id get INVALID_INPUT /
DUPLICATE_ID rows and are not billed. Maximum 5,000 placements per run. Target matching is
explicit: normalized (default), exact, or domain. Query parameters are
never dropped. www vs apex is significant in normalized and exact
mode; domain treats www.example.com and example.com as the same host
and does not treat blog.example.com as the same host.
Scheduling and webhooks
- Save the watchlist as an Actor Task with a stable
monitorKey. - Schedule it daily or weekly.
- Add a webhook on
SUCCEEDEDand filter Dataset rows wherestatusisCHANGED,LINK_LOSTorSUSPECTED_LOSS. A run that reaches the charge limit still succeeds:RUN_SUMMARYsaysBILLING_LIMIT_REACHED, the checked rows are in the Dataset and the skipped placements areNOT_CHECKEDrows.
Large watchlists need a run timeout that fits them. Before the timeout, the
Actor stops starting checks and keeps time to deliver rows, save state and
charge. Placements it did not reach get NOT_CHECKED / TIME_LIMIT, are not
billed and keep their previous state. The run still succeeds with status
TIME_LIMIT_REACHED in RUN_SUMMARY; give it a longer timeout or split the
watchlist across Tasks.
The named Key-value store backlink-monitor-state holds last-good snapshots
and pending-loss counters. Dataset runs are the history.
Pricing examples
Private launch configuration: $0.003 per successfully checked backlink plus the platform
apify-actor-start event ($0.005 per GB, minimum one event). Platform usage is
included. The start event is charged even when all source checks fail.
| Daily watchlist | Checks / month | backlink-checked |
|---|---|---|
| 50 | 1,500 | $4.50 |
| 500 | 15,000 | $45 |
| 2,500 | 75,000 | $225 |
The monthly totals including 30 starts at 1024 MB are $4.65, $45.15 and $225.15. One check costs $0.008; the 5,000-placement maximum costs $15.005 at 1024 MB. At 4096 MB the start fee is $0.020, so the maximum is $15.020.
Retries, source failures, robots blocks, parser failures, invalid input and
duplicate ids are not billed. Unchanged successful checks are billed once. Before fetching, the Actor reserves enough budget for each selected placement.
Placements beyond that capacity receive NOT_CHECKED / BUDGET_LIMIT, incur no
check charge and keep their previous state. Capacity is conservative: a failed
selected check does not cause an extra placement to be fetched. The partial run
ends with BILLING_LIMIT_REACHED; verified output remains available. Increase
the limit or submit only the skipped placements in the next run.
Two-strike loss confirmation
False lost-link alerts are expensive. Default confirmLossAfter is 2:
- Link present → last-good stored.
- Next successful page check, link missing →
SUSPECTED_LOSS. Last-good is not overwritten. - Still missing on the next successful check →
LINK_LOST. - If the link returns before confirmation, the suspected loss is cleared.
A source HTTP 404 or 410 is a successful observation that the page is gone,
so it counts toward two-strike loss (the Dataset sourceStatus shows 404/410).
A brief CDN 404 can therefore confirm loss; raise confirmLossAfter if that
is too sensitive. HTTP 403, 429, timeouts and 5xx never count.
Failure semantics
LINK_NOT_FOUND is not SOURCE_FAILED. A 403, 429, timeout, 5xx, CAPTCHA/
challenge page, parser failure, or HTML with zero <a href> links is
never LINK_LOST. The source page must be fetched and parsed with at
least one HTML link before absence can count as a loss observation. One bad
placement never kills the batch. If every placement independently fails, the
run still SUCCEEDED with per-item SOURCE_FAILED or INVALID_INPUT rows.
Limitations
- HTTP HTML only. No JavaScript rendering, no CAPTCHA solving, no login.
- Does not discover unknown backlinks or crawl a site.
- Does not claim Google index status, PageRank, domain authority or SEO value.
follow-like HTML is not a ranking guarantee.crates.io-style JavaScript marketplaces often return HTML with no<a href>. That isSOURCE_FAILED(NO_HTML_LINKS), not verified link loss and not a browser fallback.
API / MCP usage
Direct MCP endpoint:
https://mcp.apify.com?tools=automa-flow/backlink-monitor
Ask an agent to monitor a named watchlist of source/target pairs and return
only LINK_LOST and DOFOLLOW_TO_NOFOLLOW rows. Bound spend with
maxTotalChargeUsd (at least $0.008 for one check at 1024 MB).
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automa-flow/backlink-monitor').call({monitorKey: 'client-a',placements: [{id: 'guest-post-001',sourceUrl: 'https://www.python.org/',expectedTarget: 'https://docs.python.org',},],});
Replace automa-flow with your account if you are running a private copy.
Source and legal notes
Only user-supplied public HTTP(S) URLs on ports 80/443 are fetched. Private,
loopback, link-local, multicast, metadata and credentialed URLs are rejected,
including redirect hops. The Actor respects robots.txt when enabled. It
does not bypass authentication, paywalls, CAPTCHAs or access controls. Report
HTML facts; do not treat them as search-engine scoring.