Ошибка 404 Not Found: что значит, откуда берётся и как исправить
404 — единственный код HTTP, который знают даже далёкие от серверов люди. Разбираем, что он означает по спецификации, чем отличается от 410, 403 и редиректа, почему сервер отвечает 404 на страницу, которая лежит на диске, как найти массовые ошибки в логах и чем опасен «мягкий 404».
Ошибка 404 Not Found — ответ HTTP-сервера, означающий, что запрос дошёл до сервера и был понят, но по указанному адресу нет ресурса, который можно отдать. По RFC 9110 (§15.5.5) сервер «не нашёл текущего представления для целевого ресурса или не желает раскрывать, что оно существует». Это ошибка адреса, а не сервера: сайт работает, соединение в порядке, просто конкретного URL нет — или сервер не смог сопоставить его с файлом или маршрутом приложения.
Чем 404 отличается от 410, 403, редиректа и «мягкого 404»
404 — «здесь ничего нет, и я не знаю, надолго ли». 410 — «было, удалено навсегда». 403 — «есть, но вам нельзя». Редирект — «теперь там». Soft 404 — не код, а ситуация, когда текст «страница не найдена» приходит с кодом 200. Роботы реагируют на код, а не на надпись. Сводка по RFC 9110 и документации поисковиков на сентябрь 2026:
| Ответ | Смысл по RFC 9110 | Когда отдавать | Реакция Google и Яндекса |
|---|---|---|---|
| 404 Not Found | Ресурса нет; надолго ли — неизвестно. Кэшируется по умолчанию | Опечатка, страницы не было, удалена без решения о замене | Google: URL удаляется из индекса, обход редеет. Яндекс: удаление из базы в течение недели |
| 410 Gone | Удалено, и это, скорее всего, навсегда (§15.5.9). Не уверен — отдавай 404 | Осознанное удаление без преемника | Google: как 404. Яндекс: «если ресурс удалён навсегда, обеспечьте отдачу кода 410» |
| 403 Forbidden | Запрос понят, выполнять отказ; закрытое можно прятать за 404 (§15.5.4) | Закрытые каталоги, IP-фильтры | Оба: выпадает из индекса, как при 404 |
| 301 / 308 | Переехало навсегда | Есть новый адрес или преемник по смыслу | Google: сильный сигнал в пользу цели. Яндекс: рекомендует 301 с удалённых страниц |
| 302 / 307 | Временно по другому адресу | Техработы, A/B-тест | Google: слабый сигнал, старый URL остаётся основным |
| Soft 404 (200 + «не найдено») | Спецификацией не предусмотрен: сервер лжёт о статусе | Никогда | Google: метка в отчёте об индексировании, исключение из поиска. Яндекс: считает страницу существующей |
Все группы кодов — в статье «Коды ответа HTTP: 200, 301, 404, 500 и другие»; здесь остаёмся внутри 404.
Что делать пользователю, если сайт показывает 404
Чаще всего ошибка на стороне адреса: опечатка, устаревшая ссылка из закладок или выдачи, обрезанный при копировании URL. Проверьте адресную строку, уберите всё после «?» и поднимитесь на уровень выше — с /catalog/telefony/iphone-15-pro к /catalog/telefony/.
| Что видит пользователь | Где причина | Что делать |
|---|---|---|
| 404 на одной странице, остальное открывается | Опечатка, устаревшая ссылка, страница удалена | Проверить URL, поиск по сайту, родительский раздел |
| 404 по ссылке из поисковика или соцсети | Страницу перенесли или удалили без редиректа | Искать по названию на сайте; владельцу — сообщить |
| 404 на главной или на всём сайте | Сбой на сервере: vhost, деплой, конфиг | Не ваша ошибка: подождать или написать в поддержку |
| Только что была, теперь 404, у других открывается | Браузер или прокси закэшировал 404 (это разрешает RFC 9110) | Ctrl+F5, инкогнито, очистить кэш сайта |
Почему сервер отдаёт 404, хотя страница существует
Потому что 404 генерирует не «сайт», а конкретный слой: веб-сервер, не нашедший файл; приложение, не нашедшее маршрут; CDN, отдавший старый ответ из кэша. Первый шаг — понять по заголовкам curl -I, кто ответил.
$ curl -I https://example.com/catalog/item-42/ # пример вывода: 404 от nginx, приложение не участвовало HTTP/2 404 server: nginx/1.26.3 date: Thu, 24 Sep 2026 09:14:02 GMT content-type: text/html content-length: 153 # пример вывода: 404 сгенерировал WordPress — до PHP запрос дошёл HTTP/2 404 server: nginx content-type: text/html; charset=UTF-8 x-powered-by: PHP/8.3.12 link: <https://example.com/wp-json/>; rel="https://api.w.org/" cache-control: no-cache, must-revalidate, max-age=0
| Кто ответил | Признак в заголовках | Где искать причину |
|---|---|---|
| Веб-сервер (nginx, Apache) | Крошечный content-length, content-type без charset, нет заголовков движка | server_name, root/alias, try_files, .htaccess, регистр имён файлов |
| Приложение (WordPress, фреймворк) | x-powered-by, link на wp-json, set-cookie | Правила ЧПУ, статус записи, маршруты |
| CDN или кэширующий прокси | cf-cache-status: HIT, x-cache: Hit, ненулевой age | В кэше: на origin ошибка могла быть уже исправлена |
Для nginx главный инструмент — error.log: туда сервер пишет полный путь файла, который пытался открыть.
| Причина на сервере | Как выглядит | Как проверить | Исправление |
|---|---|---|---|
| nginx: try_files без маршрута приложения | try_files $uri $uri/ =404 на сайте с ЧПУ: файла /about нет, до index.php запрос не доходит | error.log: open() "/var/www/site/about" failed (2: No such file…) | Последним параметром — /index.php?$args или именованный location |
| nginx: root вместо alias | location /static/ { root /var/www/assets; } ищет /var/www/assets/static/…: URI добавляется целиком | Путь в error.log | alias /var/www/assets/; со слешами, как в location |
| Регистр букв | Разрабатывали на Windows или macOS, выложили на Linux: Logo.PNG и logo.png — разные файлы | ls -la в каталоге против пути в HTML | Имена в нижний регистр; Apache: mod_speling с CheckCaseOnly on как костыль |
| Apache: не работает .htaccess | AllowOverride None, нет mod_rewrite или файл потерян: все ЧПУ — 404, index.php открывается | apachectl -M | grep rewrite; ls -la .htaccess | a2enmod rewrite, AllowOverride All или FileInfo, восстановить файл |
| WordPress: устаревшие правила permalinks | После переноса или смены структуры ссылок: главная работает, записи — 404 | Ответ от PHP; запись в статусе «Опубликовано» | Настройки → Постоянные ссылки → Сохранить или wp rewrite flush --hard |
| Удалили страницу без редиректа | Товар снят или статья переехала, а меню, рассылки и выдача ведут на старый URL | Топ 404 в access.log с непустым referer | 301 на преемника; нет преемника — 404 или 410 |
| CDN закэшировал 404 | Файл выложили позже, чем сослались. Cloudflare по умолчанию держит 404 и 410 три минуты, 200 и 301 — 120 минут | cf-cache-status: HIT при 404; curl на IP origin даёт 200 | Очистить кэш по URL; деплоить файлы раньше ссылок на них |
| Не тот vhost | Домен без server_name попал в default_server с чужим root: 404 на всём сайте | curl -H "Host: site.ru" http://127.0.0.1/; nginx -T | grep server_name | Добавить server_name; nginx -t && nginx -s reload |
Правильная связка в nginx — try_files с маршрутом приложения последним параметром и страница ошибки через error_page. По документации nginx try_files $uri $uri/ @app эквивалентно error_page 404 = @app плюс log_not_found off.
# nginx: статика с диска, остальное — приложению, честная 404
server {
server_name example.com www.example.com;
root /var/www/example.com/public;
index index.php;
# тело ответа меняется, код остаётся 404
error_page 404 /404.html;
location = /404.html { internal; }
location / {
# нет файла и каталога — отдать index.php с аргументами
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
# несуществующий .php — сразу 404, а не «No input file»
try_files $uri =404;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
include fastcgi.conf;
}
# статика: не засорять error.log каждой пропавшей картинкой
location ~* \.(png|jpe?g|webp|css|js|woff2?)$ { log_not_found off; }
}
sudo nginx -t && sudo nginx -s reload
В Apache то же дают ErrorDocument и стандартный блок правил WordPress в .htaccess. ErrorDocument в .htaccess работает только при AllowOverride FileInfo; аргумент с «/» в начале — локальный URL с сохранением кода 404, а полный http://-адрес превращает ошибку в редирект.
# .htaccess: своя страница ошибки + стандартные правила WordPress
ErrorDocument 404 /errors/404.html
# BEGIN WordPress
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
# файл или каталог существует — отдать как есть
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# иначе — маршрутизация в WordPress
RewriteRule . /index.php [L]
# END WordPress
В WordPress 404 на записях при живой главной лечится пересозданием правил перезаписи: flush_rewrite_rules() «удаляет правила и создаёт их заново», её же вызывает сохранение настроек постоянных ссылок. Без админки то же делает WP-CLI.
# WordPress: пересоздать правила ЧПУ (и .htaccess при --hard)
$ wp rewrite flush --hard
Success: Rewrite rules flushed.
# Статус «пропавшей» записи
$ wp post list --name=item-42 --fields=ID,post_status,post_type
# пример вывода: запись есть, но в черновиках — отсюда и 404
| 517 | draft | product |
# Код ответа одной строкой
$ curl -s -o /dev/null -w '%{http_code}\n' https://example.com/item-42/
404
Как найти массовые 404 в логах сервера
Access.log — самый честный источник: в нём 404, которые запрашивают люди и роботы прямо сейчас. В комбинированном формате nginx и Apache статус — девятое поле, путь — седьмое, referer — одиннадцатое; этого хватает, чтобы одной командой получить топ проблемных адресов.
# Топ-20 адресов с 404
awk '$9 == 404 {print $7}' /var/log/nginx/access.log \
| sort | uniq -c | sort -rn | head -20
# пример вывода
1842 /wp-content/uploads/2026/08/banner-hero.webp
613 /catalog/telefony/iphone-14/
207 /favicon.ico
41 /old-blog/post-123.html
# Те же 404 с источником ссылки: что чинить у себя,
# а что просить исправить у партнёров
awk '$9 == 404 && $11 != "\"-\"" {print $7, $11}' \
/var/log/nginx/access.log | sort | uniq -c | sort -rn | head
Первая строка примера — типичная картина после деплоя: один пропавший файл, на который ссылается каждая страница, даёт тысячи 404 в час. Вторая — удалённая карточка, на которую ещё ведут ссылки. Со стороны роботов: в Яндекс Вебмастере рост 4xx — алерт «Некоторые страницы сайта отвечают HTTP-кодом 4xx» в «Диагностике», в Google Search Console — строка «Не найдено (404)» в отчёте об индексировании.
Что такое soft 404 и почему он хуже настоящей ошибки
Soft 404 («мягкий 404») — страница, которая говорит посетителю «ничего не найдено», а роботу отдаёт код 200. Google относит сюда же пустые страницы. Яндекс в списке распространённых ошибок называет это заменой сообщения 404 на заглушку с кодом 200: поисковик считает адрес существующим, не удаляет его из базы, и это замедляет индексирование полезных страниц. Причины по документации Google: пропавший серверный include, оборванное соединение с базой, пустая страница внутреннего поиска, незагрузившийся JavaScript. На практике чаще виноваты две конфигурации:
# ПЛОХО: nginx подменяет код — любой несуществующий адрес станет 200
error_page 404 =200 /404.html;
# ПЛОХО: SPA-fallback без ограничений — index.html с кодом 200 на всё,
# роутер в браузере рисует «Не найдено», робот видит успех
location / { try_files $uri /index.html; }
# Проверка любого сайта: код, а не надпись
$ curl -s -o /dev/null -w '%{http_code}\n' https://example.com/qwerty-12345
200
# 200 на заведомо несуществующий адрес = soft 404
Лечение: в nginx убрать «=200»; в SPA отдавать 404 при серверном рендеринге или хотя бы meta robots noindex в состоянии «не найдено». Есть и обратный случай: Google помечает живую страницу как soft 404, если при рендеринге она осталась пустой из-за заблокированных в robots.txt скриптов или тяжёлых ресурсов, — это видно в инструменте проверки URL.
Как правильно оформить страницу 404
Требование одно: страница может выглядеть как угодно, но статус обязан быть настоящим 404. Остальное — чтобы посетитель не ушёл: объяснение, навигация, поиск, ссылки на популярные разделы. Google напоминает: страница ошибки создаётся для людей, а от индексации её защищает именно код.
| Пункт чек-листа | Почему | Как проверить |
|---|---|---|
| Настоящий код 404 (или 410) | Иначе это soft 404 | curl -I на несуществующий URL |
| Без редиректа на главную | Потеря контекста для человека, soft 404 для робота | В ответе нет заголовка location |
| Тот же адрес в строке браузера | Пользователь видит опечатку и может её поправить | error_page с локальным URI, не с http:// |
| Шапка, меню, поиск по сайту | Выход вместо кнопки «назад»; Google советует общий вид сайта | Открыть глазами, кликнуть по меню |
| Лёгкая и автономная | Отдаётся тысячи раз в час; не должна ходить в базу | Статический HTML в десятки килобайт |
| Не индексируется сама | Прямой запрос /404.html не должен давать 200 | В nginx — internal; из меню на неё не ссылаться |
| Попадает в лог и аналитику | Иначе не узнать, какие адреса ищут посетители | access_log включён; в аналитике — сегмент по title «404» |
RFC 9110 разрешает кэшировать 404 без явных заголовков, и CDN этим пользуются. После исправления очищайте кэш по конкретному URL, иначе часть посетителей ещё несколько минут будет видеть старый ответ.
Как ошибка 404 влияет на позиции в поиске
Сам код — не штраф: по документации Google это нормальный ответ для страницы, удалённой без замены, а Яндекс предлагает игнорировать 404 на адресах, которых на сайте никогда не было. Вредят следствия: потеря страниц с трафиком (Google удаляет URL с 404 из индекса, Яндекс — в течение недели), внутренние ссылки в пустоту и soft 404, из-за которого в индексе копятся пустые адреса.
Самый дорогой сценарий — массовые 404 после смены структуры адресов: сотни страниц выпадают разом. У каждой удаляемой страницы с трафиком или внешними ссылками должен быть 301 на преемника; какой код редиректа выбрать — в статье про 301, 302, 307 и 308. Как системно найти битые ссылки и что делать с каждым типом — в статье «Битые ссылки и 404».
Как узнать о 404 на важной странице раньше посетителей
Самые дорогие 404 случаются не на забытых адресах, а на главной, в каталоге и на посадочных рекламы — после деплоя, обновления CMS или правки конфига. Логи и панели покажут это постфактум; нужна проверка, которая запрашивает ключевые URL по расписанию и сравнивает код с ожидаемым.
В Пруфене это два типа проверок. HTTP-проверка запрашивает страницу с интервалом от 2 минут из 20 точек мониторинга в России, Беларуси, Казахстане и Испании и считает успехом только коды 2xx или разрешённые вами: как только страница после релиза начала отдавать 404, открывается инцидент. Проверка наличия контента ловит soft 404: она ищет в HTML заданный текст, например артикул или заголовок раздела, а в инвертированном режиме контролирует отсутствие фразы «ничего не найдено» на странице с кодом 200. Время обнаружения равно интервалу проверки.
Пруфен присылает уведомление в Email, Telegram или Макс, когда проверка перестала проходить, и второе — когда страница снова отвечает 200. Если ресурс так и не поднялся, подключается голосовой звонок. Бесплатный план включает 5 проверок: хватит на главную, ключевые категории и контроль soft 404.
Частые вопросы
Влияет ли ошибка 404 на позиции сайта?
Не напрямую: Google и Яндекс называют 404 нормальным ответом для несуществующего адреса, штрафа за него нет. Позиции теряются, когда 404 начинает отдавать страница, которая ранжировалась: её удаляют из индекса вместе с накопленными сигналами. Опасен не код, а 404 на нужных страницах.
Что лучше отдавать при удалении — 404 или 410?
По RFC 9110 410 — для удалённого навсегда; если сервер не уверен в постоянстве, положен 404. Google обрабатывает оба кода одинаково, Яндекс прямо рекомендует 410 для окончательно удалённого контента. Осознанно удалили без замены — 410; может вернуться — 404; есть преемник — 301.
Почему страница есть на сервере, а он отдаёт 404?
Потому что «есть на диске» и «доступна по этому URL» — разные вещи. Между ними стоят server_name, root или alias, try_files, регистр букв в имени файла, правила перезаписи движка и кэш CDN. Начните с curl -I: по заголовкам видно, кто ответил, — затем смотрите error.log, куда nginx пишет полный путь, который пытался открыть.
Нужно ли перенаправлять все 404 на главную?
Нет. Для посетителя это потеря контекста: искал конкретную страницу, попал на витрину. Для поисковика — soft 404: сотни адресов «ведут» на главную, и робот не получает сигнала, что их больше нет. Редирект уместен только точечный — на преемника удалённой страницы. Остальное должно отдавать честный 404 с полезной страницей ошибки.