SEO и редиректы через .htaccess

Всё, что нужно знать о SEO-настройках через .htaccess: один канонический адрес (без дублей www/без-www, http/https, со слешом/без), правильные редиректы при переносах — подробно разобрано ниже. Инструменты: пакетный генератор 301-редиректов, тестер RewriteRule, линтер .htaccess. Рецепты быстрого доступа — в рецептах .htaccess; страницы ошибок — в гиде «Почему .htaccess не работает».

Канонизация хоста, редиректы при переезде страниц и доменов, цепочки, чистые URL, X-Robots-Tag — всё ниже. Если нужны рецепты под конкретную CMS — хаб WordPress или хаб CMS и фреймворков.

1. Почему .htaccess важен для SEO

Поисковые системы рассматривают http://example.com/page, https://example.com/page, https://www.example.com/page и https://example.com/page/ как разные URL. Если они отдают одинаковый контент без редиректа на один «главный» адрес, это дубли — поисковик дробит «ссылочный вес» (PageRank), вместо того чтобы концентрировать его на одной странице.

Файл .htaccess — самый быстрый способ настроить канонический адрес на уровне сервера: 301-редирект сообщает поисковику «этот адрес переехал навсегда, переноси весь вес на новый». Без этого краулер будет обходить несколько копий вашего сайта, тратить краулинговый бюджет впустую и ранжировать дубли ниже, чем единый канонический URL.

Также через .htaccess решаются: 301-перенос страниц при переструктурировании, X-Robots-Tag: noindex для staging-зеркал и PDF-файлов, чистые URL без .php-расширений. Что нельзя (или не нужно) делать через .htaccess: тег canonical и hreflang — это HTML <head>, не сервер; автоматический редирект по языку браузера Google не любит (может засчитать как маскировку); параметры UTM лучше «канонизировать» тегом, а не редиректом (редирект сломает аналитику).

2. Канонический хост: www, HTTPS, слеш

Задача — одним блоком правил сделать так, чтобы любой вариант адреса (http, https, www, без-www) редиректил к единственному каноническому хосту по HTTPS. Делать это двумя отдельными блоками (один для www→без-www, другой для http→https) опасно: браузер может попасть в цепочку из двух хопов. Лучше — один совмещённый блок.

Вариант «без-www» как канонический (рекомендуется):

.htaccessкопировать
<IfModule mod_rewrite.c>
RewriteEngine On
# Убрать www, одновременно → https
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
# Остался не-www, но http — → https
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

Если сайт работает за CDN или прокси (Cloudflare, nginx-реверс), Apache всегда видит соединение как http. Используйте заголовок X-Forwarded-Proto:

.htaccessкопировать
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>
  • После настройки редиректа укажите основное зеркало в Google Search Console («Настройки» → «Изменить адрес») и в Яндекс.Вебмастере («Индексирование» → «Главное зеркало»).
  • Собрать блок из чекбоксов — генератор; проверить конкретный URL — тестер RewriteRule; рецепты www/HTTPS — /cookbook/ → WWW и /cookbook/ → HTTPS.

3. Политика завершающего слеша

Решите один раз: ваш сайт использует URL со слешом (/about/) или без слеша (/about)? Оба варианта допустимы, но выберите один и приведите к нему все URL постоянным редиректом. Смешивание создаёт дубли страниц.

Добавить завершающий слеш (если запрос — не файл с расширением):

.htaccessкопировать
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+[^/])$ /$1/ [R=301,L]
</IfModule>

Убрать завершающий слеш (кроме корня /):

.htaccessкопировать
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.+)/$ /$1 [R=301,L]
</IfModule>
  • Грабли: не трогайте /index.php и файлы с расширением — условие !-f в блоке «добавить» защищает от этого.
  • Apache по умолчанию сам добавляет слеш к каталогам (DirectorySlash On) — не создавайте петлю, добавляя ещё один редирект «добавить слеш» поверх этого поведения.
  • Не делайте одновременно «добавить» и «убрать» — получите бесконечный редирект.

4. 301 vs 302 vs 307/308 vs 410

Выбор кода ответа напрямую влияет на SEO и поведение браузера:

  • 301 Moved Permanently — постоянный переезд. Поисковик переносит «ссылочный вес» на новый URL и со временем исключает старый из индекса. Браузер кэширует редирект — пользователь, открывший старый URL, уйдёт на новый даже без сервера. Используйте для постоянного переноса страниц и доменов.
  • 302 Found / 307 Temporary Redirect — временный редирект. Поисковик оставляет «вес» на старом URL (он остаётся в индексе). Браузер не кэширует. 302 исторически меняет метод (POST→GET), 307 сохраняет метод. Используйте для A/B-тестов, технических заглушек, временных переездов.
  • 308 Permanent Redirect — как 301, но сохраняет метод запроса (POST остаётся POST). Нужен для API и форм, а не для обычных страниц.
  • 410 Gone — страница удалена навсегда. Google быстрее исключает такие URL из индекса, чем при 404. Используйте для намеренно удалённых страниц без замены.

Миф: «302 не передаёт ссылочный вес». Google со временем может трактовать долго висящий 302 как 301, но надеяться на это не стоит — используйте 301 там, где переезд постоянный. В .htaccess: флаги [R=301,L], [R=302,L], [R=307,L], [R=308,L]; для 410 — [G] (Gone).

.htaccessкопировать
RewriteEngine On
RewriteRule ^obsolete-page$ - [G]

5. 301-редирект одной страницы

Простейший способ — директива Redirect из mod_alias (точное совпадение пути, без regex):

.htaccessкопировать
Redirect 301 /old-page.html /new-page.html

Для раздела целиком — RedirectMatch с регулярным выражением (группа (.*) захватывает путь после префикса):

.htaccessкопировать
RedirectMatch 301 ^/old-section/(.*)$ /new-section/$1

Альтернатива — через mod_rewrite (удобно, если уже есть другие RewriteRule-блоки):

.htaccessкопировать
RewriteEngine On
RewriteRule ^old-page\.html$ /new-page.html [R=301,L]

6. Массовый перенос URL

Если переезжаете на новую структуру URL и у вас десятки или сотни страниц — не пишите редиректы вручную. Подготовьте список «старый URL → новый URL» и воспользуйтесь пакетным генератором 301-редиректов: вставляете пары, выбираете формат (RewriteRule / Redirect) и код ответа — получаете готовый блок.

  • Грабли с порядком правил: более специфичные пути должны идти раньше общих. Если сначала стоит RedirectMatch 301 ^/blog/(.*)$ /articles/$1, а потом Redirect 301 /blog/special /new-special — второй никогда не сработает. Ставьте конкретные правила выше общих.
  • Грабли с петлями: проверьте, что ни один новый URL не совпадает со старым (иначе ERR_TOO_MANY_REDIRECTS).
  • После генерации — проверьте синтаксис в линтере и цепочки в тестере RewriteRule.

7. Цепочки редиректов: опасность и устранение

Цепочка редиректов — это когда A→B→C (и далее). Каждый дополнительный хоп это:

  • Лишний HTTP-запрос (задержка для пользователя, особенно на мобильных).
  • Потраченный краулинговый бюджет — краулер может не дойти до конечного URL.
  • Небольшая «утечка» ссылочного веса на каждом хопе (спорно, но лучше не рисковать).

Всегда редиректируйте напрямую A→C, минуя промежуточные шаги. Типичная причина цепочки: отдельный HTTP→HTTPS-редирект + отдельный www→без-www + постраничный редирект. Объедините первые два в один блок (см. раздел 2), тогда постраничный редирект будет лишь один хоп.

Как найти цепочки: чекер цепочки редиректов покажет все хопы; также DevTools → Network (вкладка, фильтр 3xx) или тестер RewriteRule — пошагово разберёт, во что переписывается каждый запрос.

8. Чистые URL для SEO

Адрес /about выглядит лучше и понятнее, чем /about.php. Чтобы убрать расширение .php из адреса — нужно два блока: внутренняя перезапись (пользователь видит чистый URL, сервер отдаёт .php-файл) и опционально 301-редирект со старого адреса с расширением на новый.

.htaccessкопировать
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^([^.]+)$ $1.php [L]

Если старые URL с .php уже проиндексированы — добавьте 301-редирект со страницы с расширением на чистый URL (условие по %{THE_REQUEST} предотвращает петлю):

.htaccessкопировать
RewriteCond %{THE_REQUEST} \s/+([^.\s]+)\.php[\s?] [NC]
RewriteRule ^ /%1 [R=301,L]

Убрать index.php или index.html из URL (301-редирект):

.htaccessкопировать
RewriteCond %{THE_REQUEST} /index\.(php|html)[\s?] [NC]
RewriteRule ^(.*?)index\.(php|html)$ /$1 [R=301,L]
  • Важно: после смены структуры URL обязательно поставьте 301-редиректы со старых адресов на новые — иначе входящие ссылки и закладки будут приводить к 404.
  • Рецепт с пояснениями — /cookbook/ → Убрать .php из URL.

9. X-Robots-Tag через .htaccess

Мета-тег <meta name="robots" content="noindex"> работает только для HTML-страниц — поисковик должен скачать страницу и прочитать тег. Для PDF, изображений, архивов и других не-HTML ресурсов единственный способ управлять индексированием — HTTP-заголовок X-Robots-Tag, который отдаётся через mod_headers.

Закрыть весь staging-сервер от индексирования:

.htaccessкопировать
<IfModule mod_headers.c>
    Header set X-Robots-Tag "noindex, nofollow"
</IfModule>

Запретить индексировать PDF и документы:

.htaccessкопировать
<IfModule mod_headers.c>
    <FilesMatch "\.(pdf|doc|docx)$">
        Header set X-Robots-Tag "noindex"
    </FilesMatch>
</IfModule>
  • Отличие от robots.txt: robots.txt запрещает сканирование (краулер не зайдёт), X-Robots-Tag и мета-тег запрещают индексирование (краулер зайдёт, но не внесёт в индекс). Для noindex краулер должен иметь возможность скачать страницу — не закрывайте её одновременно в robots.txt.
  • Классическая ошибка: забыли убрать noindex после переноса сайта со staging на production — весь сайт выпадает из индекса. Проверяйте после каждого деплоя.
  • Другие значения: noarchive (запрет кэширования в поисковике), nosnippet (запрет сниппета в выдаче). Подробнее — справочник HTTP-заголовков → управление контентом.

10. Чеклист переезда на новый домен

Переезд домена — одна из самых рискованных операций с точки зрения SEO. Правильно выполненный переезд с 301-редиректами практически не влияет на позиции в долгосрочной перспективе; ошибки могут стоить месяцев восстановления.

Блок редиректа на СТАРОМ домене (перенаправляет каждый путь на тот же путь нового домена, сохраняя query-строку):

.htaccessкопировать
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)$ https://new-domain.com/$1 [R=301,L,QSA]
</IfModule>

Флаг QSA (Query String Append) добавляет оригинальную query-строку к новому URL — без него ?utm_source=email и прочие параметры будут потеряны. Паттерн ^(.*)$ захватывает путь без query; %{REQUEST_URI} включал бы и query, поэтому лучше использовать $1 + QSA.

  1. На СТАРОМ домене — поставить вышеуказанный блок редиректа. Редиректировать на тот же путь (/page/https://new-domain.com/page/), не на главную нового домена.
  2. Держите старый домен и редирект работающим минимум год (а лучше два) — это нужно для того, чтобы все входящие ссылки и закладки обновились.
  3. В Google Search Console — воспользуйтесь функцией «Переезд сайта» (Изменение адреса) в настройках свойства старого домена.
  4. Обновите sitemap.xml на новом домене — только URL нового домена.
  5. Замените все внутренние ссылки и canonical-теги на новом домене на новые URL.
  6. Проверьте, что редирект сохраняет путь (не редиректирует всё на главную) — типичная ошибка, ведущая к «мягким 404» по всему сайту.
  • Грабли: редирект /page/https://new-domain.com/ (главная) вместо соответствующей страницы — Google видит это как «soft 404» и не передаёт вес со старых URL.

11. Типовые SEO-ошибки с .htaccess

  • (а) 302 вместо 301 на постоянном переносе. Используете 302 для переезда, который «навсегда»? Поисковик оставляет вес на старом URL, старая страница остаётся в индексе. Исправление: замените [R=302,L] на [R=301,L].
  • (б) Редирект 404 на главную. ErrorDocument 404 / или RewriteRule .* / [L] заставляет 404-страницы отдавать контент главной с кодом 200 (или 301). Google видит сотни «мягких 404» по всему сайту. Решение: нормальная страница 404 со статусом 404, а не редирект. Подробно — /errors/.
  • (в) Длинные цепочки редиректов. Старый http-редирект + www-редирект + постраничный редирект = три хопа. Объедините (см. раздел 7).
  • (г) Петля редиректа после перехода на HTTPS. За CDN %{HTTPS} всегда off — редирект уходит в бесконечную петлю. Используйте %{HTTP:X-Forwarded-Proto} (см. раздел 2).
  • (д) Забытый noindex после staging. Сайт перенесли с тестового сервера, но X-Robots-Tag: noindex в .htaccess остался. Весь сайт выпадает из индекса. Проверяйте заголовки после каждого деплоя.
  • (е) Дубли www / без-www без редиректа. Разный контент доступен и на www.example.com, и на example.com. Поисковик видит дубли, разбавляет вес. Исправление: редирект на канонический хост (см. раздел 2).
  • (ж) UTM-параметры создают «дубли». ?utm_source=email — технически другой URL. Не редиректируйте параметры (сломаете аналитику): используйте тег canonical в <head> на каждой странице, указывающий на чистый URL. Для аудита — аудит .htaccess; разобраться в чужом файле — объяснить .htaccess.

12. SEO-.htaccess за 5 минут

  1. Один канонический хост (www/без-www + https) одним коротким блоком? — раздел 2, генератор
  2. Нет петель и цепочек — проверить каждый URL в тестере RewriteRule?
  3. Переносы страниц — код 301 (не 302), на точный новый URL (не на главную)? — раздел 5
  4. 404 отдаёт статус 404 (не редирект на главную, не 200)? — гид по ошибкам
  5. noindex стоит ТОЛЬКО там, где надо (не на всём сайте)? — раздел 9
  6. Trailing-slash политика выбрана и не петляет? — раздел 3
  7. Синтаксис .htaccess проверен линтером? — /check/, /audit/