# Broken Link Checker - Find 404s, Dead Links & Redirects (`tinyrex/broken-link-checker`) Actor

Crawl a website and find every broken link: 404s, 5xx, dead external links, broken images and redirect chains, with the pages each one appears on. ~$0.50/1k links checked; robots.txt-skipped links free, no login.

- **URL**: https://apify.com/tinyrex/broken-link-checker.md
- **Developed by:** [TinyRex](https://apify.com/tinyrex) (community)
- **Categories:** SEO tools, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 1,000 link checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Broken Link Checker: find 404s, dead links and redirects on any website

**Crawl a website and get a list of every broken link** — 404 and 410 pages, 5xx server errors, dead external links, broken images, scripts and stylesheets, plus redirect chains — each with **the pages it appears on** and its anchor text, so you know exactly what to fix. Paste a homepage, press Start, download the list as CSV or Excel. **~$0.50 per 1,000 unique links checked; each URL is checked once however many pages link to it; robots.txt-blocked paths and links over your cap are free; no login, no browser, no monthly fee.**

### What you get from the Broken Link Checker

- **Every problem link, ranked** — `broken` (4xx/5xx), `error` (unreachable: DNS, timeout, TLS) and `blocked` (401/403/429/999, usually bot protection on sites like LinkedIn) come first, sorted by how many pages contain them.
- **Where to fix it** — `foundOn` lists up to 10 pages that contain the link, `foundOnCount` how many crawled pages do, plus the `anchorText` (or image alt) of the link.
- **Redirect audit** — by default every redirect is reported too, with its full `redirectChain`, `redirectCount` and `finalUrl` (handy after a migration or an http→https / www switch).
- **Links and assets** — `<a href>` links plus `<img>`, `<script>`, stylesheets, favicons and `<iframe>` sources, internal and external, with `nofollow` flagged.
- **Run summary** — the `SUMMARY` record has per-site totals: pages crawled, links found, checked, broken, unreachable, blocked, redirects, OK.

### Sample output (JSON, real run on crawlee.dev, 13 Oct 2026)

```json
{
  "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"
}
```

Download the dataset as **CSV, Excel or JSON**, or send it to Google Sheets, Slack, Make, Zapier, n8n, a webhook or the Apify API. Schedule it weekly to catch new broken links before your visitors (and Google) do.

### How to use the Broken Link Checker

1. Paste one or more **website URLs** (usually the homepage). The Actor crawls pages on the same domain — `www.` and the bare domain count as one site, other subdomains don't — and collects every link.
2. Set **Max pages to crawl per site** (default 50) and **Max link checks per run** (default 500, up to 50,000). The link-check cap is your cost cap.
3. Choose **What to report**: problems plus redirects (default), problems only, or every link.
4. Run. Your own pages and files are checked first, then external links, most-linked first, so a capped run still covers what matters most.

#### Example input

```json
{
  "startUrls": ["https://example.com"],
  "maxPagesPerSite": 200,
  "maxLinksToCheck": 3000,
  "checkExternalLinks": true,
  "checkAssets": true,
  "reportMode": "problemsAndRedirects"
}
```

#### Example input: internal 404s only (fast weekly check)

```json
{
  "startUrls": ["https://example.com"],
  "maxPagesPerSite": 500,
  "maxLinksToCheck": 2000,
  "checkExternalLinks": false,
  "checkAssets": true,
  "reportMode": "problems"
}
```

| Setting | Default | Notes |
|---|---|---|
| startUrls | (required) | Websites to crawl, one per line |
| maxPagesPerSite | 50 | Internal HTML pages crawled per site (max 5,000) |
| maxLinksToCheck | 500 | Unique links checked per run, all sites together (max 50,000) |
| checkExternalLinks | true | Also check links to other domains |
| checkAssets | true | Also check images, scripts, stylesheets, favicons, iframes |
| reportMode | problemsAndRedirects | `problemsAndRedirects`, `problems` or `all` |
| respectRobotsTxt | true | Skip internal paths disallowed for user-agent \* |
| maxConcurrency | 10 | Requests in parallel (keep it polite) |
| requestTimeoutSecs | 15 | After this a link counts as unreachable |

### How much does it cost to check broken links?

You pay **$0.0005 per unique link checked** (about $0.50 per 1,000), with Bronze/Silver/Gold discounts on higher Apify plans, plus a tiny Actor-start fee. A typical 50-page small-business site has 300–800 unique links, so a full check costs roughly **$0.15–$0.40**. Each URL is checked once per run however many pages link to it, robots.txt-blocked paths are skipped for free, and the run stops cleanly at your max-charge limit.

### FAQ — Broken Link Checker

**How do I find broken links on my website?** Paste your homepage into *Website URLs* and run. The dataset lists every broken or unreachable link with the pages that contain it, so you can open each page and fix or remove the link.

**What counts as a broken link?** Any link whose final response is HTTP 400 or higher (404 Not Found, 410 Gone, 500, 502, 503…), plus links that can't be reached at all (DNS failure, timeout, TLS error). Links answering 401/403/429/999 are reported separately as `blocked`, because sites like LinkedIn or Stack Overflow refuse automated checks even when the page exists — check those by hand.

**Does it follow redirects?** Yes, up to 10 hops. The final status decides whether a link is OK or broken, and `redirectChain` shows every hop. Redirects are reported by default (switch to *problems only* to hide them), which gives you a ready redirect report after a site migration.

**Do broken links hurt SEO?** Broken internal links waste crawl budget and leak link equity, and broken pages frustrate visitors. Fixing them is one of the quickest technical SEO wins. Pair this Actor with the [SEO On-Page Audit](https://apify.com/tinyrex/seo-on-page-audit) for titles, meta tags and canonicals, or the [Sitemap Scraper](https://apify.com/tinyrex/sitemap-scraper) to check every URL in your XML sitemap.

**How often should I check my site for broken links?** Monthly is enough for most small sites; weekly for blogs, shops and sites that link out a lot, and always right after a migration or redesign. Save your input as an Apify task and add a schedule, so a fresh list lands in your dataset (or Slack / email via an integration) automatically.

**How do I fix a broken link?** Open one of the `foundOn` pages, find the link by its `anchorText`, then update it to the right URL, point it at the `finalUrl` of a redirect, or remove it. For a deleted page of your own, add a 301 redirect to the closest live page so old links and bookmarks keep working.

**Does it crawl other websites?** No. It only crawls pages on the domain you enter. External links are checked with a single HEAD request (GET fallback) and never crawled.

**Can I check several sites at once?** Yes, add one URL per line. The link-check cap applies to the whole run.

**Is it a JavaScript crawler?** No, it reads the HTML your server sends (fast and cheap). Links injected only by client-side JavaScript aren't seen.

### Legal and politeness

The Actor fetches only public pages on the website you supply, respects robots.txt by default, runs at modest concurrency and never logs in or bypasses paywalls. It collects link URLs and HTTP status codes, not personal data. Use it on sites you own or are allowed to audit.

### More tools from TinyRex

- [SEO On-Page Audit](https://apify.com/tinyrex/seo-on-page-audit) — titles, meta, H1, canonical, hreflang, Open Graph and schema for a list of URLs
- [Sitemap Scraper](https://apify.com/tinyrex/sitemap-scraper) — every URL in a site's XML sitemaps, with status checks
- [Tech Stack Detector](https://apify.com/tinyrex/tech-stack-detector) — CMS, frameworks, analytics and hosting behind any website
- [Contact Details Extractor](https://apify.com/tinyrex/contact-details-extractor) — emails, phones and social profiles from a domain list

Questions or a site that fails? Open an issue on the Actor's Issues tab and I'll look at it.

# Actor input Schema

## `startUrls` (type: `array`):

Websites to check, e.g. https://example.com. The Actor crawls pages on the same domain (www and non-www count as the same site; other subdomains don't) and checks every link it finds. One site per line.

## `maxPagesPerSite` (type: `integer`):

How many internal HTML pages are crawled per site to discover links.

## `maxLinksToCheck` (type: `integer`):

Hard cap on unique links checked in this run (all sites together). Each unique URL is checked once, however many pages link to it. This is what you pay for.

## `checkExternalLinks` (type: `boolean`):

Also check links that point to other domains (HEAD request, GET fallback). Off = only your own pages and files.

## `checkAssets` (type: `boolean`):

Also check <img>, <script src>, stylesheet, favicon and <iframe> URLs, not just <a href> links.

## `reportMode` (type: `string`):

Which checked links are written to the dataset. Run totals for all links are in the SUMMARY record either way.

## `respectRobotsTxt` (type: `boolean`):

Don't crawl or check internal paths that the site's robots.txt disallows for user-agent \* (default on).

## `maxConcurrency` (type: `integer`):

How many requests run at the same time. Keep it low to be polite to the site.

## `requestTimeoutSecs` (type: `integer`):

How long to wait for each page or link before it counts as unreachable.

## `proxyConfiguration` (type: `object`):

Optional proxy, only needed for sites that block datacenter IPs.

## Actor input object example

```json
{
  "startUrls": [
    "https://quotes.toscrape.com"
  ],
  "maxPagesPerSite": 50,
  "maxLinksToCheck": 500,
  "checkExternalLinks": true,
  "checkAssets": true,
  "reportMode": "problemsAndRedirects",
  "respectRobotsTxt": true,
  "maxConcurrency": 10,
  "requestTimeoutSecs": 15,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `links` (type: `string`):

Reported links with status, HTTP code and the pages they appear on.

## `summary` (type: `string`):

Per-site and total counts of pages crawled and links checked.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        "https://quotes.toscrape.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tinyrex/broken-link-checker").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "startUrls": ["https://quotes.toscrape.com"] }

# Run the Actor and wait for it to finish
run = client.actor("tinyrex/broken-link-checker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    "https://quotes.toscrape.com"
  ]
}' |
apify call tinyrex/broken-link-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tinyrex/broken-link-checker"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/vjZBwr1VGPvqPknEb/builds/Ea80PHFAU303gjUkF/openapi.json
