# Bulk URL Status Checker (`cyber1nj3ct0r/url-status-checker`) Actor

Check the HTTP status of a list of web addresses. For each one you get the status code, whether it works, redirects or is broken, the full redirect chain, the final address and the response time. Paste the list or link a text file; thousands of addresses per run.

- **URL**: https://apify.com/cyber1nj3ct0r/url-status-checker.md
- **Developed by:** [Sanira Botheju](https://apify.com/cyber1nj3ct0r) (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.60 / 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.
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

### What does Bulk URL Status Checker do?

Bulk URL Status Checker tells you, for a list of web addresses, which ones work, which ones redirect and which ones are broken. Paste the addresses or link a file that lists them, and you get each one's **HTTP status code**, the **full redirect chain**, the **final address** and the **response time**, ready to export to Excel, CSV or JSON.

- Checks thousands of addresses in one run
- Follows redirects and shows every step (301, 302, 307, 308) and where it ends
- Explains each problem in words: page not found, server error, domain does not exist, redirect loop, certificate problem, timeout
- Separates real errors from sites that refuse automated checks
- Asks for headers only when the server allows it, so checks are fast and light on the sites
- Optional: every response header, for example `x-robots-tag`, `cache-control` or `last-modified`

### What data do you get?

| Field | Example |
|---|---|
| Address | `http://example.com/old-page` |
| Result | `redirected` (or `ok`, `broken`, `blocked`, `skipped`) |
| HTTP status | `200` |
| Problem | `Redirects 2 times to https://www.example.com/new-page` |
| Ends at | `https://www.example.com/new-page` |
| Redirect chain | `301` then `302` |
| Response time | `412` ms |
| Place in list | `17` |

### How to check the status of many URLs

1. Under **Web addresses**, paste your list with **Bulk edit**, add addresses one by one, or link a text file (a Google Sheet published as CSV works too).
2. Press **Start**.
3. Open the **Statuses** table, sort it by result or status, and export it.

### How much does it cost to check URL statuses?

You pay for results, not for time: **$0.80 per 1,000 URLs** checked. Apify subscribers on the Silver plan pay $0.70 and on the Gold plan $0.60 per 1,000 URLs. Each run also has a start fee of $0.00005. Duplicates in your list are checked, and paid, once.

| URLs checked | Cost |
|---|---|
| 100 | $0.08 |
| 1,000 | $0.80 |
| 10,000 | $8.00 |
| 100,000 | $80.00 |

Apify's free plan includes $5 of credit each month, which covers about 6,000 URLs. Set a maximum cost for the run in Apify Console and the tool stops there and keeps what it has checked.

### Input

The only required field is **Web addresses**. The other options:

- **How to check**: *Fast* asks for headers first and makes a normal request only when a server answers that badly; *Normal request* always asks for the page, like a browser does.
- **Include response headers**: adds every header of the final answer.
- **Requests at the same time per website**: keep it low for other people's sites, raise it for long lists of your own site.
- **Time limit per request** and **User-Agent** under More options.

### Output example

```json
{
    "url": "http://example.com/old-page",
    "position": 17,
    "result": "redirected",
    "broken": false,
    "status": 200,
    "reason": "Redirects 2 times to https://www.example.com/new-page",
    "finalUrl": "https://www.example.com/new-page",
    "redirectCount": 2,
    "redirectChain": [
        { "url": "http://example.com/old-page", "status": 301 },
        { "url": "https://example.com/old-page", "status": 302 }
    ],
    "responseTimeMs": 412,
    "contentType": "text/html",
    "contentLength": 48213,
    "method": "HEAD",
    "checkedAt": "2026-10-15T09:30:00.000Z",
    "error": null
}
```

### What the results mean

- **ok**: the address works (status 200 to 299 without a redirect).
- **redirected**: it works, but only after one or more redirects. The chain shows each step.
- **broken**: visitors get an error: 404 or 410, a server error (5xx), a domain that does not exist, a server that does not answer, too many redirects, or a certificate problem.
- **blocked**: the site answered the automated check with "forbidden" or "too many requests" (401, 403, 429). The address may work in a browser.
- **skipped**: not checked, because the entry is not a web address or points to a private network.

### What can you use it for?

- Check every address of a site after a migration, a redesign or a change of domain
- Confirm that old addresses redirect to the right new pages, with the right kind of redirect (301 for permanent moves)
- Clean a list of links before you publish it or import it into another system
- Find addresses in a spreadsheet, a sitemap or a backlink report that no longer work
- Watch a fixed list on a schedule in Apify Console

### Use it from the API

```bash
curl -X POST "https://api.apify.com/v2/acts/cyber1nj3ct0r~url-status-checker/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls": [{"url": "https://www.example.com"}, {"url": "http://example.com/old-page"}]}'
```

The same works from Python, JavaScript, Make, Zapier and n8n through Apify's integrations.

### FAQ

#### Why does a working page show as "blocked"?

Some sites, often the large ones, refuse automated requests even when the page exists. The tool reports what the site answered and does not try to get round it. Open the address in a browser to be sure.

#### Why is the order different from my list?

Addresses are checked several at a time, so results arrive in the order the checks finish. Sort by **Place in list** to get your original order back.

#### Does it read robots.txt?

It requests only the addresses you give it, once each, and follows no links, so it does not crawl and does not read `robots.txt`. To check a whole website, including the links on its pages, use a link checker instead.

#### A site blocks the tool. What can I do?

The tool identifies itself honestly in its User-Agent. If it is your own site, allow the User-Agent in your firewall, or set your own under **More options**.

#### Is it allowed to check URLs?

The tool makes one request per address, like a visitor opening the page. You are responsible for checking only addresses you are allowed to and for how you use the results.

#### Something does not work

Open an issue on the **Issues** tab with an address that shows the problem. Every report is read and answered.

# Actor input Schema

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

The addresses to check, for example <code>https://www.example.com/page</code>. Add them one by one, paste many at once with <b>Bulk edit</b>, or link a text file (or a Google Sheet published as CSV) that holds them. Duplicates are checked once.

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

<b>Fast</b> asks for the headers only and makes a normal request only when a server answers that badly. <b>Normal request</b> always asks for the page, like a browser; use it for sites that answer header-only requests wrongly.

## `includeHeaders` (type: `boolean`):

Add every header of the final answer to the result, for example <code>server</code>, <code>cache-control</code>, <code>last-modified</code> or <code>x-robots-tag</code>.

## `perHostConcurrency` (type: `integer`):

How many addresses of the same website are checked at the same time. Keep it low for sites you do not run; raise it for your own site to finish long lists faster.

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

How long to wait for an address to answer before counting it as not answering.

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

The name the tool sends with each request. Leave empty to use the tool's own name, which tells site owners what is visiting. Set your own only for sites you run or have permission to test.

## Actor input object example

```json
{
  "urls": [
    {
      "url": "https://apify.com"
    },
    {
      "url": "http://crawlee.dev"
    },
    {
      "url": "https://blog.apify.com/this-page-does-not-exist/"
    }
  ],
  "method": "AUTO",
  "includeHeaders": false,
  "perHostConcurrency": 2,
  "requestTimeoutSecs": 20
}
```

# Actor output Schema

## `statuses` (type: `string`):

One record per address with its HTTP status, result, redirect chain and response time.

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

Counts for the run: addresses checked, working, redirected, broken, refused and skipped.

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

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

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

```

## MCP server setup

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