Link Rot Checker: Dead Links with Closest Archived Copy avatar

Link Rot Checker: Dead Links with Closest Archived Copy

Pricing

from $0.60 / 1,000 link checkeds

Go to Apify Store
Link Rot Checker: Dead Links with Closest Archived Copy

Link Rot Checker: Dead Links with Closest Archived Copy

Broken link checker for a list of URLs. One row per link: alive, redirected or dead, the HTTP status, the full redirect chain and, for every dead link, the newest working copy in the Wayback Machine to replace it with. Blocked and unreachable links are never charged.

Pricing

from $0.60 / 1,000 link checkeds

Rating

0.0

(0)

Developer

Adriana Voss

Adriana Voss

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

Share

Paste a list of URLs and get one row per link: alive, redirected or dead, the HTTP status, the full redirect chain, and for every dead link the newest copy the Wayback Machine saved while the page still worked, ready to use as the replacement. A broken link checker that also hands you the fix. No API key, no account, no proxy.

Who it's for

  • Content and SEO teams cleaning outbound links in a blog, a docs site or a knowledge base, who need the dead ones and something to point them at instead.
  • Researchers, librarians and editors checking the references of a paper, a report or a wiki article for link rot, and swapping in an archived address where the source is gone.
  • Newsletter and course authors checking every link before a send or a relaunch.
  • Developers and agencies auditing the links of a site they inherited, straight from a sitemap or a database export.

What you get

One flat row per link:

WhatColumns
The verdictsourceUrl, linkStatus, isBroken, statusCode, reason
Where it goes nowfinalUrl, redirectKind, redirectCount, redirectChain
The replacementarchiveStatus, archivedUrl, archivedAt
DetailsblockedBy, contentType, responseTimeMs, scrapedAt

Three example rows, shortened. They are the three pre-filled links, read on 2026-10-11:

sourceUrllinkStatusstatusCodereasonarchiveStatusarchivedUrlarchivedAt
https://example.com/alive200OKNOT_CHECKED
https://example.com/this-page-does-not-existdead404HTTP_404NONE
https://www.google.com/reader/about/dead404HTTP_404FOUNDhttps://web.archive.org/web/20210503140021/https://www.google.com/reader/about/2021-05-03T14:00:21Z

What each status means

linkStatusMeaningCharged
aliveAnswers normally at the address you gave.yes
redirectedWorks, but at another address. redirectKind says how far it moved.yes
dead404, 410, another error status, a domain that no longer exists, a refused connection or an invalid certificate.yes
blockedThe site refused the check (403, 429, a login wall, a bot-protection page). The page is probably fine in a browser, so it is not called dead.no
unreachableNo answer after two attempts. It cannot be said whether the link is dead.no

What each redirect type means

redirectKindMeaning
same-pageOnly https, www or a trailing slash changed. Nothing to fix.
same-siteAnother page on the same site.
other-siteAnother site. The original may be gone, so an archived copy is looked up.
to-homepageA deep link that now lands on a front page. The content is usually gone even though the status is 200, so an archived copy is looked up.
  1. In the Apify Console. Open the actor page and click Start — the urls field is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found.
  2. Via the API. Call it directly with a POST request — no Console needed once you have an API token:
    curl "https://api.apify.com/v2/acts/accountable_eel~link-rot-check/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{"urls":["https://example.com","https://example.com/this-page-does-not-exist","https://www.google.com/reader/about/"]}'
  3. On a schedule. Save this actor as an Apify Task with the input you want, then add a Schedule (hourly, daily, weekly) so it runs on its own — no server of your own required.

Input

{
"urls": [
"https://example.com",
"https://example.com/this-page-does-not-exist",
"https://www.google.com/reader/about/"
]
}

One URL per line. Each one is opened the way a browser would open it, redirects are followed, and you get back whether it is alive, redirected or dead. A dead link also gets the newest copy the Wayback Machine saved while the page still worked. Accepted formats: https://example.com/some/page, example.com/pricing, http://old-site.org/article.html.

Output

queryfoundstatussourceUrllinkStatusisBrokenstatusCodereasonfinalUrlredirectKindredirectCountredirectChainarchiveStatusarchivedUrlarchivedAtblockedBycontentTyperesponseTimeMsscrapedAt
https://example.comtrueOK<response time (ms)>1970-01-01T00:00:00.000Z

A line that is not a web link, a blocked link and an unreachable link come back as one row with "found": false and a message that says why. They are never charged.

Example runs

Three inputs that need no credentials of any kind and return rows as they stand. Paste one into the Input tab and press Start.

1. Which of these links are dead, and what can replace them?

{
"urls": [
"https://example.com",
"https://example.com/this-page-does-not-exist",
"https://www.google.com/reader/about/"
],
"checkArchive": true
}

2. A permanent archived address next to every reference, working or not

{
"urls": [
"https://www.w3.org/TR/html401/",
"https://www.rfc-editor.org/rfc/rfc2616",
"https://example.com"
],
"checkArchive": true,
"archiveLiveLinks": true
}

3. A fast status and redirect pass over a list, dead links only in the result

{
"urls": [
"http://example.com",
"https://example.org/missing-page",
"https://www.iana.org/domains/example"
],
"checkArchive": false,
"includeKeywords": ["dead"]
}

Pricing

Pay-per-event. A flat per-run fee covers session/proxy warmup; each independent source is billed under its own event, only when that source actually returns data — see .actor/pay_per_event.json for exact prices. A miss is never charged.

You pay once per link that got a verdict, and nothing else:

  • A blocked link, an unreachable link and a line that is not a URL are free.
  • The archived copy is included in the price of the link. There is no separate charge for it.
  • A row hidden by "Only keep rows containing" is not returned and not charged, so example 3 above pays for the dead links only.
  • Use "Stop after this many results" to put a ceiling on a long list.

Use it from Clay, n8n, Make, or an AI agent

This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.

curl "https://api.apify.com/v2/acts/accountable_eel~link-rot-check/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
-X POST \
-H "Content-Type: application/json" \
-d '{"urls":["https://example.com","https://example.com/this-page-does-not-exist","https://www.google.com/reader/about/"]}'

n8n. Add an HTTP Request node: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~link-rot-check/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body Content Type JSON, JSON Body {"urls":["https://example.com","https://example.com/this-page-does-not-exist","https://www.google.com/reader/about/"]} (swap in an expression from an earlier node for a real value).

Clay. Add an "HTTP API" column: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~link-rot-check/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body {"urls":["{{link}}"]}, mapping the row's link into the urls array.

MCP. In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "broken link checker" — the agent will find and run this actor.

Where the data comes from

  • The status and the redirect chain come from opening each link once with a normal browser request and following every redirect. Page bodies are not downloaded.
  • The archived copy comes from the Internet Archive's public Wayback Machine index. The row carries the newest capture taken while the page still answered normally, not a capture of the error page that replaced it.

Limits, stated plainly

  • A blocked link is not a verdict. Some sites refuse every request that does not come from a home connection. Those rows say blocked and are free. Open them in a browser to be sure.
  • A page that says "not found" with status 200 counts as alive. The check reads the status and the redirects, not the text of the page. A deep link that was redirected to a front page is flagged as to-homepage.
  • The Wayback Machine throttles bulk lookups. On a long list with very many dead links it may stop answering part-way. Those rows say RATE_LIMITED or ERROR in archiveStatus, which means "not known this run", never "no copy exists". Run those links again later.
  • NONE means no working capture. A page the archive only ever saved as an error page has no copy worth linking to.
  • One moment in time. A server that was down for the two attempts is reported as it was. Server errors (5xx) are retried once before they count as dead.
  • It checks the links you give it. It does not crawl a site to find links.
  • No login, no cookies, no JavaScript. A link that only works when signed in is reported as blocked with the reason LOGIN_REQUIRED.

Data & privacy

The actor opens the URLs you list and reads the public Wayback Machine index. It stores nothing between runs and returns no personal data beyond what your own URLs contain.

FAQ

Why is a link I can open in my browser reported as blocked? The site refuses automated requests. The row is free, and blockedBy names the protection when it could be identified.

Why does a dead link have no archived copy? Either the Wayback Machine never saved the page while it worked (NONE), or it did not answer during this run (ERROR, RATE_LIMITED).

Is the archived copy the closest one to today? Yes: it is the most recent capture in which the page still returned a normal response.

Can I check thousands of links? Yes. Status checks run in parallel, with no more than two requests at a time to any one site, so a thousand links take a few minutes. An archive lookup can take 10 to 15 seconds and they run three at a time, which is about 900 dead links an hour. For a list with more dead links than that, turn "Find an archived copy for broken links" off for a first pass, then run the dead ones again with it on.

Do I need a proxy? No.

  • HTTP Status Lookup for status and headers only.
  • Redirect Chain Tracer for every hop of a redirect.
  • Wayback Machine Snapshot Lookup for a site's first and last capture and its age.
  • Soft 404 Detector for pages that say "not found" with status 200.
  • Sitemap URL Discovery to get the list of URLs to check.