# Broken Link Checker & Bulk URL Status Checker (`ahmed.fouaad82/url-status-checker`) Actor

Broken link checker: bulk-check URL status codes, 404s, redirect chains and SEO tags for URL lists or small same-site crawls. $2/1,000 checks.

- **URL**: https://apify.com/ahmed.fouaad82/url-status-checker.md
- **Developed by:** [Ahmed Fouad](https://apify.com/ahmed.fouaad82) (community)
- **Categories:** SEO tools, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 url checks

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 & Bulk URL Status Checker

**Find broken links and 404s: bulk-check URL status codes and redirect chains** for SEO specialists, website maintainers and migration teams. Check a supplied URL list or crawl same-hostname links to depth 2, inspect SEO tags and optionally verify links to a known target. This is not a backlink-discovery index.

**First 25 saved URL checks of every run are free; after that, $2 per 1,000 saved URL checks.** Saved error and robots-denial diagnostics count toward the free prefix and are billable after it; there is no per-anchor fee. The Pricing tab is authoritative. Apify plan allowances and any applicable platform/storage charges are separate.

**Example output** (illustrative abbreviated record, not a captured result):

```json
{"url":"https://example.com/","statusCode":200,"finalUrl":"https://example.com/","title":"Example Domain","redirectChain":[]}
```

### What does Bulk URL Status & Backlink Checker do?

**Bulk-check HTTP status codes, redirect chains, SEO metadata and existing backlinks** from a URL list, or crawl links from a supplied page to depth 0–2 on the same hostname. Verify that your target URL or domain appears in real HTML anchors, including anchor text and `nofollow`, `sponsored` and `ugc` attributes.

This is a lightweight plain-HTTP link checker and API, not a search-engine backlink index. It does **not discover who links to you**, execute JavaScript, solve CAPTCHAs or bypass access controls. [Example Domain](https://example.com/) is the one-click public test page.

### Why use a bulk URL and broken-link checker?

- Audit migrations, redirects, broken links, canonical tags and noindex directives.
- Verify purchased placements or known referring pages without a browser.
- Trace each redirect's HTTP status, raw Location and resolved destination.
- Run scheduled checks or call through the Apify API; export results to your integrations.
- Bound work using maximum results, request timeouts, retries and response-size limits.

Network requests are serialized per hostname, with a default 750 ms pause between requests; separate hosts can run concurrently. Robots rules are checked before every page, including redirect destinations. No paid proxy is used.

### What data can this Actor extract?

| Field | Type | Meaning |
| --- | --- | --- |
| `url`, `sourceUrl`, `depth` | string/integer | Checked URL and crawl provenance |
| `statusCode`, `finalUrl` | integer/string | Final HTTP response and destination |
| `redirectChain` | array | Each hop: URL, status, raw Location, resolved URL |
| `responseTimeMs`, `attempts`, `method` | integer/string | Full check elapsed time, attempt count and final HEAD/GET method |
| `contentType`, `title`, `canonicalUrl` | string | Response and HTML metadata |
| `metaRobots`, `xRobotsTag`, `noindex` | string/boolean | Observed indexing directives |
| `target`, `linked`, `matchedLinks` | string/boolean/array | Target verification and matching anchors with rel flags |
| `robotsAllowed`, `error`, `checkedAt` | boolean/string | Access diagnostic and UTC check start |

Missing or unverified values are `null`, not invented. Each unique normalized input/crawled URL produces at most one saved row. Broken URLs, robots denials and transport failures are useful diagnostic results and count as saved results.

### How to check URLs and backlinks

1. Paste public HTTP(S) URLs into **URLs to check**, or enter **Page to crawl**.
2. Choose crawl depth 0 (seeds only), 1 or 2. Crawling follows anchors only on the exact seed hostname, not sibling subdomains. Cross-host redirects are traced, but their external anchors are not added to the crawl.
3. Optionally enter a target domain or URL to verify links. Choose `domain` (including subdomains) or `url` matching.
4. Set a result limit, start the run and open the dataset.

### How much does it cost?

**First 25 saved URL checks of every run are free; after that, $2 per 1,000 results.** One result = one saved unique URL check, including its status/error, redirect chain, available SEO metadata and optional target-link verification.

This Actor is public with pay-per-event pricing. The Pricing tab shows the current event price. There is no per-anchor fee: all matching anchors observed on a page are part of that page's result. After the first 25 saved checks, the Actor stops saving rows when its event charge limit is reached. Apify plan allowances and any applicable platform/storage charges are separate from this Actor's per-run free prefix.

### Input

See the input tab for full configuration options. You can combine `urls` and `pageUrl`; duplicates and fragments are removed. Empty input checks `https://example.com/` and completes with a non-empty dataset.

```json
{
  "urls": ["https://example.com/"],
  "target": "iana.org",
  "targetMatch": "domain",
  "crawlDepth": 0,
  "maxResults": 10,
  "maxConcurrency": 5,
  "perHostDelayMs": 750,
  "headFirst": true,
  "timeoutSeconds": 20,
  "maxRetries": 1,
  "maxRedirects": 5,
  "maxResponseBytes": 2000000
}
```

Exact URL matching uses the URL standard's normalization, preserves path/query/trailing-slash differences and ignores fragments. Domain matching includes the named hostname and its subdomains, not lookalike suffixes. A `www` hostname is not automatically equivalent to its parent domain. Targets are compared with anchor destinations; redirects at the target are not independently resolved.

### Output

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel. Nested redirect and anchor details are best preserved in JSON. Simplified illustrative rows:

```json
[
  {"url":"https://example.com/","statusCode":200,"title":"Example Domain","target":"iana.org","linked":true,"matchedLinks":[{"url":"https://iana.org/domains/example","anchorText":"Learn more","rel":[],"nofollow":false,"sponsored":false,"ugc":false}]},
  {"url":"https://example.com/missing","statusCode":404,"linked":null,"error":"HTTP 404"}
]
```

`SUMMARY` contains the saved count, queued count and stop reason. `STATE` contains the remaining queue and saved URLs for migration/resurrection. Ordinary new runs start clean; explicit resurrection resumes saved work. Storage and charge operations cannot be transactional: an interruption precisely between saving and billing/checkpointing may require reconciliation before resurrecting a monetized run.

### Advanced options and limits

HEAD is tried first. HTML pages are fetched with GET to collect metadata; HEAD failures or a missing Content-Type fall back to GET. For non-HTML content a successful HEAD may be enough. `redirectChain`, final status and headers describe the authoritative final attempt, not a merge of HEAD/GET/retry histories. Redirect loops and excess hops are reported. Response time includes robots requests, queues, delays and retry backoff, not just server latency.

Retries cover network errors, HTTP 429 and selected transient 5xx responses; access denials are not evaded. Timeout applies to each DNS lookup and each HTTP request, not to an entire multi-hop check. Body size is bounded; oversized responses produce an error rather than a partial HTML claim. Use lower concurrency for large HTML pages; default memory is 256 MB and the platform run timeout is 1,800 seconds.

Robots checking is always enabled, even for supplied URL lists. Missing robots (404/410) allows access; denied, challenged, unreadable or unavailable robots fails closed. Robots Crawl-delay can extend the configured wait. Public DNS addresses are validated and pinned for each connection; local/private/reserved addresses, credentials, unsupported schemes and ports other than 80/443 are refused. HTTPS certificate verification stays enabled.

### FAQ and support

#### Is this a backlink discovery tool?

No. Supply the referring pages you want to verify. There is no web-wide backlink index, authority score or historical discovery feed.

#### Why is `linked` null?

Verification was not requested or HTML could not be inspected. `false` means HTML was inspected and no matching anchor was present. JavaScript-created links are not visible to this plain-HTTP Actor. A link's presence does not imply search-engine credit.

#### Does `noindex` mean Google has removed the page?

No. It reports observed `noindex` or `none` in robots/googlebot/bingbot meta tags or X-Robots-Tag. Agent-specific directives are preserved in raw fields; interpret them for your intended crawler. Non-HTML headers are available, but HTML metadata is null when no body was fetched.

#### Why did a URL fail?

Read `error` and `robotsAllowed`. Fix invalid URLs, reduce concurrency, or ask the site owner for permission. Do not use this Actor to bypass robots rules, authentication or CAPTCHA protections. HTTP errors are dataset diagnostics rather than reasons to fail the entire bulk run.

Use only public pages you are authorized to check and comply with site terms. Titles and anchor text can contain personal data; avoid personal-data targets and handle any incidental data under applicable law. The Actor does not intentionally harvest contact information. Report reproducible problems in the Issues tab; use the API tab for programmatic access.

# Actor input Schema

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

Public HTTP(S) URLs. Fragments are ignored and duplicate URLs checked once. Leave empty to use the crawl page or example.com.

## `pageUrl` (type: `string`):

Add a seed page. Set crawl depth 1 or 2 to check its same-hostname links.

## `target` (type: `string`):

Verify anchors linking to this target on each HTML page. Does not discover backlinks across the web.

## `targetMatch` (type: `string`):

Domain matches hostname plus subdomains; URL compares normalized full URLs ignoring fragments.

## `headFirst` (type: `boolean`):

Try HEAD first; GET HTML pages for metadata and fall back when HEAD fails. Disable to always GET.

## `crawlDepth` (type: `integer`):

0 checks seeds only; 1-2 follows anchors on the exact seed hostname.

## `maxResults` (type: `integer`):

Stop after this many unique saved URL results, including HTTP errors. First 25 results of every run are free.

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

Parallel URLs across hosts; network requests to a single host are serialized.

## `perHostDelayMs` (type: `integer`):

Minimum wait between requests on a host; robots Crawl-delay can increase this.

## `maxRetries` (type: `integer`):

Retry network errors, 429 and selected 5xx responses. Never evade access denials.

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

Maximum redirects per HEAD or GET request chain; loops are reported as errors.

## `timeoutSeconds` (type: `integer`):

Timeout for DNS and each HTTP request, including reading its body.

## `maxResponseBytes` (type: `integer`):

Reject oversized response bodies to bound memory usage.

## Actor input object example

```json
{
  "urls": [
    "https://example.com/"
  ],
  "pageUrl": "",
  "target": "",
  "targetMatch": "domain",
  "headFirst": true,
  "crawlDepth": 0,
  "maxResults": 10,
  "maxConcurrency": 5,
  "perHostDelayMs": 750,
  "maxRetries": 1,
  "maxRedirects": 5,
  "timeoutSeconds": 20,
  "maxResponseBytes": 2000000
}
```

# Actor output Schema

## `dataset` (type: `string`):

All saved checks

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

Saved count and stop reason

# 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 = {
    "urls": [
        "https://example.com/"
    ],
    "maxResults": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed.fouaad82/url-status-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 = {
    "urls": ["https://example.com/"],
    "maxResults": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("ahmed.fouaad82/url-status-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 '{
  "urls": [
    "https://example.com/"
  ],
  "maxResults": 10
}' |
apify call ahmed.fouaad82/url-status-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ahmed.fouaad82/url-status-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/tnrInGI8RSxGgSSUy/builds/fxSNwcvbuDwln9EMA/openapi.json
