# Bulk HTTP Status Code & Redirect Chain Checker (`veedel_digital/status-checker`) Actor

Check HTTP status codes and full redirect chains of up to 100,000 URLs. Finds 404s, 5xx errors, redirect chains and loops, 302 instead of 301, missing HTTPS redirects, and verifies relaunch redirect maps. No proxies, pay per URL.

- **URL**: https://apify.com/veedel_digital/status-checker.md
- **Developed by:** [Tim Tonat](https://apify.com/veedel_digital) (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 $1.00 / 1,000 urls

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

### What does Bulk HTTP Status Code & Redirect Chain Checker do?

This Actor **checks the HTTP status code and the full redirect chain of up to 100,000 URLs** in one run. For every URL you get the first status code, every redirect hop, the final URL and its status code, plus **issue codes** for the problems that hurt SEO and users.

It also **verifies redirect maps after a website relaunch**: paste lines like `old URL -> new URL` and see at a glance which redirects land on the wrong page.

No proxies and no browser, so runs are fast and cheap.

### Why use this HTTP status checker?

- **Find broken URLs (404, 410, 500)** in lists from Google Search Console, sitemaps, backlink tools or old exports
- **Check every redirect hop**: redirect chains waste crawl budget and slow down users
- **Catch 302 instead of 301**: temporary redirects don't pass rankings reliably
- **Detect redirect loops** and URLs with too many redirects
- **Make sure http:// redirects to https://**
- **Website relaunch / migration**: check hundreds of old URLs against their expected new targets
- **Monitor link lists** on a schedule and export to Google Sheets, Excel or CSV
- **Pay per URL**: URLs that can't be reached at all are free

### What does it check?

| Issue code | Meaning |
|---|---|
| `INVALID_REDIRECT` | A redirect status (301, 302, …) without a valid `Location` header |
| `CLIENT_ERROR` | Final status is 4xx (404 not found, 410 gone, 403 forbidden, …) |
| `SERVER_ERROR` | Final status is 5xx |
| `REDIRECT_CHAIN` | More than one redirect before the final page |
| `REDIRECT_LOOP` | The chain leads back to a URL it already visited |
| `TOO_MANY_REDIRECTS` | More than 10 redirects |
| `TEMPORARY_REDIRECT` | A 302, 303 or 307 redirect in the chain instead of 301 or 308 |
| `HTTP_TO_HTTPS_MISSING` | An `http://` URL does not end on `https://` |
| `WRONG_TARGET` | Redirect map only: the final URL is not the expected target |
| `UNREACHABLE` | No HTTP response at all (DNS error, timeout, connection refused). Not charged |
| `INVALID_URL` | The input line is not a valid URL. Not charged |

### What data does it return?

| Field | Description |
|---|---|
| `url` | Checked URL |
| `statusCode` | Status code of the first response |
| `finalUrl`, `finalStatusCode` | Where the chain ends |
| `redirectCount` | Number of redirects followed |
| `redirectChain` | Every hop with `url`, `statusCode` and `location` |
| `responseTimeMs` | Total time for the whole chain |
| `contentType` | Content type of the final response |
| `expectedUrl`, `matchesExpected` | Redirect map only |
| `issues` | Issue codes, see above |
| `error` | Network error, if no response was received |

A **Summary** (key-value store record `SUMMARY`) counts all URLs by final status code and by issue.

### How to check status codes and redirects in bulk

1. Click **Try for free**.
2. Paste your URLs into **URLs**, one per line. Or paste `old -> new` lines into **Redirect map**.
3. Click **Start**.
4. Sort the **Overview** table by status or issues, or download it as CSV or Excel.

### How much does it cost?

This Actor uses **pay per event**: a fixed price **per checked URL**, and **platform usage is included**. The current price is shown in the **Pricing** tab. URLs that can't be reached at all and invalid input lines are not charged.

### Input

See the **Input** tab for all options.

```json
{
    "urls": ["http://example.com", "https://example.com/old-page"],
    "redirectMap": ["https://example.com/old-shop -> https://example.com/shop/"],
    "method": "HEAD",
    "timeoutSecs": 15,
    "concurrency": 10
}
```

### Output

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

```json
{
    "url": "http://example.com/old-shop",
    "statusCode": 301,
    "finalUrl": "https://example.com/shop/",
    "finalStatusCode": 200,
    "redirectCount": 2,
    "redirectChain": [
        { "url": "http://example.com/old-shop", "statusCode": 301, "location": "https://example.com/old-shop" },
        { "url": "https://example.com/old-shop", "statusCode": 302, "location": "https://example.com/shop/" },
        { "url": "https://example.com/shop/", "statusCode": 200, "location": null }
    ],
    "responseTimeMs": 412,
    "contentType": "text/html; charset=utf-8",
    "expectedUrl": "https://example.com/shop/",
    "matchesExpected": true,
    "issues": ["REDIRECT_CHAIN", "TEMPORARY_REDIRECT"],
    "error": null
}
```

### Related Actors

Don't have a URL list yet? The SEO Site Audit crawls a whole website and finds broken internal links on its own.

- [SEO Site Audit & Broken Link Checker](https://apify.com/veedel_digital/seo-audit): crawl a whole website and find on-page SEO issues and broken pages
- [PageSpeed Insights & Core Web Vitals Bulk Audit](https://apify.com/veedel_digital/pagespeed-audit): Lighthouse scores and real-user Core Web Vitals for many URLs
- [Structured Data, Schema.org & Open Graph Extractor](https://apify.com/veedel_digital/structured-data): extract JSON-LD, schema.org types and Open Graph tags from many pages
- [PDF to Text with OCR](https://apify.com/veedel_digital/pdf-to-text): extract text from PDFs in bulk, scanned pages included

### FAQ

#### Why HEAD requests?

HEAD asks only for the headers, so checks are fast and light on the server. Some servers answer HEAD with a wrong error code, so **every error response is double-checked with a GET request**. Choose *GET* if you want only GET requests.

#### Does it run JavaScript redirects?

No. It follows HTTP redirects (301, 302, 303, 307, 308), like search engines do on the first pass. Redirects done with JavaScript or `<meta http-equiv="refresh">` are not followed.

#### Some sites return 403 for every URL

Some firewalls (for example Cloudflare bot protection) block automated requests. The 403 is then what bots see, not what browsers see. Try another *User agent* in the advanced options.

#### Will it overload a server?

It uses 10 parallel requests by default. If all URLs are on one small server, lower *Parallel requests*.

#### Something does not work

Please open an issue in the **Issues** tab with the URL and the run ID. You can also start the Actor programmatically from the **API** tab.

# Actor input Schema

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

URLs to check, one per line. Domains without http(s):// are checked as https://.

## `redirectMap` (type: `array`):

For website relaunches: one line per redirect, e.g. "https://example.com/old-page -> https://example.com/new-page". Separators: ->, tab, comma or semicolon. The target may be relative. Each row gets matchesExpected true/false.

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

HEAD is fastest. Error responses to HEAD are always double-checked with GET, because some servers answer HEAD incorrectly.

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

Leave empty to use a current desktop Chrome user agent.

## `timeoutSecs` (type: `integer`):

How long to wait for each single response before the URL counts as unreachable.

## `concurrency` (type: `integer`):

Lower it if you check many URLs on one small server.

## Actor input object example

```json
{
  "urls": [
    "http://apify.com",
    "https://apify.com/store",
    "https://apify.com/this-page-does-not-exist"
  ],
  "method": "HEAD",
  "timeoutSecs": 15,
  "concurrency": 10
}
```

# Actor output Schema

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

Dataset with all checked URLs

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

Counts by final status code and issue

# 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": [
        "http://apify.com",
        "https://apify.com/store",
        "https://apify.com/this-page-does-not-exist"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("veedel_digital/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": [
        "http://apify.com",
        "https://apify.com/store",
        "https://apify.com/this-page-does-not-exist",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("veedel_digital/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": [
    "http://apify.com",
    "https://apify.com/store",
    "https://apify.com/this-page-does-not-exist"
  ]
}' |
apify call veedel_digital/status-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,veedel_digital/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/1VX2Zn0QCxsFm2Wpf/builds/tb6b9PYsUjE8UKP4h/openapi.json
