# Broken Link Checker — Find 404s, Dead Links & Redirect Issues (`khadinakbar/broken-link-checker`) Actor

Crawl a website, scan a URL list, or verify all URLs from a sitemap. Returns broken links with source page, anchor text, status, redirect chain, and failure class — for SEO audits, content QA, and migration validation.

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

## Pricing

from $1.00 / 1,000 link checkeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Broken Link Checker — Find 404s, Dead Links, Redirects & Slow Pages

Scan a **whole website**, a **list of URLs**, or every URL in a **sitemap.xml** and find every broken link — 404s, server errors, timeouts, SSL/DNS failures, redirect chains, and slow pages. Each broken link comes with the **source page** that linked to it, the **anchor text**, the **HTTP status**, the **redirect chain**, and a **failure class** like `broken`, `redirect_loop`, `timeout`, `dns_error`, or `ssl_error`. Built for SEO audits, content QA, site migrations, and AI-agent link health checks.

Try it now — paste a website URL and get a CSV of every broken link in minutes.

### What does Broken Link Checker do?

Broken Link Checker is a fast, configurable link auditor that runs on the [Apify platform](https://apify.com/about). Three modes cover every link-checking workflow:

- **Crawl mode** — start at a URL, crawl up to N pages on the same domain, extract every link (`<a>`, `<img>`, `<script>`, `<link>`, `<iframe>` if enabled), and verify each one.
- **List mode** — paste up to 5,000 URLs and get HTTP status + classification for each. No crawling.
- **Sitemap mode** — point at a `sitemap.xml` (sitemap-index files supported) and verify every URL inside.

For every URL the actor tries `HEAD` first (fast, ~1 KB), then falls back to `GET` if the server returns an ambiguous code (405, 403, 501, etc.) — exactly how a real browser would. Redirects are tracked hop-by-hop so you can see the full chain. Output ships as a structured dataset you can download as CSV / JSON / Excel, query via the [Apify API](https://docs.apify.com/api/v2), schedule, or call from Make / Zapier / your own code.

### Why use Broken Link Checker?

- **Fix SEO-killing 404s** — broken internal links bleed PageRank and frustrate users; broken outbound links damage E-E-A-T signals.
- **Validate site migrations** — confirm every old URL 301s correctly to its new home; flag redirect chains that lose link equity.
- **Audit content at scale** — agencies running monthly link-rot reports, enterprises auditing 10,000+ blog posts.
- **Pre-launch QA** — catch dead links in marketing pages, docs, and email templates before they go live.
- **AI agents** — perfect MCP tool for Claude / GPT agents auditing site quality. Predictable cost (~$0.001 per URL), structured JSON output, no setup required.

### How to use Broken Link Checker

1. Open the actor on Apify Console and click **Try for free**.
2. Pick an **input mode**:
   - `crawl` → paste a website URL into **Website URL** and set **Max pages**.
   - `list` → paste your URLs into **URLs to verify**.
   - `sitemap` → paste your sitemap.xml URL into **Website URL**.
3. (Optional) Tune **Max links to verify**, toggle **Check external links**, and enable **Check images, scripts, and stylesheets** for a full content audit.
4. Click **Save & Start**. The actor reports progress in real-time.
5. When finished, open the **Output** tab → download as **CSV**, **JSON**, or **Excel**, or pull via the [Apify API](https://docs.apify.com/api/v2).

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `crawl` | One of `crawl`, `list`, `sitemap`. |
| `startUrl` | string | — | Required for `crawl` and `sitemap`. The site to crawl or the `sitemap.xml` URL. |
| `urls` | array | — | Required for `list`. Up to 5,000 URLs. |
| `maxPages` | int | 50 | Max internal pages to crawl (`crawl` mode only). |
| `maxLinksToCheck` | int | 500 | Hard cap on links verified per run. |
| `checkExternalLinks` | bool | true | Verify links pointing to other domains. |
| `checkAssets` | bool | false | Also check `<img>`, `<script>`, `<link>`, `<iframe>` URLs. |
| `onlyReportBroken` | bool | true | Dataset contains only failing links. Set to `false` for a full inventory. |
| `slowThresholdMs` | int | 5000 | Above this, link is classified `slow`. |
| `requestTimeoutMs` | int | 15000 | Per-request timeout in milliseconds. |
| `maxConcurrency` | int | 20 | Parallel verification requests. |
| `maxRedirects` | int | 10 | Max hops before classifying as `redirect_loop`. |
| `userAgent` | string | ApifyBrokenLinkChecker UA | Custom User-Agent for all requests. |
| `proxyConfiguration` | object | Apify datacenter | Proxy settings; switch to residential only if blocked. |

### Output

Each broken link becomes a structured record in the dataset.

```json
{
    "url": "https://example.com/missing-page",
    "finalUrl": "https://example.com/missing-page",
    "status": 404,
    "statusText": "Not Found",
    "classification": "broken",
    "isBroken": true,
    "sourceUrl": "https://example.com/blog/post-with-broken-link",
    "anchorText": "see our pricing",
    "linkType": "a",
    "allSources": [
        { "sourceUrl": "https://example.com/blog/post-with-broken-link", "anchorText": "see our pricing", "linkType": "a" }
    ],
    "method": "GET",
    "hops": 0,
    "redirectChain": [],
    "durationMs": 234,
    "error": null,
    "checkedAt": "2026-05-03T19:55:00.000Z"
}
````

The final record is a `_summary: true` row with totals and a per-class breakdown.

You can download the dataset in JSON, CSV, Excel, HTML, RSS, or XML, or pull it via API.

### Data table

| Field | Description |
|---|---|
| `url` | Normalized URL that was checked. |
| `finalUrl` | URL after following redirects. |
| `status` | HTTP status of the final response. `null` if no response. |
| `statusText` | HTTP status reason phrase. |
| `classification` | One of `ok`, `slow`, `redirect_chain`, `redirect_loop`, `broken`, `timeout`, `dns_error`, `ssl_error`, `connection_refused`, `blocked`, `error`. |
| `isBroken` | `true` for any failing class — easy filter for actionable rows. |
| `sourceUrl` | First page on the crawled site that linked to this URL. |
| `anchorText` | Visible link text (or alt/title for assets), trimmed and capped at 200 chars. |
| `linkType` | How it was referenced: `a`, `img`, `script`, `link`, `iframe`, `sitemap`, `list`. |
| `allSources` | Up to 5 source pages that link to this URL. |
| `method` | HTTP method used for the final response (`HEAD` or `GET`). |
| `hops` | Redirect hops followed. |
| `redirectChain` | Array of `{ from, to, status }` per hop. |
| `durationMs` | Total verification time. |
| `error` | `{ code, message }` when verification failed. |
| `checkedAt` | ISO 8601 timestamp. |

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

Broken Link Checker uses **pay-per-event** pricing — only pay for what you actually verify.

| Event | Price |
|---|---|
| Actor start | $0.00005 |
| Link checked | $0.001 per URL verified |

**Typical costs:**

- Small site crawl (50 pages, ~200 links) → **~$0.20**
- Bulk URL list (1,000 URLs) → **~$1.00**
- Full sitemap (5,000 URLs) → **~$5.00**

There are no monthly fees, no setup fees, and runs that fail before discovering links cost only the negligible $0.00005 start fee.

### Tips & advanced options

- **Cut cost in half** by setting `checkExternalLinks: false` — most sites have more outbound links than internal pages.
- **Skip asset checks** (`checkAssets: false`) for hyperlink-only audits — typical sites have 5-10× more assets than `<a>` links.
- **Use `mode: 'list'` for outreach link audits** — paste your placement URLs directly without crawling.
- **Use `mode: 'sitemap'`** for full URL coverage on sites with deep navigation that's hard to crawl.
- For **rate-limited targets**, drop `maxConcurrency` to `5-10` and increase `requestTimeoutMs`.
- For **fragile sites that block bots**, switch `proxyConfiguration.apifyProxyGroups` to `["RESIDENTIAL"]` and customize `userAgent` to a real browser string.
- **Combine with other Apify tools**: pair with [Bulk Website Contact Extractor](https://apify.com/khadinakbar/bulk-website-contact-extractor) to find broken backlinks AND contact owners, or feed sitemaps from [Sitemap URL Extractor](https://apify.com/mikolabs/sitemap-url-extractor).

### Schedule recurring link audits

On Apify Console, open the **Schedules** tab on the actor and add a cron expression — e.g. `0 6 * * 1` to run every Monday at 6 AM. Combine with the [Apify webhook integration](https://docs.apify.com/platform/integrations) to push results into Slack, Google Sheets, or your own monitoring stack.

### FAQ

**Does it follow `robots.txt`?**
The actor verifies links by issuing a single HEAD/GET per URL — the same load a normal browser visit would create. For polite crawling, the `crawl` mode respects `robots.txt` via Crawlee's defaults; you can override per request if needed.

**Can it check authenticated pages?**
Not yet. Add an issue if you'd like cookie-based authentication added.

**What counts as a "broken" link?**
The `isBroken` flag is `true` for these classes: `broken` (4xx/5xx, except 403/429), `timeout`, `dns_error`, `ssl_error`, `connection_refused`, `redirect_loop`, and `error`. The classes `slow`, `redirect_chain`, and `blocked` (403/429) are reported but not flagged broken — they're worth reviewing but may be intentional.

**Why HEAD first?**
HEAD requests are 5-10× cheaper than GET for the target server and faster for you. Some servers refuse HEAD with 405/403/501 — when that happens we automatically retry with GET, so you still get an accurate result.

### Disclaimer

Broken Link Checker only verifies HTTP responses to URLs. It does not download page content beyond crawl mode (which fetches HTML to extract links). Use this actor responsibly: respect target site Terms of Service, set sensible concurrency for small sites, and do not use the tool to probe systems you do not own or have permission to audit. The actor reports raw HTTP signals — interpretation (whether a 403 is intentional access control or a broken link) is up to you.

### Support and feedback

Found a bug or want a feature? Open an issue on the actor's [Issues tab](https://apify.com/khadinakbar/broken-link-checker/issues) on Apify Console.

# Actor input Schema

## `mode` (type: `string`):

How URLs are sourced. 'crawl' starts at startUrl and crawls the site to maxPages, extracting and verifying every link found. 'list' verifies only the URLs in the urls array (no crawling). 'sitemap' fetches sitemap.xml from startUrl and verifies every URL found. Default: 'crawl'. Choose 'list' for outreach link audits and 'sitemap' for full-site URL coverage without crawling overhead.

## `startUrl` (type: `string`):

The URL to start crawling from (mode='crawl') or the sitemap.xml URL (mode='sitemap'). Must include the protocol — example: 'https://example.com' or 'https://example.com/sitemap.xml'. Crawler stays within the same registrable domain by default. Ignored when mode='list'.

## `urls` (type: `array`):

List of URLs to check directly without crawling. Used only when mode='list'. Each entry must be a full URL including protocol — example: \['https://example.com/page1', 'https://example.com/missing']. Up to 5000 URLs per run. Ignored when mode='crawl' or 'sitemap'.

## `maxPages` (type: `integer`):

Maximum number of internal pages to crawl (mode='crawl' only). Higher values find more broken links but take longer. Default: 50. Set to a small value (5-10) for quick audits; 200-500 for thorough site reviews.

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

Maximum number of unique links to verify per run. Caps cost on link-heavy sites. Default: 500. Each verified link triggers a 'link-checked' charge of $0.001.

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

Verify links pointing to other domains, not just internal links. Default: true. Set to false to focus only on same-domain links and reduce cost (typically halves the link count).

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

Also verify <img>, <script>, <link>, and <iframe> resource URLs in addition to <a> hyperlinks. Default: false. Enable for full content audits; disable for hyperlink-only checks (faster and cheaper).

## `onlyReportBroken` (type: `boolean`):

If true, dataset contains only broken/failing links (status >= 400, timeouts, errors). If false, every checked link is recorded with its status. Default: true. Set to false to get a complete link inventory with response times.

## `slowThresholdMs` (type: `integer`):

Response time in milliseconds above which a link is classified as 'slow'. Default: 5000. Slow links are reported (status 200 + slow flag) so you can find performance issues without classifying them as broken.

## `requestTimeoutMs` (type: `integer`):

Maximum time to wait for a response before classifying a link as 'timeout'. Default: 15000 (15s). Increase for slow targets; decrease to fail fast on dead sites.

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

Number of concurrent HTTP requests during link verification. Default: 20. Higher values are faster but may trigger rate limits on small sites. Reduce to 5-10 for fragile or rate-limited targets.

## `maxRedirects` (type: `integer`):

Maximum redirect hops to follow per URL before classifying as 'redirect\_loop'. Default: 10. Redirect chains longer than 2 hops are flagged as 'redirect\_chain' (still a 200 but worth reviewing).

## `userAgent` (type: `string`):

Custom User-Agent string sent on every request. Default identifies as ApifyBrokenLinkChecker. Use a browser UA if a target site blocks bots; leave default for transparency and lower block rate.

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

Proxy settings for outbound requests. Default: no proxy (direct, fastest). Enable Apify Proxy only if a target site blocks your IP — most link checks work fine without proxies. Use residential group only when datacenter is blocked.

## Actor input object example

```json
{
  "mode": "crawl",
  "startUrl": "https://example.com",
  "urls": [
    "https://example.com",
    "https://example.com/this-page-does-not-exist",
    "https://httpstat.us/404",
    "https://httpstat.us/500"
  ],
  "maxPages": 50,
  "maxLinksToCheck": 500,
  "checkExternalLinks": true,
  "checkAssets": false,
  "onlyReportBroken": true,
  "slowThresholdMs": 5000,
  "requestTimeoutMs": 15000,
  "maxConcurrency": 20,
  "maxRedirects": 10,
  "userAgent": "Mozilla/5.0 (compatible; ApifyBrokenLinkChecker/1.0; +https://apify.com)",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `brokenLinks` (type: `string`):

No description

## `downloadCsv` (type: `string`):

No description

## `htmlReport` (type: `string`):

No description

## `summaryJson` (type: `string`):

No description

# 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 = {
    "startUrl": "https://crawler-test.com/links/broken_links_internal",
    "urls": [
        "https://example.com",
        "https://example.com/this-page-does-not-exist",
        "https://httpstat.us/404",
        "https://httpstat.us/500"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/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 = {
    "startUrl": "https://crawler-test.com/links/broken_links_internal",
    "urls": [
        "https://example.com",
        "https://example.com/this-page-does-not-exist",
        "https://httpstat.us/404",
        "https://httpstat.us/500",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

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

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

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

```

## CLI example

```bash
echo '{
  "startUrl": "https://crawler-test.com/links/broken_links_internal",
  "urls": [
    "https://example.com",
    "https://example.com/this-page-does-not-exist",
    "https://httpstat.us/404",
    "https://httpstat.us/500"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call khadinakbar/broken-link-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=khadinakbar/broken-link-checker",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Broken Link Checker — Find 404s, Dead Links & Redirect Issues",
        "description": "Crawl a website, scan a URL list, or verify all URLs from a sitemap. Returns broken links with source page, anchor text, status, redirect chain, and failure class — for SEO audits, content QA, and migration validation.",
        "version": "1.1",
        "x-build-id": "bTAMgJc0EBFkahDba"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/khadinakbar~broken-link-checker/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-khadinakbar-broken-link-checker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/khadinakbar~broken-link-checker/runs": {
            "post": {
                "operationId": "runs-sync-khadinakbar-broken-link-checker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/khadinakbar~broken-link-checker/run-sync": {
            "post": {
                "operationId": "run-sync-khadinakbar-broken-link-checker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "mode"
                ],
                "properties": {
                    "mode": {
                        "title": "Input mode",
                        "enum": [
                            "crawl",
                            "list",
                            "sitemap"
                        ],
                        "type": "string",
                        "description": "How URLs are sourced. 'crawl' starts at startUrl and crawls the site to maxPages, extracting and verifying every link found. 'list' verifies only the URLs in the urls array (no crawling). 'sitemap' fetches sitemap.xml from startUrl and verifies every URL found. Default: 'crawl'. Choose 'list' for outreach link audits and 'sitemap' for full-site URL coverage without crawling overhead.",
                        "default": "crawl"
                    },
                    "startUrl": {
                        "title": "Website URL or sitemap URL",
                        "type": "string",
                        "description": "The URL to start crawling from (mode='crawl') or the sitemap.xml URL (mode='sitemap'). Must include the protocol — example: 'https://example.com' or 'https://example.com/sitemap.xml'. Crawler stays within the same registrable domain by default. Ignored when mode='list'."
                    },
                    "urls": {
                        "title": "URLs to verify",
                        "type": "array",
                        "description": "List of URLs to check directly without crawling. Used only when mode='list'. Each entry must be a full URL including protocol — example: ['https://example.com/page1', 'https://example.com/missing']. Up to 5000 URLs per run. Ignored when mode='crawl' or 'sitemap'.",
                        "items": {
                            "type": "string",
                            "pattern": "^https?:\\/\\/.+"
                        }
                    },
                    "maxPages": {
                        "title": "Max pages to crawl",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Maximum number of internal pages to crawl (mode='crawl' only). Higher values find more broken links but take longer. Default: 50. Set to a small value (5-10) for quick audits; 200-500 for thorough site reviews.",
                        "default": 50
                    },
                    "maxLinksToCheck": {
                        "title": "Max links to verify",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Maximum number of unique links to verify per run. Caps cost on link-heavy sites. Default: 500. Each verified link triggers a 'link-checked' charge of $0.001.",
                        "default": 500
                    },
                    "checkExternalLinks": {
                        "title": "Check external links",
                        "type": "boolean",
                        "description": "Verify links pointing to other domains, not just internal links. Default: true. Set to false to focus only on same-domain links and reduce cost (typically halves the link count).",
                        "default": true
                    },
                    "checkAssets": {
                        "title": "Check images, scripts, and stylesheets",
                        "type": "boolean",
                        "description": "Also verify <img>, <script>, <link>, and <iframe> resource URLs in addition to <a> hyperlinks. Default: false. Enable for full content audits; disable for hyperlink-only checks (faster and cheaper).",
                        "default": false
                    },
                    "onlyReportBroken": {
                        "title": "Only report broken links",
                        "type": "boolean",
                        "description": "If true, dataset contains only broken/failing links (status >= 400, timeouts, errors). If false, every checked link is recorded with its status. Default: true. Set to false to get a complete link inventory with response times.",
                        "default": true
                    },
                    "slowThresholdMs": {
                        "title": "Slow link threshold (ms)",
                        "minimum": 100,
                        "maximum": 60000,
                        "type": "integer",
                        "description": "Response time in milliseconds above which a link is classified as 'slow'. Default: 5000. Slow links are reported (status 200 + slow flag) so you can find performance issues without classifying them as broken.",
                        "default": 5000
                    },
                    "requestTimeoutMs": {
                        "title": "Request timeout (ms)",
                        "minimum": 1000,
                        "maximum": 60000,
                        "type": "integer",
                        "description": "Maximum time to wait for a response before classifying a link as 'timeout'. Default: 15000 (15s). Increase for slow targets; decrease to fail fast on dead sites.",
                        "default": 15000
                    },
                    "maxConcurrency": {
                        "title": "Max parallel requests",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Number of concurrent HTTP requests during link verification. Default: 20. Higher values are faster but may trigger rate limits on small sites. Reduce to 5-10 for fragile or rate-limited targets.",
                        "default": 20
                    },
                    "maxRedirects": {
                        "title": "Max redirects to follow",
                        "minimum": 0,
                        "maximum": 30,
                        "type": "integer",
                        "description": "Maximum redirect hops to follow per URL before classifying as 'redirect_loop'. Default: 10. Redirect chains longer than 2 hops are flagged as 'redirect_chain' (still a 200 but worth reviewing).",
                        "default": 10
                    },
                    "userAgent": {
                        "title": "User-Agent header",
                        "type": "string",
                        "description": "Custom User-Agent string sent on every request. Default identifies as ApifyBrokenLinkChecker. Use a browser UA if a target site blocks bots; leave default for transparency and lower block rate.",
                        "default": "Mozilla/5.0 (compatible; ApifyBrokenLinkChecker/1.0; +https://apify.com)"
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Proxy settings for outbound requests. Default: no proxy (direct, fastest). Enable Apify Proxy only if a target site blocks your IP — most link checks work fine without proxies. Use residential group only when datacenter is blocked.",
                        "default": {
                            "useApifyProxy": false
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
