How to find every broken link and redirect on a website, with the pages to fix
Updated 2026-10-28 ยท Tool used: Broken Link Checker - Find 404s, Dead Links & Redirects on Apify ยท Price: about $0.50 per 1,000 unique links checked; each URL is checked once however many pages link to it
Broken links frustrate visitors and waste crawl budget, and they pile up quietly: a partner site goes offline, a product page is deleted, an image is renamed after a redesign. Free online checkers usually stop after a few hundred links or show the dead URL without telling you which page links to it.
This guide shows how to crawl one or many websites and get a ranked list of problem links: broken (4xx/5xx), unreachable (DNS, timeout, TLS) and blocked by bot protection, plus every redirect with its chain and final URL. Each row says on which pages the link appears and with what anchor text, so you know exactly what to edit.
Open Broken Link Checker on Apify โSteps
- Put one or more homepages in
startUrlsand setmaxPagesPerSitefor how deep the crawl goes. - Choose whether to check external links and assets (
checkExternalLinks,checkAssets) and setmaxLinksToCheckas a cost cap. - Export the dataset as CSV, sort by
foundOnCountand fix the links used on the most pages first; the SUMMARY record has per-site totals.
Example input
{
"startUrls": [
"https://quotes.toscrape.com"
],
"maxPagesPerSite": 50,
"maxLinksToCheck": 500
}
Example output (one item, shortened)
{
"site": "https://crawlee.dev/",
"url": "https://github.com/apify/crawlee-python/tree/master/templates",
"status": "broken",
"statusCode": 404,
"finalUrl": "https://github.com/apify/crawlee-python/tree/master/templates",
"redirectChain": [],
"redirectCount": 0,
"linkType": "link",
"isInternal": false,
"nofollow": false,
"anchorText": "ready-made templates",
"foundOn": [
"https://crawlee.dev/blog/launching-crawlee-python",
"https://www.crawlee.dev/blog/launching-crawlee-python"
],
"foundOnCount": 2,
"error": null,
"checkedAt": "2026-10-13T07:26:19.132Z"
}
Every run's dataset can be downloaded as JSON, CSV, Excel, XML or HTML from the Apify Console, or via https://api.apify.com/v2/datasets/<datasetId>/items?format=csv.
Run it from code
Python
from apify_client import ApifyClient # pip install apify-client
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run_input = {
"startUrls": [
"https://quotes.toscrape.com"
],
"maxPagesPerSite": 50,
"maxLinksToCheck": 500
}
run = client.actor("tinyrex/broken-link-checker").call(run_input=run_input)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)JavaScript / Node.js
import { ApifyClient } from 'apify-client'; // npm i apify-client
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('tinyrex/broken-link-checker').call({
"startUrls": [
"https://quotes.toscrape.com"
],
"maxPagesPerSite": 50,
"maxLinksToCheck": 500
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);curl (no SDK)
# Runs the actor and returns the results directly (CSV here; use format=json for JSON)
curl -X POST "https://api.apify.com/v2/acts/tinyrex~broken-link-checker/run-sync-get-dataset-items?format=csv" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"startUrls": ["https://quotes.toscrape.com"], "maxPagesPerSite": 50, "maxLinksToCheck": 500}' > results.csv
Get your API token in Apify Console โ Settings โ API & Integrations. The free Apify plan includes monthly credit that is enough to try this.
Use it from an AI agent (MCP)
The Apify MCP server exposes this actor as a tool for Claude, Cursor, VS Code, n8n and other MCP clients. Add this to your client's MCP config (or use the OAuth flow at mcp.apify.com instead of a token):
{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=tinyrex/broken-link-checker",
"headers": {
"Authorization": "Bearer <YOUR_APIFY_TOKEN>"
}
}
}
}
Then ask in plain language, e.g. "Broken link checker for this list and give me a table".
Use cases
- Monthly site health check: schedule a run and compare broken link counts over time.
- After a migration or redesign: catch redirect chains and pages that now return 404.
- Agencies: one broken link report per client site in a single run.
- Link building: find dead external links on other sites as outreach opportunities.
Pricing
Pay per result: about $0.50 per 1,000 unique links checked; each URL is checked once however many pages link to it. You can cap the cost of every run in the run options.
FAQ
How do I find all broken links on my website?
Enter the homepage and run it. The actor crawls internal pages, collects every link and asset and checks each unique URL once. Rows with status broken or error are the ones to fix.
Why are LinkedIn or some other links marked blocked?
Sites with bot protection answer 401, 403, 429 or 999 to automated requests even when the page exists. Those links are reported as blocked, separate from truly broken ones, so you can check them by hand.
Does it report redirects?
Yes. By default every redirect is listed with its full redirectChain, redirectCount and finalUrl. Set reportMode to problems if you do not need them.
What is the difference to the sitemap broken link check?
The sitemap check tests only the URLs listed in your sitemaps. This actor crawls the pages and tests the links inside them, including images, scripts and external links.
Try it on Apify โRelated guides
- How to extract all URLs from a website's sitemap (and find broken links)
- How to audit titles, meta descriptions, H1s and canonicals for hundreds of pages at once
More guides
- Bulk tech stack lookup: a Wappalyzer / BuiltWith alternative for thousands of domains
- How to scrape Greenhouse, Lever and Ashby jobs (plus Personio, Teamtailor, Recruitee)
- How to export all products from any Shopify store to CSV or JSON
- How to scrape jobs from Workday career sites (myworkdayjobs.com)
- How to export products from any WooCommerce store to CSV or JSON
- How to export EU public tenders from TED (Tenders Electronic Daily) to CSV or JSON
- How to scrape remote jobs from Himalayas, Remote OK, We Work Remotely and more in one run
- How to export open EU funding calls (Horizon Europe, Digital Europe, cascade funding) to CSV or JSON
- How to turn any RSS or Atom feed into JSON or CSV (bulk, with monitoring)
- How to extract emails, phone numbers and social links from a list of company domains
- How to take bulk website screenshots from a URL list and save them to CSV or Google Drive
- How to export US federal (SAM.gov) and UK (Contracts Finder) tenders to CSV or JSON
- How to look up French companies by SIREN or SIRET and build a B2B list from Sirene
- How to look up Norwegian companies by organisation number and build lead lists from Brreg
- How to download SEC filings (10-K, 10-Q, 8-K, Form 4) by ticker and search EDGAR full text
- How to validate NPI numbers in bulk and build US healthcare provider lists from NPPES
- How to look up hundreds of UK companies on Companies House at once (profile, officers, PSC)
- How to look up Finnish companies by Y-tunnus and build B2B lead lists from the YTJ register
- How to extract all URLs from a website's sitemap (and find broken links)
- How to transcribe hundreds of audio and video files to text and subtitles with Whisper
- How to extract text from hundreds of PDFs, including scanned ones, in one run
- How to clean an email list before a campaign: bulk MX, disposable and typo check
- How to get Dutch public tenders from TenderNed into a spreadsheet, with daily alerts
- How to audit titles, meta descriptions, H1s and canonicals for hundreds of pages at once
- How to validate LEI codes and find the LEI for a list of companies in bulk
- How to run Lighthouse on hundreds of URLs and get Core Web Vitals in one table