Цепочки и циклы редиректов: как найти и исправить
Практика3 минРедакция Innovialabs
Коротко
Цепочка редиректов — это несколько переходов до конечной страницы, а цикл не приводит к ней вовсе; оба случая лечатся одинаково: каждый старый URL и каждая внутренняя ссылка ведут на финальный адрес одним 301 или 308.
Коротко
Цепочка редиректов — это когда URL перенаправляет на другой URL, который снова перенаправляет, прежде чем дойти до конечной страницы: A → B → C. Цикл редиректов — когда переходы не заканчиваются: A → B → A.
Решение одно: любой старый адрес должен вести на финальный URL за один переход, а внутренние ссылки, canonical и sitemap — указывать на финальный URL напрямую, вообще без редиректа.
Чем вредят цепочки и циклы
- Расход краулингового бюджета. Каждый переход — отдельный запрос. На больших сайтах робот тратит время на редиректы вместо новых страниц.
- Размывание сигналов. Каждый лишний шаг — еще одна точка отказа: не тот код, потерянный параметр, временный редирект посередине.
- Лимиты обхода. Поисковики проходят только ограниченное число переходов. Если цепочка слишком длинная, робот не доходит до страницы и фиксирует ошибку переадресации.
- Медленная загрузка. Пользователь тоже ждет каждый переход, особенно это заметно в мобильных сетях.
- Цикл полностью ломает страницу. Браузер показывает ошибку, а поисковик не может проиндексировать URL.
Откуда они берутся
- Нормализация протокола и хоста в разных шагах:
http://example.com→https://example.com→https://www.example.com. - Правила для слеша в конце URL, добавленные поверх остальных.
- Несколько переездов сайта, каждый из которых добавлял свои редиректы к старым.
- Конфликт правил между сервером, CDN и приложением. Классический цикл: приложение за прокси видит HTTP и перенаправляет на HTTPS, хотя прокси уже отдает HTTPS.
Как их найти
Краулером
Запустите краулер (Screaming Frog, Sitebulb или аналог) с главной страницы и отдельно по списку старых URL. Ищите:
- URL с более чем одним переходом;
- внутренние ссылки, ведущие на редиректы;
- редиректы, которые заканчиваются 4xx или 5xx;
- циклы, отмеченные как ошибки.
В Search Console
В отчете Страницы (индексирование страниц) откройте статус Страница с переадресацией. Эти URL не индексируются, потому что перенаправляют. Для старых адресов это нормально, но список показывает, о каких редиректах Google все еще знает. Если эти адреса есть в вашем sitemap или во внутренних ссылках — обновите их. Отдельный статус Ошибка переадресации указывает на слишком длинные цепочки, циклы и битые цели редиректов.
Вручную
Чтобы увидеть все переходы для конкретного URL:
curl -sIL http://example.com/old-page | grep -iE "^(HTTP|location)"
Каждая строка HTTP — один ответ. Больше одного редиректа до финального 200 — это цепочка.
Как исправить
- Составьте таблицу: старый URL → финальный URL.
- Перепишите каждое правило так, чтобы оно вело сразу на финальный адрес.
- Объедините нормализацию (протокол, хост, слеш) в одно правило.
- Обновите внутренние ссылки, canonical, hreflang и sitemap на финальные URL.
- Перепроверьте сайт краулером.
Nginx
HTTP и хост без www сразу на финальный адрес:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
# здесь ssl_certificate и ssl_certificate_key
return 301 https://www.example.com$request_uri;
}
Apache (.htaccess)
Одно правило вместо двух отдельных шагов для HTTPS и www:
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [L,R=301]
Next.js
В next.config.js ведите старые адреса сразу на финальный. Если /old когда-то переехал на /new, а потом на /newest, оба правила должны вести на /newest:
module.exports = {
async redirects() {
return [
{ source: "/old", destination: "/newest", permanent: true },
{ source: "/new", destination: "/newest", permanent: true },
];
},
};
С permanent: true Next.js отдает 308 — поисковики считают его постоянным редиректом. Проверьте также, что настройка trailingSlash совпадает с адресами в destination, иначе Next.js добавит лишний переход.