List redirect chains

GET/v1/api/sites/{site_id}/redirect-chains

List a site's redirect chains, as the Issues page lists them.

Page with cursor and the snapshot of the first response; both are opaque tokens and the snapshot binds every filter. availability says how much of the site was observed: partial or unknown make total null. total and confirmed_total are also null on cursor continuation pages. The read scans the site's chains, so keep limit and request rate moderate.

Scope
issues:read
Token
API key or OAuth access token
Role
Any workspace member
MCP tool
list_redirect_chains
What scopes, tokens and roles mean →
Request
curl "https://api.crawle.io/v1/api/sites/11111111-1111-1111-1111-111111111111/redirect-chains?limit=10" \
  -H "Authorization: Bearer $CRAWLE_API_KEY"
const response = await fetch("https://api.crawle.io/v1/api/sites/11111111-1111-1111-1111-111111111111/redirect-chains?limit=10", {
  headers: {
    Authorization: `Bearer ${process.env.CRAWLE_API_KEY}`,
  },
});
const data = await response.json();
import os

import requests

response = requests.request(
    "GET",
    "https://api.crawle.io/v1/api/sites/11111111-1111-1111-1111-111111111111/redirect-chains?limit=10",
    headers={
        "Authorization": f"Bearer {os.environ['CRAWLE_API_KEY']}",
    },
)
data = response.json()
$CRAWLE_API_KEY
is an API key from Settings › API keys.
Response 200JSON
{
  "availability": {
    "awaiting_first_observation": 1,
    "known": 1,
    "not_applicable": 1,
    "observed_at": "example",
    "policy_generation": 1,
    "reasons": [
      "example"
    ],
    "state": "known",
    "substrate": "raw",
    "total": 1,
    "unknown": 1
  },
  "chains": [
    {
      "chain_key": "example",
      "chain_status": "resolved",
      "crawled_at": "example",
      "cross_domain": true,
      "final_url": "https://example.com/",
      "hop_count": 1,
      "hops": [
        {
          "is_redirect_step": true,
          "location": "example",
          "status_code": 1,
          "unique_internal_source_count": 1,
          "url": "https://example.com/"
        }
      ],
      "inlinks_evaluated_at": "example",
      "last_known_url": "https://example.com/",
      "redirect_count": 1,
      "redirect_transition_count": 1,
      "site_id": 1,
      "start_url": "https://example.com/",
      "terminal_status_code": 1,
      "unavailable_reason": "example",
      "unique_internal_entry_source_count": 1,
      "unique_internal_inlink_count": 1,
      "url_id": 1
    }
  ],
  "confirmed_total": 1,
  "inlinks_evaluated_at": "example",
  "issue_type": "example",
  "next_cursor": "example",
  "snapshot": "example",
  "snapshot_at": "example",
  "title": "Example",
  "total": 1,
  "website_id": 1
}

Example generated from the API contract.

Parameters

site_idpath · string (uuid)required
min_redirectsquery · integer
0–100 · default 2
min_hopsquery · integer or null
1–100
max_hopsquery · integer or null
1–100
chain_statusquery · string or null
up to 40 characters
response_status_classquery · string or null
up to 10 characters
cross_domainquery · boolean or null
directoryquery · string or null
up to 768 characters
segment_idquery · integer or null
at least 1
searchquery · string or null
up to 500 characters
limitquery · integer
1–200 · default 50
cursorquery · string or null
1–8192 characters
snapshotquery · string or null
1–4096 characters

Pages with cursor and limit.

Response 200

availabilityPublicObservationAvailabilityrequired
awaiting_first_observationinteger or null
knowninteger or null
not_applicableinteger or null
observed_atstring or null
policy_generationinteger or null
reasonsarray of string
stateenumrequired
known: every page in scope was observed. partial: some were not, so total is null. unknown: the scope could not be determined. not_applicable and awaiting_first_observation: there is nothing to observe yet.one of "known", "partial", "unknown", "not_applicable", "awaiting_first_observation"
substrateenum or null
Which kind of observation the availability is about.one of "raw", "content", "restrictions", "graph"
totalinteger or null
Pages in scope.
unknowninteger or null
issue_typestringrequired
titlestringrequired
website_idintegerrequired
chainsarray of PublicRedirectChain
chain_keystringrequired
Identity of the chain within the snapshot it was listed in; opaque.
chain_statusenum or null
resolved: the chain ends at a final page. loop: it revisits a URL. break: a hop is missing or failed. truncated: it was cut at the crawler's hop limit. unavailable: the chain could not be read; see unavailable_reason.one of "resolved", "loop", "break", "truncated", "unavailable"
crawled_atstring or null
cross_domainboolean or null
final_urlstring or null
hop_countinteger or null
hopsarray of PublicRedirectHop
is_redirect_stepboolean or null
locationstring or null
status_codeinteger or null
unique_internal_source_countinteger or null
urlstringrequired
inlinks_evaluated_atstring or null
last_known_urlstring or null
redirect_countinteger or null
redirect_transition_countinteger or null
site_idinteger or null
start_urlstringrequired
terminal_status_codeinteger or null
unavailable_reasonstring or null
unique_internal_entry_source_countinteger or null
unique_internal_inlink_countinteger or null
url_idinteger or null
confirmed_totalinteger or null
Chains found among the pages observed so far; null on cursor continuation pages.
inlinks_evaluated_atstring or null
next_cursorstring or null
Opaque token for the next page, at most 8192 characters, or null on the last page.
snapshotstring or null
Opaque signed token for this listing, at most 4096 characters. Send it back with next_cursor, and with chain_key to read one chain; it binds the site and every filter.
snapshot_atstring or null
totalinteger or null
Chains in the listing, or null while the availability is partial or unknown, and also null on cursor continuation pages even when the availability is known: null does not always mean a partial observation.

Errors

  • 401

    When
    Missing, invalid, or expired token.
  • 403

    When
    The token has none of the accepted scopes (issues:read).
  • 409

    When
    Conflict with the current state. detail says why.
  • 422

    When
    The request did not match the schema. detail lists each problem.
  • 502

    When
    The site's crawler answered outside the contract (crawler_response_invalid).
  • 503

    When
    Temporarily unavailable. detail says whether a retry is safe.
  • 429

    When
    Rate limited. Wait for Retry-After seconds.

All errors and what to do →

Generated from the API contract at 7e7039b0b, synced October 30, 2026.