# URL Redirect Chain & Loop Analyzer (`andok/redirect-chain-analyzer`) Actor

Trace HTTP redirects across any domain. Identify broken links, infinite loops, and SEO-damaging redirect chains.

- **URL**: https://apify.com/andok/redirect-chain-analyzer.md
- **Developed by:** [Andok](https://apify.com/andok) (community)
- **Categories:** SEO tools, Developer tools
- **Features:** Limited permissions
- **Stats:** 11 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.47 / 1,000 url traceds

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

## Redirect Chain Analyzer

Trace every redirect chain in bulk during domain migrations to prevent SEO loss from broken or looping redirects. A single redirect loop or chain longer than 3 hops can cause search engines to drop pages from the index entirely. This actor follows 301/302/307/308 redirects for each URL, records every hop, and reports the final destination and status — processing thousands of URLs in minutes.

### Features

- **Full chain visibility** — records every redirect hop with URL, status code, Location header, and resolved next URL
- **Bulk processing** — analyze thousands of URLs in a single run with configurable concurrency
- **Loop detection** — identifies redirect loops and chains that exceed the configured hop limit
- **HTTP method control** — use HEAD requests for speed or GET when servers block HEAD
- **Flexible input** — accepts bare domains, HTTP URLs, or HTTPS URLs
- **Error resilience** — reports timeouts and connection errors per URL without stopping the run
- **Redirect counting** — separates total hops from actual redirect count for clear reporting

### Input

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `urls` | `array` | Yes | — | List of URLs to trace redirect chains for |
| `url` | `string` | No | — | Single URL for backward compatibility. Merged into `urls` if both are provided. |
| `followRedirects` | `boolean` | No | `true` | Whether to follow redirect responses or stop at the first hop |
| `maxRedirects` | `integer` | No | `10` | Maximum number of redirects to follow before stopping |
| `timeoutSeconds` | `integer` | No | `15` | HTTP timeout in seconds for each request |
| `concurrency` | `integer` | No | `10` | Number of URLs to process in parallel (1-50) |
| `method` | `string` | No | `HEAD` | HTTP method to use: HEAD (faster) or GET (more compatible) |

#### Input Example

```json
{
    "urls": [
        "http://example.com",
        "https://example.com/old-page",
        "http://www.example.com"
    ],
    "maxRedirects": 10,
    "method": "HEAD",
    "concurrency": 10
}
```

### Output

Each URL produces one dataset item with the complete redirect chain from input URL to final destination.

- `inputUrl` (`string`) — the original URL you provided
- `finalUrl` (`string | null`) — the URL after all redirects resolve
- `finalStatus` (`number | null`) — HTTP status code of the final destination
- `hopCount` (`number`) — total number of hops in the chain (including the final destination)
- `redirectCount` (`number`) — number of actual redirects (hopCount minus 1)
- `hops` (`array`) — ordered list of hops, each with `url`, `status`, `location`, and `nextUrl`
- `checkedAt` (`string`) — ISO timestamp
- `error` (`string`) — error message if the request failed (only present on errors)

#### Output Example

```json
{
    "inputUrl": "http://example.com",
    "finalUrl": "https://www.example.com/",
    "finalStatus": 200,
    "hopCount": 3,
    "redirectCount": 2,
    "hops": [
        {
            "url": "http://example.com",
            "status": 301,
            "location": "https://example.com/",
            "nextUrl": "https://example.com/"
        },
        {
            "url": "https://example.com/",
            "status": 301,
            "location": "https://www.example.com/",
            "nextUrl": "https://www.example.com/"
        },
        {
            "url": "https://www.example.com/",
            "status": 200,
            "location": null,
            "nextUrl": null
        }
    ],
    "checkedAt": "2025-11-20T14:30:00.000Z"
}
```

### Pricing

| Event | Cost |
|-------|------|
| URL Traced | $0.001 per URL |

You are charged per URL traced. Platform usage fees apply separately.

### Use Cases

- **Domain migration validation** — verify all old URLs redirect correctly to their new destinations after a migration
- **HTTP-to-HTTPS audit** — confirm every HTTP URL properly 301-redirects to its HTTPS counterpart
- **www/non-www canonicalization** — check that www and non-www versions resolve to a single canonical URL
- **Redirect chain cleanup** — find chains with 3+ hops that slow down crawling and dilute link equity
- **Vanity URL verification** — confirm short URLs and marketing redirects land on the correct pages

### Related Actors

| Actor | What it adds |
|-------|-------------|
| [Broken Links Checker](https://apify.com/andok/broken-links-checker) | Crawl your site to find broken links — then trace their redirect chains |
| [Hreflang Checker](https://apify.com/andok/hreflang-checker) | Verify hreflang target URLs do not redirect, which confuses search engines |
| [XML Sitemap URL Extractor](https://apify.com/andok/sitemap-extractor) | Extract all URLs from your sitemap to bulk-check their redirect behavior |

# Actor input Schema

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

List of URLs to trace redirect chains for. Accepts full URLs or bare domains — bare domains are automatically prefixed with https://.

## `url` (type: `string`):

A single URL for backward compatibility. If both this and the URLs list are provided, this is merged into the list.

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

Whether to follow redirect responses (301/302/303/307/308). Disable to only see the first response without following the chain.

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

Maximum number of redirects to follow per URL before stopping. Helps detect redirect loops. Set to 0 to disable redirect following.

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

HTTP timeout in seconds for each individual request in the redirect chain. Increase for slow-responding servers.

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

Number of URLs to trace simultaneously. Higher values speed up large batches but use more memory.

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

HTTP method for requests. HEAD is faster but some servers block it — switch to GET if you get unexpected results.

## Actor input object example

```json
{
  "urls": [
    "https://example.com",
    "http://example.com"
  ],
  "followRedirects": true,
  "maxRedirects": 10,
  "timeoutSeconds": 15,
  "concurrency": 10,
  "method": "HEAD"
}
```

# Actor output Schema

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

No description

## `resultsCsv` (type: `string`):

No description

## `run` (type: `string`):

No description

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

// Run the Actor and wait for it to finish
const run = await client.actor("andok/redirect-chain-analyzer").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",
        "http://example.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("andok/redirect-chain-analyzer").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",
    "http://example.com"
  ]
}' |
apify call andok/redirect-chain-analyzer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,andok/redirect-chain-analyzer"
        }
    }
}
```

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/lnEkLgjyrgaj8Gcn2/builds/ccHJcbOvJxlCj1M7q/openapi.json
