Broken Link Checker: 404s, Redirects & Dead Links avatar

Broken Link Checker: 404s, Redirects & Dead Links

Pricing

$2.00 / 1,000 page checkeds

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

Broken Link Checker: 404s, Redirects & Dead Links

Crawl a website and check every link on its pages: internal, external and, if you like, images, scripts and stylesheets. Finds 404s, server errors, timeouts, DNS and SSL failures and redirect loops, with the page, link text and redirect chain. Pay per page checked.

Pricing

$2.00 / 1,000 page checkeds

Rating

0.0

(0)

Developer

Michael Shanker

Michael Shanker

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Security

Limited permissions

Share

Give it your website and it crawls the pages, then checks every link on every page: links to your own pages, links to other websites, and if you like the images, scripts and stylesheets each page loads. You get one row per broken or problem link, with the page it's on, the link text, what went wrong, and where the redirect chain ended.

It finds:

  • Broken links: 404 Not Found, 410 Gone and other 4xx answers.
  • Server errors: 500, 502, 503 and other 5xx answers (retried before they're reported).
  • Dead domains and servers: DNS failures (the domain doesn't exist), refused or dropped connections, and timeouts.
  • SSL problems: expired, self-signed or wrong-host certificates.
  • Redirect problems: redirect loops and chains longer than 10 hops.
  • Links that can never work for visitors: links to localhost, private network addresses, or with no domain at all (http://).

You pay per page checked, not per link. A page with 300 links costs the same as a page with 3.

Who it's for

  • Site owners and SEO teams who want a list of broken links to fix, page by page.
  • Documentation teams checking that links to other projects haven't rotted.
  • Agencies running a quick link audit on a client site before a launch or migration.
  • Developers who want a scheduled check (run it weekly with Apify Schedules and send the dataset to Slack or email).

How it compares

This ActorTypical browser-based link checkerDesktop crawler (e.g. free versions of SEO spiders)
What you pay forPer page crawled ($2 per 1,000 pages), whatever the number of linksUsually compute time, which grows with page weightA licence, or a free tier with a URL limit
Runs in a browserNo, plain HTTP: fast and lightYes: renders JavaScript, slower and heavierNo
Links added by JavaScript after loadNot seenSeenDepends on settings
External links checkedYes, every one, once per runVariesYes
Images, scripts, stylesheetsOptionalVariesYes
Where the problem isPage, link text, HTML element, final URL, redirect countVariesYes
Runs on a schedule in the cloudYes (Apify Schedules, API, integrations)YesNo, your computer must be on

How it works

  1. Crawl: it starts at each start URL and follows links to pages of the same site (www.example.com and example.com count as one site; other subdomains like blog.example.com are separate sites). It reads up to Max pages per site, breadth first, up to Max clicks from the start page. It obeys your site's robots.txt for every page it reads and every link on your site it checks, and honors a Crawl-delay.
  2. Check: every link found on those pages is checked, wherever it points. Each link is checked once per run even if hundreds of pages have it: a HEAD request first, then a GET (without downloading the body) when HEAD fails or is refused, so servers that answer HEAD wrongly don't show up as broken. Redirects are followed by hand, so you see how many there were and where they ended.
  3. Report: a row per problem link per page it appears on, so you know exactly where to fix it.

It is polite by design:

  • At most 3 requests per second to any one host of your site by default, page fetches and link checks together.
  • At most 10 link checks per second to any other host your pages link to (github.com, a partner site, a CDN). Those hosts get one HEAD request per link (plus a GET when needed), once per run, so this stays light even for a host linked from every page.
  • Your own pages are fetched at most 2 per second, and never faster than the Crawl-delay your robots.txt asks for (honored up to 10 seconds). Link checks on a host with a Crawl-delay wait the delay too, up to 1 second, so a long Crawl-delay doesn't turn a few hundred link checks into an hour. Page fetches go ahead of queued link checks, so the crawl keeps moving.
  • A User-Agent that names it (BrokenLinkCheckBot), retries with back-off on 429 and 5xx answers (a host that answers 429 is also checked more slowly for the rest of the run, down to one request every 2 seconds, and listed in SUMMARY as hostsSlowedBy429), and no requests to local or private network addresses.

Input

FieldDefaultWhat it does
Websites to check (startUrls)One start page per line: https://example.com/, example.com/docs/. Start URLs on the same site share its page limit. Request-list style objects ({"url": "..."}) work too.
Max pages per site (maxPagesPerSite)100Pages crawled and checked per site (1 to 10,000). This also caps the cost per site.
Max clicks from the start page (maxDepth)100 checks the start page's links only; 1 also crawls the pages it links to, and so on.
Also check images, scripts and stylesheets (checkAssets)falseAlso check img (src and srcset), script, stylesheet and icon links, video, audio, source, track, iframe and embed.
List working links too (reportAllLinks)falseSave a row for every link, including working ones (status: ok) and the ones robots.txt kept it away from (not_checked).
Requests per second per host of your site (maxRequestsPerSecondPerHost)31 to 10, for each host of the crawled site. Page fetches stay at 2 per second or less, and follow its Crawl-delay.
Link checks per second per other host (maxRequestsPerSecondPerExternalHost)101 to 20, for each host that is only checked, never crawled.

Example input:

{
"startUrls": ["https://www.example.com/"],
"maxPagesPerSite": 500,
"maxDepth": 10,
"checkAssets": true,
"reportAllLinks": false,
"maxRequestsPerSecondPerHost": 3,
"maxRequestsPerSecondPerExternalHost": 10
}

Output

One row per broken or problem link and the page it was found on (values illustrative):

{
"sourcePage": "https://www.example.com/blog/launch",
"linkUrl": "https://partner.example.org/old-pricing",
"anchorText": "see their pricing",
"linkType": "external",
"status": "broken",
"httpStatus": 404,
"error": "HTTP 404 Not Found",
"finalUrl": "https://partner.example.org/pricing-2023",
"redirectCount": 1,
"element": "a",
"site": "example.com",
"checkedAt": "2026-11-03T18:02:11.000000+00:00"
}
  • linkType: internal (a page of the same site), external (another site) or asset (an image, script, stylesheet and so on).
  • status: what was found.
    • broken: a 4xx answer such as 404 or 410.
    • blocked: 401, 403, 429 or 999. The page needs a login or the server blocks automated checks; it may still work in a browser, so check these by hand.
    • server_error: a 5xx answer, after a retry.
    • timeout, dns_error, ssl_error, connection_error: the server couldn't be reached.
    • too_many_redirects: a redirect loop, or more than 10 redirects.
    • local_address: the link points to localhost or a private network address (it was not requested).
    • invalid_url: the link isn't a usable address.
    • With List working links too: also ok, and not_checked for links robots.txt keeps the checker away from, and for links on a site that kept refusing automated checks (HTTP 429) even when asked slowly. Big sites such as GitHub do this when a page links to them hundreds of times; those links aren't reported as broken, they're counted in SUMMARY (linksNotCheckedRateLimited, hostsGivenUpAfter429) so you can check them by hand.
  • httpStatus is the final status after redirects, finalUrl where the redirects ended, and redirectCount how many there were.
  • anchorText is the link's visible text (or the image's alt text, or its aria-label). element is the HTML tag the link came from (a, area, img, script, link...).
  • If a start page itself can't be read, you get one row for it with element: "start page" and the reason, at no charge.

The run also saves a SUMMARY record (pages checked and charged, problem links by status, per-site counts, whether a site hit its page limit or the run hit your spending cap) and a PAGES record listing every page crawled with its depth and link counts. Download results as JSON, CSV or Excel, or send them to Google Sheets, Slack, Zapier, Make or n8n.

Pricing

Pay per event: $0.002 per page checked ($2 per 1,000 pages). A page is charged once it has been read (an HTML page that answered 200) and all of its links have been checked, whether or not anything was broken. Links themselves cost nothing, and neither do pages that couldn't be read, non-HTML files, or rows for unusable start URLs.

Set a maximum charge per run in the run options: the Actor never starts a page it can't pay for, stops cleanly, and says so in the log and the SUMMARY.

Good to know

  • Plain HTTP, no browser. Links that a page adds with JavaScript after it loads aren't seen. Most sites render their links in the HTML; single-page apps that don't will show few links.
  • Fragments aren't checked. page#section is checked as page; whether #section exists isn't.
  • robots.txt. Pages and links on your own site that robots.txt disallows for this checker are skipped. Links to other sites get a single HEAD (and a GET if needed) per hop, paced per host, without reading those sites' robots.txt.
  • Bot protection. Some big sites (LinkedIn, some news and shop sites behind Cloudflare and similar) refuse automated requests. Those links come back as blocked, not broken.
  • Limits. Up to 1,000 links are checked per page (the rest are counted in SUMMARY) and pages are read up to 5 MB. A link request waits up to 10 seconds for an answer (a timeout isn't retried), and one link gets at most 25 seconds of network time in all, redirects and retries included, so a slow or hanging server can't hold up the crawl. A page waits up to 30 seconds. Each page gets 10 minutes for its link checks: links still waiting then (only on very slow or very link-heavy hosts) are counted in SUMMARY as linksNotCheckedPastDeadline, listed as not_checked when List working links too is on, and the page is saved and charged as usual. A page that is somehow still not done after 15 minutes is dropped with a log line, not charged.
  • Where the time went. Each page's log line shows how long it took and the run clock. SUMMARY has the run's seconds, seconds per site, the Crawl-delay used per site, the time spent waiting for each host's pace (gateWaitSeconds, summed over all requests) and the hosts waited on most.
  • Non-web links (mailto:, tel:, javascript:, #top, app links) are skipped.

Responsible use

Use it on websites you own or manage, or with permission. It reads only public pages, sends no forms, logs into nothing, and collects no personal data: the output is about links, not people.

This Actor isn't affiliated with or endorsed by any of the websites it checks.

More tools from the same developer