Broken Link Checker: Find 404s, Dead Images & Redirects avatar

Broken Link Checker: Find 404s, Dead Images & Redirects

Under maintenance

Pricing

from $2.00 / 1,000 page checkeds

Go to Apify Store
Broken Link Checker: Find 404s, Dead Images & Redirects

Broken Link Checker: Find 404s, Dead Images & Redirects

Under maintenance

Crawl your website and find every broken link, missing image, and dead script or stylesheet, plus the exact page each one sits on. Fast checks with no browser, redirect detection, external-link checking, and a summary of what failed and why.

Pricing

from $2.00 / 1,000 page checkeds

Rating

0.0

(0)

Developer

Aleksandr Jelohhin

Aleksandr Jelohhin

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

3 days ago

Last modified

Share

Broken Link & Image Checker (with source pages)

Crawl your website and find every broken link and missing image — plus the exact page each one is on, so you know precisely what to fix. It also checks scripts and stylesheets on request, follows and reports redirects, and can verify external links too.

Fast and inexpensive: it uses lightweight HTTP checks and never opens a browser. Run it on demand, on a schedule, or from the API.

Why this one

  • Priced per page, not per link. One page usually has 50–150 links and images, and they're all included. Tools that bill each link checked cost 20–100× more on a real site.
  • Every broken URL comes with the page it's on, so you know exactly where to fix it.
  • No false alarms from bot protection. Links behind a Cloudflare / Akamai / DataDome challenge are reported as blocked, not broken, so your broken count is the real one.
  • Each URL is checked once per run, however many pages link to it, so even big sites finish fast.
  • Images, scripts and stylesheets too, plus redirecting links you should update.
  • Plain HTTP checks, no browser. That's why it's cheap.

What it finds

  • Broken links — 404s, 410s, server errors, timeouts, DNS failures, connection errors
  • Broken images — the <img> sources that don't load
  • Broken scripts & stylesheets (optional)
  • Redirecting URLs — links that only resolve after a 301/302, so you can update them
  • Bot-protection blocks — external URLs that answer with a Cloudflare/DataDome/Akamai-style anti-bot challenge (a 401/403/429/503 with a challenge header or challenge page). Reported separately as state: "blocked" and not counted as broken, because they normally work fine in a browser. A plain 403/503 with no challenge is still reported as broken.
  • For every problem: the source page it was found on, the resource type, the HTTP status, and a reason code

Input

{
"startUrls": [{ "url": "https://example.com" }],
"crawl": true,
"maxPages": 1000,
"checkExternal": true,
"checkImages": true,
"checkScripts": false,
"checkStylesheets": false
}

Output

One dataset row per page that has problems (or every page — your choice):

{
"pageUrl": "https://example.com/blog",
"checked": 124,
"broken": 5,
"redirecting": 12,
"blocked": 2,
"items": [
{ "url": "https://example.com/old-post", "type": "link", "scope": "internal",
"statusCode": 404, "sourceUrl": "https://example.com/blog", "reason": "not_found", "state": "broken" },
{ "url": "https://crozdesk.com/software/apify", "type": "link", "scope": "external",
"statusCode": 403, "sourceUrl": "https://example.com/blog", "reason": "blocked",
"state": "blocked", "blockedBy": "Cloudflare" }
]
}

Plus a run SUMMARY: total URLs checked, broken count, breakdown by reason, and the worst offenders with the pages that link to them.

Use it for

  • Regular link-rot maintenance on a blog or docs site
  • A pre-launch check that nothing 404s
  • Finding images that silently stopped loading after a CDN or media move
  • Bulk-auditing many sites from the API

Note on 403 / 429 (bot protection)

Some third-party sites sit behind Cloudflare, Akamai, DataDome and similar services that challenge automated requests with a 401, 403, 429 or 503. The scanner sends real browser headers to get past the soft blocks, and when a challenge is unavoidable — confirmed by a challenge header or challenge-page body — it labels the URL state: "blocked" (with blockedBy naming the service) instead of broken. A bare 429 (Too Many Requests) is always treated this way (reason: "rate_limited"): it is a rate limit, not a dead link. These do not inflate the broken count or the run's brokenTotal. A genuine 403/503 with no challenge fingerprint is still counted as broken.

Each distinct URL is checked once per run, no matter how many crawled pages link to it — this keeps the run fast and avoids self-inflicted rate limiting. If a page's link batch runs past the per-page analyzer timeout, its outstanding requests are cancelled instead of being left running, so memory stays flat over a long crawl.

  • To count them as broken anyway, set treatBlockedAsBroken: true.
  • To skip external checks entirely, set checkExternal: false.

Pricing

Pay per page checked. All the link and image checks on that page are included, however many there are. Every crawled page counts once, whether or not it has problems.

EventPrice
Page checked$0.002
Run start$0.00005

Examples: a 100-page site costs about $0.20. A 1,000-page site costs about $2.00.

Run it from the API, a schedule or an automation

Run it on demand, schedule it in Apify Console → Schedules (e.g. weekly), or call it from code, n8n, Make or Zapier. One synchronous call returns the rows:

curl -X POST "https://api.apify.com/v2/acts/moonweil~broken-link-scanner/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"startUrls":[{"url":"https://example.com"}],"maxPages":200}'

Add a webhook or Slack / email integration on Run succeeded to get the results pushed to you.

FAQ

Does it check links to other websites? Yes. External links are checked by default (checkExternal). Turn it off to check only your own site.

Why is a link "blocked" instead of "broken"? The other site answered with an anti-bot challenge. Such links almost always work in a browser. Set treatBlockedAsBroken: true to count them anyway.

Can I get only the problems? That's the default (onlyReportProblems: true). Set it to false to get a row for every page.

How big a site can it handle? Up to maxPages (default 1,000). It can also start from your sitemap.xml (useSitemap) and skip sections with excludePatterns.

Does it respect robots.txt? Yes, by default (respectRobotsTxt).