# Bulk URL Status Code and Redirect Chain Checker (`pistachio_implementation/url-status-redirect-checker`) Actor

Check thousands of URLs for HTTP status codes, broken links (404, 410, 5xx) and redirect chains. Returns every hop (301, 302, 307, 308), the final URL, response time and key headers. For SEO migrations and link audits. $0.80 per 1,000 URLs.

- **URL**: https://apify.com/pistachio\_implementation/url-status-redirect-checker.md
- **Developed by:** [Hay Equipos](https://apify.com/pistachio_implementation) (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

$0.80 / 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.

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 Code and Redirect Chain Checker

Paste a list of URLs and get back, for each one, the HTTP status code, whether it is broken, the full redirect chain hop by hop (301, 302, 307, 308), the final URL, the response time and the headers that matter for SEO. Built for site migrations, broken link audits, backlink checks, affiliate link checks and cleaning URL lists before you feed them to other tools.

**Price: $0.80 per 1,000 URLs.** URLs that give no HTTP answer at all (the domain does not exist, the connection is refused or times out) are reported but free.

### What you get for each URL

| Field | Meaning |
|---|---|
| `statusCode` | The first answer, for example 301 |
| `finalStatusCode` | The answer at the end of the redirect chain, for example 200 or 404 |
| `isBroken` | True for a final 4xx or 5xx, a redirect loop, too many hops, or no answer |
| `ok` | True for a final 2xx |
| `finalUrl` | Where the URL really lands |
| `redirectCount`, `redirectChain` | Every hop with its URL, status code, method and Location header |
| `redirectsToHttps`, `changedDomain` | Did an http URL move to https, did the redirect leave the original host |
| `redirectLoop`, `tooManyRedirects` | Redirect problems, flagged |
| `responseTimeMs` | Total time for the whole chain |
| `contentType`, `contentLength`, `lastModified`, `server`, `xRobotsTag`, `cacheControl`, `hsts` | Headers from the final answer |
| `error` | For URLs with no HTTP answer: `ENOTFOUND`, `ECONNREFUSED`, `Timed out` and similar |

### Input

```json
{
  "urls": [
    "http://apify.com",
    "https://httpbin.org/status/404",
    "https://httpbin.org/redirect/2"
  ],
  "followRedirects": true,
  "maxRedirects": 10
}
```

You can also paste a column of URLs into `urlsText`. Duplicates are removed. Addresses without a scheme get `https://` added.

### Output example

```json
{
  "url": "http://apify.com",
  "ok": true,
  "isBroken": false,
  "statusCode": 301,
  "finalStatusCode": 200,
  "finalUrl": "https://apify.com/",
  "redirectCount": 1,
  "redirectChain": [
    { "url": "http://apify.com/", "statusCode": 301, "method": "HEAD", "location": "https://apify.com/" },
    { "url": "https://apify.com/", "statusCode": 200, "method": "HEAD", "location": null }
  ],
  "redirectsToHttps": true,
  "changedDomain": false,
  "contentType": "text/html; charset=utf-8",
  "responseTimeMs": 1956
}
```

### How it checks

- A HEAD request first, which does not download the page. If the server refuses HEAD (many answer 403, 404 or 405 to HEAD but serve the page normally), the URL is checked again with a GET that reads at most 64 KB. You can switch this off.
- Redirects are followed by hand so every hop is recorded, with loop detection.
- Many sites are checked in parallel, while requests to the same site are spaced out (3 per second by default, adjustable from 1 to 10).
- 429 and 5xx answers are retried with backoff before they are reported.
- The actor identifies itself honestly as `ApifyLinkChecker` and respects robots.txt by default, including rules written for Apify crawlers. URLs a site closes to automated tools come back as free `skipped` rows. Turn this off only for sites you own or may check.

### Pricing

Pay per event: **$0.0008 per URL checked ($0.80 per 1,000)**. A URL is charged when a server answered it with any HTTP status, including 404 and 500, because that answer is the result you asked for. No start fee and no platform usage on top. Invalid URLs, URLs with no HTTP answer, and URLs skipped for robots.txt are free.

### Limits

- No JavaScript. Redirects done by JavaScript or by a meta refresh tag are not followed; the page's own status code is reported.
- Some sites answer automated requests from cloud servers with 403 or a challenge page. That status is reported as it was received. The actor does not try to get around such blocks.
- Up to 50,000 URLs per run. Speed depends on the sites: a list spread across many hosts runs at hundreds of URLs a minute; a list on one host runs at your per site limit.

### FAQ

**Is a 404 charged?** Yes, when the server returned it, because finding 404s is usually the point. A URL whose domain does not exist is free.

**Does it crawl my site to find links?** No. It checks exactly the URLs you give it. To get every URL of a site first, run a sitemap extractor and pass its output here.

**Can I use it after a site migration?** Yes. Give it the old URLs and check that `finalStatusCode` is 200, `redirectCount` is 1 and `finalUrl` is the new page you expect.

**Can an AI agent use it?** Yes. One array of URLs in, one row per URL out, the same fields every time.

# Actor input Schema

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

URLs to check, one per line. Addresses without a scheme get https:// added.

## `urlsText` (type: `string`):

Optional. URLs separated by spaces, commas or new lines.

## `followRedirects` (type: `boolean`):

Follow 3xx redirects and record every hop. Off: report only the first answer.

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

Stop following after this many hops and flag the URL.

## `useGetFallback` (type: `boolean`):

Some servers answer HEAD requests with 403, 404 or 405 but serve the page normally. When on, those URLs are checked again with a GET (only the first 64 KB are read).

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

Give up on a request after this many seconds.

## `requestsPerSecondPerSite` (type: `integer`):

Politeness limit for URLs on the same host. Many hosts are checked in parallel.

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

Skip URLs that the site's robots.txt closes to automated tools (free rows). Turn off only for sites you own or have permission to check.

## `maxUrls` (type: `integer`):

Stop after this many URLs (up to 50,000 per run).

## Actor input object example

```json
{
  "urls": [
    "http://apify.com",
    "https://httpbin.org/status/404",
    "https://httpbin.org/redirect/2"
  ],
  "followRedirects": true,
  "maxRedirects": 10,
  "useGetFallback": true,
  "timeoutSecs": 20,
  "requestsPerSecondPerSite": 3,
  "respectRobotsTxt": true,
  "maxUrls": 10000
}
```

# Actor output Schema

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

All rows the run saved to the default dataset.

# 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://httpbin.org/status/404",
        "https://httpbin.org/redirect/2"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pistachio_implementation/url-status-redirect-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://httpbin.org/status/404",
        "https://httpbin.org/redirect/2",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("pistachio_implementation/url-status-redirect-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://httpbin.org/status/404",
    "https://httpbin.org/redirect/2"
  ]
}' |
apify call pistachio_implementation/url-status-redirect-checker --silent --output-dataset

```

## MCP server setup

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