301 редирект — це відповідь сервера, яка каже браузеру й пошуковому роботу: сторінка переїхала назавжди, ось її нова адреса. Від інших способів «перекинути» відвідувача він відрізняється тим, що переносить в індекс не лише адресу, а й накопичену вагу посилань. Нижче — готові правила для .htaccess під типові задачі, їхні аналоги для nginx і розбір помилок, через які переїзд коштує сайту трафіку.
Як це працює
Сервер відповідає на запит кодом 301 і заголовком Location із новою адресою. Браузер одразу йде туди, зазвичай непомітно для відвідувача, і кешує цей перехід. Пошуковик робить так само: замінює в індексі стару URL новою й передає їй посилальну вагу.
Різниця між кодами важлива й коштує грошей:
| Код | Що означає | Коли застосовувати |
|---|---|---|
| 301 | Переїхало назавжди | Зміна домену, адреси сторінки, склейка дзеркал, перехід на HTTPS |
| 302 | Тимчасово | Акція на пару тижнів, техроботи, A/B-тест |
| 307 | Тимчасово, метод запиту зберігається | Те саме, але для POST-запитів |
| 308 | Назавжди, метод зберігається | Рідкісний випадок: переїзд API, де важливий POST |
| 410 | Видалено назавжди | Сторінки більше немає й заміни їй немає |
Плутати 301 і 302 — найдорожча помилка в цьому списку: за 302 пошуковик лишає в індексі стару адресу й вагу на нову не передає.
Правила для .htaccess
Усі приклади розраховані на Apache з увімкненим mod_rewrite. Блок правил ставлять на початок файлу .htaccess у корені сайту — до правил CMS, інакше WordPress перехопить запит раніше.
RewriteEngine On
RewriteBase /
Одна сторінка на іншу
# простий варіант
Redirect 301 /old-page/ https://site.com/new-page/
# той самий результат через mod_rewrite, якщо решта правил теж на ньому
RewriteRule ^old-page/?$ https://site.com/new-page/ [R=301,L]
Склейка дзеркал: з www на без www
RewriteCond %{HTTP_HOST} ^www.(.+)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
Зворотний випадок, коли головним дзеркалом обрано домен із www:
RewriteCond %{HTTP_HOST} !^www. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
Перехід на HTTPS
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
За Cloudflare чи іншим проксі умова %{HTTPS} не спрацює — до сервера запит доходить уже по HTTP. Там перевіряють заголовок:
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
HTTPS і без www одним правилом
Головний прийом цього розділу: не ставити два правила поспіль, інакше вийде ланцюжок із двох переходів.
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} ^www.(.+)$ [NC]
RewriteRule ^(.*)$ https://site.com/$1 [R=301,L]
Слеш у кінці адреси
# додати слеш
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !.[a-zA-Z0-9]{1,5}$
RewriteCond %{REQUEST_URI} !/$
RewriteRule ^(.*)$ /$1/ [R=301,L]
# прибрати слеш
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [R=301,L]
Умови з !-f і !-d тут не формальність: без них правило почне переписувати адреси картинок та наявних папок.
Переїзд на новий домен
# зі збереженням адрес сторінок — так і треба робити
RewriteCond %{HTTP_HOST} ^(www.)?old-site.com$ [NC]
RewriteRule ^(.*)$ https://new-site.com/$1 [R=301,L]
# усе на головну — лише якщо структура нового сайту геть інша
RewriteRule ^(.*)$ https://new-site.com/ [R=301,L]
Другий варіант пошуковики часто вважають «м’якою 404» і вагу не передають. Переносьте адресу в адресу скрізь, де це можливо, а на головну відправляйте лише те, чому заміни немає.
Розділ на розділ і адреси з параметрами
# /blog/стаття/ → /news/стаття/
RewriteRule ^blog/(.*)$ /news/$1 [R=301,L]
# ?id=12 → /catalog/sofa/
RewriteCond %{QUERY_STRING} (^|&)id=12(&|$)
RewriteRule ^index.php$ /catalog/sofa/? [R=301,L]
Знак питання в кінці цілі відкидає вихідний рядок параметрів — без нього він приклеїться до нової адреси.
Те саме на nginx
У nginx немає .htaccess: правила живуть у конфігу сервера й застосовуються після nginx -t та перезавантаження.
server {
listen 80;
server_name www.site.com site.com;
return 301 https://site.com$request_uri;
}
# одна сторінка на іншу
location = /old-page/ {
return 301 https://site.com/new-page/;
}
# розділ на розділ
rewrite ^/blog/(.*)$ /news/$1 permanent;
Конструкція return 301 швидша за rewrite й читається однозначно, тому для простих випадків беруть саме її.
Часті помилки
- Ланцюжок редиректів. www → без www → https → слеш: чотири запити замість одного. Збирайте умови в одне правило.
- Цикл. Правило відправляє сторінку саму на себе, браузер показує
ERR_TOO_MANY_REDIRECTS. Зазвичай причина — редирект на HTTPS за проксі через%{HTTPS}. - 302 замість 301. Переїзд зроблено, а вага лишилася на старій адресі.
- Усе на головну. Масовий редирект сотень сторінок у корінь пошуковик вважає підміною 404.
- Правила після правил CMS. У
.htaccessWordPress перехопить запит першим, і ваше правило не спрацює: ставте свій блок вище. - Редирект замість canonical. Якщо обидві сторінки потрібні людям, а дублюється лише вміст, ставлять
rel="canonical", а не 301. - Забуті внутрішні посилання. Після переїзду посилання всередині сайту мають вести на нову адресу напряму, інакше кожен перехід відвідувача йде через редирект.
Як перевірити
Найшвидше — командою в терміналі. Ключ -I запитує лише заголовки, -L іде ланцюжком до кінця:
curl -sIL https://site.com/old-page/ | grep -E "HTTP/|Location"
Правильна відповідь виглядає так: один HTTP/1.1 301, один Location і далі HTTP/2 200. Два й більше 301 поспіль — це ланцюжок, його треба схлопнути. У Search Console той самий результат видно у звіті «Індексування сторінок», а в браузері — у вкладці Network, якщо увімкнути «Preserve log».
Після масового переїзду перевірте вибірку з двох-трьох десятків адрес: головну, категорії, картки, сторінки з параметрами й адреси з топу пошукової видачі.
Коротко про головне
301 — для постійного переїзду, 302 — для тимчасового, 410 — для того, чого більше немає. Правило пишеться одне й веде одразу на кінцеву адресу, без проміжних кроків. Перевіряти треба завжди — curl -sIL відповідає на питання за секунду.
Якщо переїзд великий — зміна домену, об’єднання сайтів, перехід на HTTPS із перебудовою адрес — напишіть нам: складемо карту відповідностей і перенесемо так, щоб трафік лишився на місці.




