Chaînes de redirections : détecter et corriger redirect chains et loops

Un site e-commerce de 22 000 pages. Deux refontes en trois ans. Trois changements de structure d'URL. Résultat : 4 700 URLs internes pointent vers des chaînes de 3 à 7 redirections, Googlebot abandonne le crawl de catégories entières, et le trafic organique chute de 34 % en huit semaines — sans qu'aucune alerte ne remonte dans la Search Console.

Les redirect chains sont le type de dette technique qui s'accumule silencieusement, refonte après refonte, migration après migration. Contrairement à une erreur 404 qui déclenche une alerte visible, une chaîne de redirections fonctionne — l'utilisateur finit par arriver quelque part. Mais entre-temps, le crawl budget est brûlé, le PageRank se dilue à chaque saut, et le temps de chargement perçu se dégrade.

Anatomie d'une redirect chain et d'une redirect loop

Redirect chain : le saut en cascade

Une redirect chain se produit lorsqu'une URL A redirige vers B, qui redirige vers C, qui redirige éventuellement vers D. Chaque saut est une redirection valide individuellement, mais l'enchaînement crée un chemin inutilement long.

Le scénario classique :

GET /produits/chaussures-running → 301 → /shoes/running → 301 → /fr/shoes/running → 301 → /fr/chaussures/running → 200 OK

Trois redirections avant d'atteindre la ressource finale. La première est un vestige de la structure v1 du site. La deuxième provient d'une migration vers une architecture multilingue. La troisième corrige un choix de slug en anglais vers du français. Chaque décision était logique au moment où elle a été prise. L'agrégation est toxique.

Redirect loop : le cercle vicieux

La redirect loop est plus destructrice : l'URL A redirige vers B, qui redirige vers A (ou vers C, qui redirige vers A). Aucune ressource n'est jamais servie. Le navigateur affiche ERR_TOO_MANY_REDIRECTS après un nombre de hops configurable (Chrome s'arrête à 20 par défaut). Googlebot abandonne encore plus tôt — la documentation Google indique que Googlebot suit au maximum 10 redirections avant de considérer l'URL en erreur.

Un cas fréquent en production — un conflit entre règles serveur et logique applicative :

# .htaccess — force HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

# Application (middleware Express/Next.js) — force www
if (!req.headers.host.startsWith('www.')) {
  return res.redirect(301, `http://www.${req.headers.host}${req.url}`);
}

Le .htaccess redirige http://www.example.com vers https://www.example.com. Le middleware applicatif, lui, redirige https://example.com vers http://www.example.com (notez le http:// en dur). Le cycle est bouclé : HTTP → HTTPS → HTTP+www → HTTPS+www → le middleware renvoie vers HTTP+www… et ainsi de suite.

Pourquoi les moteurs de recherche détestent les deux

Trois impacts directs :

Gaspillage de crawl budget. Chaque saut dans une chaîne consomme une requête de crawl. Sur un site de 20 000 pages avec 5 000 URLs en chaîne de 3 hops, c'est 10 000 requêtes de crawl gaspillées par cycle. Google a confirmé dans sa documentation sur le crawl budget que les redirections inutiles réduisent la capacité de crawl effective. Si vous gérez un site suffisamment gros pour que le crawl budget soit un facteur réel, la lecture de notre article sur le crawl budget est un bon complément.

Dilution du PageRank. Bien que Google affirme officiellement que les redirections 301 transmettent le PageRank, le passage par plusieurs sauts introduit une réalité plus nuancée. Chaque hop est un point de friction potentiel — un saut qui expire, un serveur intermédiaire lent, une configuration qui change. En pratique, une chaîne de 4 redirections perd significativement plus de "link equity" qu'une redirection directe, ne serait-ce que parce que Googlebot peut abandonner le suivi avant la fin.

Dégradation UX mesurable. Chaque redirection ajoute un RTT (Round-Trip Time) complet. Sur mobile 4G avec 100ms de latence, une chaîne de 4 redirections ajoute 400ms minimum au TTFB perçu. C'est un impact direct sur le Largest Contentful Paint et la perception de vitesse globale.

Détecter les redirect chains à grande échelle

Avec Screaming Frog

Screaming Frog reste l'outil de référence pour l'audit de redirections à l'échelle. Après un crawl complet, le rapport Response Codes > Redirection (3xx) > Redirect Chains liste toutes les chaînes identifiées avec le nombre de hops.

Configuration recommandée pour un audit exhaustif :

  1. Configuration > Spider > Always Follow Redirects : activé
  2. Configuration > Spider > Max Redirects : monter à 10 (par défaut 5, ce qui peut masquer des chaînes longues)
  3. Reports > Redirects > Redirect Chains : exporter le rapport complet

Le rapport vous donne pour chaque chaîne : l'URL source, chaque URL intermédiaire, l'URL finale, et le code HTTP de chaque saut. C'est la base de votre plan de correction.

Avec cURL en ligne de commande

Pour un diagnostic rapide ou un script d'audit automatisé, curl avec l'option -L (follow redirects) et -v (verbose) est imbattable :

# Suivre la chaîne complète avec timestamps
curl -L -w "\n\nTotal time: %{time_total}s\nNumber of redirects: %{num_redirects}\nFinal URL: %{url_effective}\n" \
     -o /dev/null -s -D - \
     "https://www.monsite.fr/ancienne-categorie/chaussures"

# Sortie typique d'une chaîne de 3 sauts :
# HTTP/2 301
# location: https://www.monsite.fr/shoes/running
#
# HTTP/2 301
# location: https://www.monsite.fr/fr/shoes/running
#
# HTTP/2 301
# location: https://www.monsite.fr/fr/chaussures/running
#
# HTTP/2 200
#
# Total time: 1.247s
# Number of redirects: 3
# Final URL: https://www.monsite.fr/fr/chaussures/running

Pour auditer en masse, combinez avec xargs et une liste d'URLs extraite de votre sitemap :

# Extraire les URLs du sitemap et tester chacune
curl -s "https://www.monsite.fr/sitemap.xml" | \
  grep -oP '(?<=<loc>).*?(?=</loc>)' | \
  xargs -I {} -P 10 sh -c \
  'REDIRECTS=$(curl -s -o /dev/null -w "%{num_redirects}" -L "{}"); \
   if [ "$REDIRECTS" -gt 1 ]; then echo "{} → $REDIRECTS redirects"; fi'

Ce script parallélise les requêtes (10 simultanées) et ne remonte que les URLs avec plus d'une redirection. Simple, efficace, scriptable dans une CI.

Avec la Search Console et l'API URL Inspection

La Search Console ne signale pas directement les redirect chains comme telles. En revanche, le rapport Indexation > Pages peut révéler des symptômes : URLs avec le statut "Page avec redirection" dont la destination finale n'est pas celle attendue.

L'API URL Inspection est plus exploitable programmatiquement. Pour chaque URL inspectée, la réponse inclut le champ inspectionResult.indexStatusResult.pageFetchState et lastCrawlTime. Une URL en chaîne de redirection apparaîtra avec un pageFetchState de type REDIRECT et l'URL finale résolue dans inspectionResult.indexStatusResult.referringUrls.

Avec Chrome DevTools — Network panel

Pour un diagnostic chirurgical sur une URL spécifique :

  1. Ouvrez DevTools (F12), onglet Network
  2. Cochez Preserve log (indispensable pour voir les redirections, sinon le log se vide à chaque navigation)
  3. Décochez Disable cache pour reproduire le comportement d'un premier visiteur
  4. Naviguez vers l'URL suspecte

Chaque ligne 301/302 dans le waterfall représente un saut. La colonne Time montre le coût de chaque hop. La colonne Initiator vous indique si la redirection provient du serveur (header Location) ou d'un <meta http-equiv="refresh"> côté client.

Scénario réel : migration d'un média en ligne de 8 000 pages

Prenons un cas concret. Un média en ligne — appelons-le TechActu — gère 8 000 articles. En 2024, migration du CMS custom vers WordPress. En 2025, passage de techactu.fr/article/[id]-[slug] vers techactu.fr/[categorie]/[slug]. En 2026, activation du multilingue avec sous-répertoire /fr/.

L'état des lieux

Après la seconde migration, un audit Screaming Frog révèle :

  • 2 340 URLs en chaîne de 2 redirections (structure v1 → v2 → v3)
  • 890 URLs en chaîne de 3 redirections (structure v1 → v2 → v3 + multilingue)
  • 47 URLs en redirect loop (conflit entre les anciennes règles .htaccess v1 et les rewrite rules WordPress)
  • Temps de crawl moyen pour les pages en chaîne : 1.8s contre 0.4s pour les pages directes

L'impact mesuré

En croisant les données de la Search Console (rapport Performances, filtre par page) avec les données de crawl :

  • Les 890 URLs en chaîne de 3 hops avaient un taux de crawl 60 % inférieur aux pages similaires sans redirection
  • 312 articles parmi les plus anciens (et les plus liés par des backlinks externes) n'avaient pas été recrawlés depuis 6 semaines
  • Le trafic organique sur ces 312 articles avait chuté de 41 % sur la période

Le plan de correction

Phase 1 — Aplatir les chaînes (semaine 1). Chaque redirection intermédiaire est réécrite pour pointer directement vers l'URL finale. Concrètement, au lieu de :

/article/1234-guide-seo → /tech/guide-seo → /fr/tech/guide-seo

On réécrit :

/article/1234-guide-seo → /fr/tech/guide-seo
/tech/guide-seo → /fr/tech/guide-seo

Chaque URL historique redirige en un seul saut vers la destination finale. La configuration Nginx consolidée :

# Fichier /etc/nginx/conf.d/redirects-legacy.conf
# Généré automatiquement à partir de l'export Screaming Frog

# Anciennes URLs v1 (format /article/[id]-[slug])
location ~ ^/article/\d+-(.*) {
    return 301 /fr/tech/$1;
}

# Anciennes URLs v2 (format /[categorie]/[slug] sans préfixe langue)
location ~ ^/(tech|science|business)/(.+)$ {
    return 301 /fr/$1/$2;
}

# Boucles identifiées — redirection forcée vers URL canonique
location = /fr/tech/guide-seo-2024 {
    return 301 /fr/tech/guide-seo;
}

Phase 2 — Corriger les loops (semaine 1, priorité critique). Les 47 redirect loops étaient causées par un conflit entre les anciennes règles .htaccess (restées dans le répertoire wp-content d'un ancien sous-domaine) et les rewrite rules du nouveau WordPress. Suppression pure et simple du .htaccess vestige, et ajout d'une règle Nginx explicite pour les URLs concernées.

Phase 3 — Mettre à jour les liens internes (semaines 2-3). Les redirections sont un filet de sécurité, pas un état permanent. Chaque lien interne pointant vers une URL redirigée doit être mis à jour vers l'URL finale. Sur WordPress, une requête SQL ciblée accélère le processus :

-- Identifier les liens internes pointant vers des URLs redirigées
SELECT ID, post_title, post_content
FROM wp_posts
WHERE post_status = 'publish'
  AND post_type = 'post'
  AND (
    post_content LIKE '%href="/article/%'
    OR post_content LIKE '%href="/tech/%'
    OR post_content LIKE '%href="/science/%'
    OR post_content LIKE '%href="/business/%'
  );

-- Remplacement en masse (à exécuter après backup)
UPDATE wp_posts
SET post_content = REPLACE(post_content, '"/tech/', '"/fr/tech/')
WHERE post_content LIKE '%"/tech/%'
  AND post_status = 'publish';

Attention : exécutez toujours ce type de remplacement sur une base de staging d'abord. Et vérifiez que la regex n'attrape pas des faux positifs (un slug comme /technique/ serait capturé par %/tech/%).

Phase 4 — Soumettre les sitemaps mis à jour et forcer le recrawl (semaine 3). Mise à jour du sitemap XML avec uniquement les URLs finales. Soumission via la Search Console. Utilisation de l'API URL Inspection pour forcer l'inspection des 312 articles critiques.

Les résultats (8 semaines post-correction)

  • Temps de crawl moyen redescendu à 0.5s (contre 1.8s avant)
  • Les 312 articles critiques recrawlés en moins de 10 jours
  • Trafic organique sur le périmètre impacté : +28 % à 8 semaines (sans récupérer 100 % du niveau pré-migration, ce qui est normal — certains articles avaient perdu des positions consolidées par des concurrents entre-temps)

Les causes racines des redirect chains — et comment les prévenir

Migrations successives sans consolidation

C'est la cause n°1. Chaque migration ajoute une couche de redirections, et personne ne prend le temps de consolider les couches précédentes. La règle est simple : après chaque migration, chaque ancienne URL doit rediriger en un seul hop vers l'URL finale. Pas vers l'URL intermédiaire.

Intégrez cette vérification dans votre checklist de migration. Si vous utilisez un outil de monitoring comme Seogard, configurez une alerte sur les chaînes de plus d'un saut pour détecter les régressions dès le déploiement.

Conflit HTTP/HTTPS et www/non-www

Le piège classique décrit plus haut. La solution : une seule règle, au niveau le plus bas possible (niveau serveur, pas applicatif) qui normalise en une seule redirection vers la forme canonique.

Configuration Nginx recommandée — une seule redirection pour tous les cas :

# Attraper TOUTES les variantes non-canoniques en un seul bloc
server {
    listen 80;
    listen 443 ssl;
    server_name techactu.fr www.techactu.fr;

    # Si ce n'est pas HTTPS + www → redirection unique
    if ($scheme != "https") {
        return 301 https://www.techactu.fr$request_uri;
    }
    if ($host != "www.techactu.fr") {
        return 301 https://www.techactu.fr$request_uri;
    }

    # Configuration du site...
}

Note : l'utilisation de if dans Nginx est souvent déconseillée dans un contexte location, mais dans le contexte server pour des redirections simples, c'est le pattern recommandé. L'alternative propre est d'utiliser deux blocs server séparés :

# Bloc qui attrape toutes les variantes non-canoniques
server {
    listen 80;
    listen 443 ssl;
    server_name techactu.fr;
    return 301 https://www.techactu.fr$request_uri;
}

# Bloc qui attrape HTTP sur www
server {
    listen 80;
    server_name www.techactu.fr;
    return 301 https://www.techactu.fr$request_uri;
}

# Bloc canonique
server {
    listen 443 ssl;
    server_name www.techactu.fr;
    # Configuration du site...
}

Cette approche garantit qu'aucune combinaison ne nécessite plus d'un saut.

Trailing slashes et paramètres de tracking

Deux sources de chaînes souvent oubliées :

  • /fr/chaussures redirige vers /fr/chaussures/ (trailing slash), puis /fr/chaussures/ redirige vers /fr/chaussures/running (ancienne règle de rewrite) — chaîne de 2
  • /fr/chaussures?utm_source=newsletter → la règle de redirect ne gère pas les query strings → redirection vers /fr/chaussures/ sans les paramètres → le système de tracking côté client redirige à nouveau vers l'URL avec paramètres → loop

La règle : normalisez les trailing slashes une seule fois, au niveau serveur, et assurez-vous que vos règles de redirection préservent (ou ignorent proprement) les query strings.

Redirections côté client via JavaScript ou meta refresh

Un cas piège : des redirections qui n'apparaissent pas dans les headers HTTP mais dans le body HTML.

<!-- Redirection côté client — invisible pour curl, visible pour un navigateur headless -->
<meta http-equiv="refresh" content="0;url=/fr/nouvelle-page">

Ou pire, en JavaScript :

// Redirection JS — invisible pour Googlebot dans certains cas
window.location.href = '/fr/nouvelle-page';

Ces redirections ne sont pas des 301. Elles ne transmettent pas (ou très mal) le PageRank. Et elles sont invisibles aux outils qui se contentent de lire les headers HTTP. Googlebot les détecte partiellement grâce à son rendering, mais avec un délai et une fiabilité moindre. Pour approfondir la gestion des directives côté client, notre article sur les meta robots couvre les interactions entre meta refresh et indexation.

Automatiser la détection en continu

Un audit ponctuel ne suffit pas. Les redirect chains réapparaissent à chaque déploiement, chaque modification de règle serveur, chaque plugin WordPress mis à jour (ce dernier point est un sujet de vigilance permanent).

Script de monitoring en CI/CD

Intégrez un test de redirections dans votre pipeline de déploiement. Voici un script Node.js minimaliste qui vérifie qu'aucune URL du sitemap ne dépasse un saut de redirection :

// check-redirects.ts — à exécuter dans votre CI (GitHub Actions, GitLab CI, etc.)
import { parseStringPromise } from 'xml2js';

interface RedirectResult {
  url: string;
  redirectCount: number;
  finalUrl: string;
  chain: string[];
}

async function checkRedirects(url: string, maxHops = 10): Promise<RedirectResult> {
  const chain: string[] = [url];
  let currentUrl = url;
  let redirectCount = 0;

  for (let i = 0; i < maxHops; i++) {
    const response = await fetch(currentUrl, { redirect: 'manual' });
    
    if (response.status >= 300 && response.status < 400) {
      const location = response.headers.get('location');
      if (!location) break;
      
      // Résoudre les URLs relatives
      currentUrl = new URL(location, currentUrl).toString();
      chain.push(currentUrl);
      redirectCount++;
      
      // Détection de loop
      if (chain.filter(u => u === currentUrl).length > 1) {
        throw new Error(`Redirect loop detected: ${chain.join(' → ')}`);
      }
    } else {
      break;
    }
  }

  return { url, redirectCount, finalUrl: currentUrl, chain };
}

async function main() {
  const sitemapResponse = await fetch('https://www.monsite.fr/sitemap.xml');
  const sitemapXml = await sitemapResponse.text();
  const parsed = await parseStringPromise(sitemapXml);
  
  const urls: string[] = parsed.urlset.url.map(
    (entry: { loc: string[] }) => entry.loc[0]
  );

  console.log(`Checking ${urls.length} URLs for redirect chains...`);
  
  const problems: RedirectResult[] = [];
  
  for (const url of urls) {
    try {
      const result = await checkRedirects(url);
      if (result.redirectCount > 1) {
        problems.push(result);
        console.error(
          `⚠ ${url} → ${result.redirectCount} redirects → ${result.finalUrl}`
        );
      }
    } catch (error) {
      console.error(`✗ ${url} → ${(error as Error).message}`);
      process.exitCode = 1;
    }
  }

  if (problems.length > 0) {
    console.error(`\n${problems.length} redirect chains detected.`);
    process.exitCode = 1;
  } else {
    console.log('✓ No redirect chains found.');
  }
}

main();

Exécutez-le dans votre pipeline après chaque déploiement. Si une chaîne de plus d'un hop est détectée, le build échoue. C'est brutal, mais c'est ce qui empêche la dette de s'accumuler.

Monitoring continu via crawl régulier

Le script CI ne couvre que les URLs du sitemap. Pour détecter les chaînes sur des URLs non-sitemapées (anciennes URLs, URLs liées depuis l'extérieur), un crawl régulier est nécessaire. C'est précisément le type de régression qu'un outil de monitoring continu comme Seogard détecte automatiquement — chaque URL est surveillée et toute apparition de hop supplémentaire déclenche une alerte avant que l'impact SEO ne se matérialise.

Redirect chains et canonicals : le piège de l'incohérence

Un edge case redoutable : quand l'URL canonique déclarée dans la balise <link rel="canonical"> pointe vers une URL différente de l'URL finale de la chaîne de redirections.

Exemple :

  • Page servie à /fr/chaussures/running avec <link rel="canonical" href="https://www.monsite.fr/fr/chaussures/running">
  • Mais les backlinks externes pointent vers /shoes/running
  • /shoes/running → 301 → /fr/shoes/running → 301 → /fr/chaussures/running

Jusque-là, cohérent (la chaîne mène bien à la canonical). Mais si quelqu'un modifie la canonical pour pointer vers /fr/chaussures/running/ (avec trailing slash) alors que la page est servie sans trailing slash, Google reçoit un signal contradictoire. La chaîne de redirections mène à une URL, la canonical en déclare une autre.

Pour une compréhension approfondie de la balise canonical et de ses pièges, notre guide sur les URL canoniques détaille les interactions entre redirections et canonicalisation.

La règle absolue : l'URL finale de chaque chaîne de redirections doit être identique, caractère pour caractère, à l'URL déclarée dans la balise canonical de la page de destination. Y compris le protocole, le sous-domaine, le trailing slash et la casse.

Quand conserver une chaîne de redirections (oui, ça existe)

Il serait malhonnête de prétendre que toute chaîne de redirections est mauvaise. Il existe des cas légitimes :

Redirections temporaires empilées intentionnellement. Pendant une période de maintenance ou un A/B test, une redirection 302 temporaire peut s'ajouter à une 301 existante. Si la durée est courte (quelques jours) et que le volume d'URLs est limité, le coût est acceptable.

Contraintes d'infrastructure. Sur une architecture avec CDN + load balancer + serveur applicatif, il arrive qu'une redirection HTTPS soit gérée au niveau CDN et une redirection de normalisation d'URL au niveau applicatif. Consolider les deux au même niveau n'est pas toujours possible sans risque opérationnel. Dans ce cas, documentez la chaîne, monitorez-la, et acceptez le trade-off.

Redirections cross-domain. Quand ancien-domaine.fr redirige vers nouveau-domaine.fr qui lui-même normalise www — techniquement deux sauts, mais ils opèrent à des niveaux différents (changement de domaine + normalisation). Le consolider en un seul saut nécessite que l'ancien domaine connaisse la forme canonique exacte du nouveau, ce qui crée un couplage fort entre les deux infrastructures.

Dans tous ces cas : documentez, monitorez, et réévaluez régulièrement.


Les redirect chains sont de la dette technique SEO au sens le plus pur : elles s'accumulent progressivement, ne génèrent aucune erreur visible, et leur impact composite finit par coûter très cher. La seule défense durable est la combinaison d'un audit initial rigoureux, d'une consolidation systématique après chaque migration, et d'un monitoring continu qui détecte chaque nouveau hop avant qu'il ne se transforme en chaîne.

Articles connexes

Redirections5 avril 2026

Redirections 301 vs 302 : impact SEO et cas d'usage réels

301 ou 302 ? Quand utiliser chaque redirection, leur impact réel sur le crawl budget et le transfert de PageRank, avec configs serveur et scénarios concrets.

Redirections5 avril 2026

Migration de site : checklist SEO des redirections

Plan de redirection complet pour migrer sans perte de trafic. Crawl, mapping, tests, monitoring post-migration. Guide actionable.

Redirections5 avril 2026

Trailing slash : impact SEO et configuration technique

Configurez correctement les trailing slashes pour éviter le contenu dupliqué, les chaînes de redirections et la dilution de PageRank.