# Bulk URL Status Checker - Broken Links & Redirect Chains (`lost.fany/bulk-url-status-checker`) Actor

Check thousands of URLs at once: status code, full redirect chain, final URL, response time, title, canonical and noindex. Broken links and redirect loops flagged. No browser. dryRun prices a run before you pay; charged only for URLs checked.

- **URL**: https://apify.com/lost.fany/bulk-url-status-checker.md
- **Developed by:** [Natalia Ivanova](https://apify.com/lost.fany) (community)
- **Categories:** SEO tools, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.76 / 1,000 url 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

## Bulk URL Status Checker - Broken Links & Redirect Chains

Check **thousands of URLs in minutes**: HTTP status, the full redirect chain and final URL, response time, content type, server, page title, H1, canonical and `noindex`. Every URL is classified — `ok`, `redirect`, `broken`, `forbidden`, `server-error`, `rate-limited`, `redirect-loop`, `error` — so a spreadsheet filter is all you need to find what is wrong. No browser, no API keys.

### What you can do with it

- **Broken-link audits** — paste the URL list from your sitemap (pair it with the [Sitemap URL Extractor](https://apify.com/lost.fany/sitemap-url-extractor)), get every 404/410/5xx.
- **Migration checks** — verify old URLs redirect to the right new ones in one hop; catch chains and loops.
- **Uptime and SEO monitoring** — schedule daily runs for key pages; alert on status changes, `noindex` slipping in, canonicals pointing elsewhere.
- **Link-list hygiene** — clean CSV exports, directories, bookmarks, affiliate links.
- **AI agents** — "is this link alive and where does it go?" through the Apify MCP server.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `urls` | array | — | URLs to check. |
| `method` | select | `GET` | `GET` (reads HTML details) or `HEAD` (faster; falls back to GET when refused). |
| `onlyProblems` | boolean | `false` | Return only URLs that are not OK; healthy ones are not charged. |
| `expectedStatus` | number | — | OK only if the final status equals this. |
| `maxRedirects` | number | `10` | Longer chains are reported as loops. |
| `requestTimeoutSecs` | number | `20` | Per request. |
| `maxConcurrency` | number | `20` | Parallel requests. |
| `parseHtml` | boolean | `true` | Title, H1, canonical, robots meta, noindex. |
| `proxyConfiguration` | object | off | Apify Proxy for sites that block datacenter IPs. |

```json
{ "urls": ["https://apify.com", "https://example.com/missing", "http://github.com"], "onlyProblems": false }
```

### Output

```json
{
  "url": "http://github.com",
  "finalUrl": "https://github.com/",
  "status": 200,
  "statusText": "OK",
  "ok": true,
  "result": "ok",
  "redirectCount": 1,
  "redirectChain": [{ "url": "http://github.com", "status": 301, "location": "https://github.com/" }],
  "responseTimeMs": 412,
  "contentType": "text/html",
  "contentLength": null,
  "server": "github.com",
  "title": "GitHub · Build and ship software on a single, collaborative platform",
  "h1": "Build and ship software on a single, collaborative platform",
  "canonical": "https://github.com/",
  "robots": null,
  "noindex": false,
  "lastModified": null,
  "error": null,
  "checkedAt": "2026-09-10T15:30:00Z"
}
```

The `OUTPUT` record holds totals: checked, OK, problems, rows pushed.

### Use cases

Ready-made examples you can run without configuring anything:

- [Bulk URL status check for a sitemap export](https://apify.com/lost.fany/bulk-url-status-checker/examples/bulk-url-status-checker) — ready-made task, run it as is
- [Redirect chain checker after a migration](https://apify.com/lost.fany/bulk-url-status-checker/examples/redirect-chain-checker) — ready-made task, run it as is

#### Bulk URL status checker for a sitemap export

Paste a sitemap export and get the HTTP status of every page, classified as ok, redirect, broken, forbidden or rate-limited.

```json
{ "urls": ["https://example.com/a", "https://example.com/b"] }
```

#### Redirect chain checker after a migration

The full redirect chain and final URL per link, so loops and long hops surface before Google finds them.

```json
{ "urls": ["https://old.example.com/page"], "maxRedirects": 10 }
```

#### HTTP status code checker for link audits

Status, response time, content type, title, canonical and noindex in one row per URL — a link audit without a browser.

```json
{ "urls": ["https://example.com"] }
```

### Pricing

Pay per event: a small fee per Actor start plus a fee per URL checked (per row returned when `onlyProblems` is on). Current prices are in the **Pricing** tab.

### Good to know

- Requests come from Apify's datacenter IPs with a browser-like User-Agent; a few sites answer 403 to any non-browser client — use the proxy option or treat `forbidden` as "needs a manual look".
- HTML is read only up to 512 KB per page; titles and canonicals are found in that range in practice.
- Keep `maxConcurrency` low (3–5) when checking hundreds of URLs on a single small site.

### Use with AI agents (MCP)

Add the Actor to the [Apify MCP server](https://apify.com/apify/actors-mcp-server): "Check whether these ten links still work" → `{ "urls": ["…"], "onlyProblems": true }`.

### Related Actors

- [Sitemap URL Extractor](https://apify.com/lost.fany/sitemap-url-extractor)
- [Tech Stack Detector](https://apify.com/lost.fany/website-tech-stack-detector)
- [Career Page Jobs API](https://apify.com/lost.fany/greenhouse-lever-ats-jobs-scraper)

### Cost control

Pay per event only works if you can see the bill before you pay it:

- Set `dryRun` to count every result and print what a full run would cost - nothing is charged, and only a few sample rows are stored.
- You are charged only for rows actually delivered to the dataset; a run that finds nothing costs nothing beyond the start event.
- `maxItems` is respected exactly, and the run stops before the platform's Max total charge for the run.
- Every run writes a `COST` record to the key-value store: chargeable events, charged events, the amount in USD and whether a limit was hit.

# Actor input Schema

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

URLs to check, one per line (a scheme is added if missing). Thousands are fine.

## `method` (type: `string`):

GET also reads the page title, H1, canonical and robots meta; HEAD is faster but some servers reject it (the Actor retries with GET).

## `onlyProblems` (type: `boolean`):

Return only URLs that are not OK (4xx, 5xx, errors, redirect loops). Healthy URLs are then not charged.

## `expectedStatus` (type: `integer`):

Mark a URL as OK only if it returns exactly this status (e.g. 200). Empty = any 2xx after redirects.

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

Longer chains are reported as redirect loops.

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

Per request.

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

Parallel requests. Lower it when checking many URLs of one site.

## `parseHtml` (type: `boolean`):

Title, H1, canonical, robots meta and noindex for HTML pages (GET only).

## `maxItems` (type: `integer`):

Stop after this many URLs.

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

Optional. Use Apify Proxy if the target site blocks datacenter IPs.

## `dryRun` (type: `boolean`):

Count every result and show what a full run would cost, without charging for it. Only a few sample rows are stored. Use it to check the price before you pay.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com",
    "https://example.com/missing-page",
    "http://github.com"
  ],
  "method": "GET",
  "onlyProblems": false,
  "maxRedirects": 10,
  "requestTimeoutSecs": 20,
  "maxConcurrency": 20,
  "parseHtml": true,
  "maxItems": 100000,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "dryRun": false
}
```

# Actor output Schema

## `results` (type: `string`):

One row per URL: status, result class, redirect chain, final URL, timing, title, canonical, noindex, error.

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

Counts and errors of the run.

# 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://apify.com",
        "https://example.com/missing-page",
        "http://github.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lost.fany/bulk-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://apify.com",
        "https://example.com/missing-page",
        "http://github.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("lost.fany/bulk-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://apify.com",
    "https://example.com/missing-page",
    "http://github.com"
  ]
}' |
apify call lost.fany/bulk-url-status-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lost.fany/bulk-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/oGSWnz4rPrZemOePV/builds/AuPb3oi2qzUdXNujh/openapi.json
