All lintlab tools

Bulk redirect checker: every redirecting link on your site

What it does

A single-URL redirect checker tells you where one link goes. After a migration, an HTTPS switch or a trailing-slash change, the question is different: which links on my own pages still point at old URLs? This Actor crawls your site, checks every internal link it finds, and lists each one that redirects: the page it's on, the first status (301, 302, 303, 307 or 308), the final URL and the number of hops.

  • One-hop redirects are listed too, not only chains: a permanent 301 or 308 is a notice (update the link to save a hop), a temporary 302, 303 or 307 is a warning (it may not pass ranking signals the way you expect).
  • Redirect chains of 2+ hops and broken internal links come in the same crawl.
  • A site summary lists every redirecting URL once, up to 500, so you can fix them in one pass.
  • Rate limits aren't reported as broken: if your server answers 429 (or 503 with Retry-After), the check waits and retries; if it still can't get through, the link is listed as "not verified", never as broken.

Try it on Apify

A real run

We ran the published Actor on Apify (run MuT3BROKGZUADvbR4, 2026-10-02) on 5 pages of djangoproject.com (its robots.txt allows these paths) with link checks on. Of 80 internal links checked, 45 redirect, 0 are broken, and 9 couldn't be verified because the server rate-limited the checks. All 45 are 301s from download links to a separate media host, which is by design; the report shows where each one lands, so you decide which to update.

Input JSON

{
  "startUrls": [{ "url": "https://www.djangoproject.com" }],
  "maxPages": 5,
  "followLinks": true,
  "discoverSitemap": false,
  "maxLinkChecks": 80
}

Output excerpt

{
  "checkId": "links.redirected",
  "severity": "notice",
  "message": "Internal link https://www.djangoproject.com/download/6.1.1/tarball/ redirects with HTTP 301 to https://media.djangoproject.com/releases/6.1/django-6.1.1.tar.gz.",
  "fix": "Link straight to https://media.djangoproject.com/releases/6.1/django-6.1.1.tar.gz.",
  "value": {
    "url": "https://www.djangoproject.com/download/6.1.1/tarball/",
    "status": 301,
    "location": "https://media.djangoproject.com/releases/6.1/django-6.1.1.tar.gz",
    "finalUrl": "https://media.djangoproject.com/releases/6.1/django-6.1.1.tar.gz",
    "hops": 1
  }
}
SUMMARY.redirectedLinks[0]:
{
  "from": "https://www.djangoproject.com/download/",
  "url": "https://www.djangoproject.com/download/6.1.1/tarball/",
  "status": 301,
  "finalUrl": "https://media.djangoproject.com/releases/6.1/django-6.1.1.tar.gz",
  "hops": 1
}

Price and limits

$0.004 per successfully audited page. Link checks and redirect findings are free, within the configured cap.

  • Up to 10,000 unique internal link checks per run (set maxLinkChecks); links to other sites aren't followed.
  • At most 10 redirects followed per link.
  • HTTP-only: JavaScript redirects and meta-refresh pages aren't followed as redirects.

When a free tool is better

To check where one URL goes, a free single-URL checker or curl -I -L <url> in a terminal is faster. To check a list of old URLs you already have (a redirect map), a bulk URL checker fits better. This Actor is for finding the redirecting links inside your own pages, which you can't list by hand.

Same crawl, other checks: Broken link checker · Meta tag checker.