Перейти к содержимому
SEO/Опубликовано 18 октября 2026 г./5 мин

Ошибка 304: страница не изменилась

Код 304 Not Modified — не ошибка, а ответ «копия у вас свежая». Проверили на стенде nginx, Apache, PHP и Chromium, когда 304 показывает старую страницу, и отправили условные запросы на 2056 живых сайтов.

Ошибка 304: страница не изменилась
N
Команда NEXFORCE
Кто пишет блог

Код 304 Not Modified значит, что страница не изменилась с прошлого запроса и браузер может показать копию из своего кэша. Это не ошибка, а экономия: сервер не передаёт страницу заново, ответ состоит из одних заголовков. Ошибкой 304 называют, когда этот механизм работает неправильно — посетитель видит старую версию сайта или сервер вовсе не умеет так отвечать.

Мы проверили на стенде, как 304 отдают nginx 1.22, Apache 2.4.68 и PHP 8.3 и как его обрабатывает Chromium 149, а затем отправили условные запросы на главные страницы 2056 сайтов, чтобы узнать, сколько из них отвечают 304 на самом деле.

Что значит код 304 Not Modified

Стандарт HTTP (RFC 9110, раздел 15.4.5) определяет код так:

The 304 (Not Modified) status code indicates that a conditional GET or HEAD request has been received and would have resulted in a 200 (OK) response if it were not for the fact that the condition evaluated to false.

Иначе говоря, 304 представляет собой статус ответа на условный запрос протокола HTTP. Обычный запрос «дай страницу» всегда получает 200 с содержимым. Условный говорит «дай страницу, если она изменилась», и если не изменилась — сервер отвечает 304. Тела в таком ответе быть не может: «A 304 response is terminated by the end of the header section; it cannot contain content or trailers».

Код входит в группу 3xx — перенаправления: сервер как бы перенаправляет клиента к его же сохранённой копии. От кодов 301 и 302 он отличается тем, что нового адреса не передаёт.

Где код 304 среди кодов состояния HTTP

Код состояния — трёхзначное число в первой строке ответа сервера. Первая цифра указывает класс ответа, и по ней уже понятно, что произошло:

  • 1xx — информационные. Сервер получил часть запроса и продолжает обработку. Например, 100 Continue клиент ждёт перед отправкой больших вложений.
  • 2xx — успешные. Запрос выполнен: 200 OK — страница получена, 201 — ресурс создан, 204 — ответ без данных.
  • 3xx — перенаправление. Клиенту нужно сделать ещё одно действие: 301 — адрес перемещён навсегда, 302 — временно, 304 — ресурс не изменён, используйте сохранённую копию.
  • 4xx — ошибки клиента. 400 — неверный синтаксис запроса, 401 — клиент не авторизован и должен указать логин и пароль, 403 — доступ запрещён, 429 — слишком много запросов.
  • 5xx — ошибки сервера. 500 — внутренняя ошибка, 502 — прокси получил неверный ответ, 503 — перегрузка или обслуживание, 504 — истекло время ожидания.

Код 304 стоит в классе 3xx, хотя никуда не перенаправляет. Он не сообщает о неполадках и не требует от пользователя никаких действий. Такое состояние означает нормальную работу кэша: запрос завершён успешно, просто ответ без тела.

Как работает механизм кэширования и условные запросы

При первом визите сервер отдаёт страницу с кодом 200 и одним или двумя заголовками-метками:

  • ETag — идентификатор версии файла, например "6ad43807-4e";
  • Last-Modified — время последнего изменения.

Браузер сохраняет страницу вместе с метками. При повторном запросе он отправляет их обратно в заголовках If-None-Match (с ETag) и If-Modified-Since (с датой). Сервер сравнивает: метка совпала — ответ 304, не совпала — 200 с новой версией.

По шагам процесс выглядит так:

  1. При первой загрузке браузер получает полный ответ 200 и сохраняет его в кэше вместе с ETag и Last-Modified.
  2. При следующих посещениях он отправляет условный запрос с этими значениями.
  3. Сервер сравнивает их с текущей версией файла на своей стороне.
  4. Если в запрашиваемом ресурсе ничего не менялось, возвращается 304 без тела, и браузер показывает загруженную ранее копию.
  5. Если файл изменился, сервер отдаёт 200 с новой версией и новыми метками, и цикл начинается заново.

Так браузер получает обновление, когда оно есть, и не скачивает страницу, когда его нет. Это существенно снижает количество передаваемых данных: на нашем сайте ответ по условному запросу в десятки тысяч раз меньше полного.

Если пришли оба заголовка, главнее ETag. Стандарт (раздел 13.1.3) прямо требует игнорировать If-Modified-Since при наличии If-None-Match. На стенде nginx так и сделал: чужой ETag при верной дате дал 200, а не 304.

Стенд: как 304 отдают nginx, Apache и PHP

Сервер и случайМетки в ответеУсловный запрос
nginx 1.22, статический файлETag и Last-Modified304, 0 байт тела
nginx, сжатие gzipслабый ETag W/"…"304
nginx, дата в If-Modified-Since не совпадает—200 (по умолчанию нужна точная дата)
Apache 2.4.68, статический файлETag и Last-Modified304
Apache, сжатие mod_deflateETag с суффиксом -gzip200 — 304 не приходит
PHP 8.3, обычный скриптникаких меток304 не бывает
PHP с session_start()Cache-Control: no-store, Expires 1981 года304 не бывает
PHP со своим ETagETag из кода304

Отсюда три вывода. Статические файлы оба сервера отдают с 304 сами. Страницы на PHP — а это большинство сайтов на CMS — по умолчанию его не получают: скрипт не сообщает ни ETag, ни Last-Modified, и сервер не знает, с чем сравнивать. А у Apache со сжатием есть грабля: ETag в ответе меняется на "…-gzip", и с таким значением в If-None-Match сервер отвечает 200, хотя файл не менялся.

Как Chromium обрабатывает 304

Обычная перезагрузка (F5). Chromium отправил If-None-Match, If-Modified-Since и Cache-Control: max-age=0. Сервер ответил 304, браузер показал копию из кэша. Сама страница при этом видит код 200: браузер подставляет сохранённый ответ, и 304 заметен только в журнале сервера.

Жёсткая перезагрузка (Ctrl+Shift+R). Условных заголовков нет, только Cache-Control: no-cache. Сервер всегда отдаёт 200 и свежую версию.

Переход по ссылке. Страница без Cache-Control, но с Last-Modified десятидневной давности: при повторном переходе по ссылке Chromium вообще не обратился к серверу и взял копию с диска. Браузер сам считает её свежей по возрасту файла — это эвристическое кэширование.

304 без кэша. Если сервер ответил 304 на запрос, где условий не было, Chromium прервал переход с ошибкой ERR_ABORTED. Новая вкладка осталась пустой страницей about:blank — посетитель видит белый экран.

Зачем 304 владельцу сайта

Для владельцев сайтов и предпринимателей 304 — бесплатный способ ускорить сайт без переделки. Он позволяет не передавать повторно то, что у посетителя уже есть: HTML-страницы, картинки, стили и скрипты. Чем больше постоянных посетителей и роботов, тем заметнее экономия.

Что даёт правильная настройка:

  • производительность — повторная загрузка идёт быстрее, ведь по сети передаются только заголовки;
  • нагрузка — сервер не отправляет одни и те же данные, а на тарифах с оплатой трафика это ещё и счёт меньше;
  • сканирование — поисковые роботы периодически обходят сайт и с 304 быстрее находят новые и изменённые страницы;
  • актуальность — при правильных метках посетитель получает новую версию сразу после правки, а не через неделю.

Понимание этого механизма полезно и для оптимизации: 304 могут получать не только браузеры, но и мобильные приложения, и роботы.

Однако 304 не гарантия скорости. Если первая загрузка медленная, а большинство посетителей приходят впервые, выигрыш будет небольшим. Основная польза — для постоянной аудитории и для поисковых систем, которые возвращаются к сайту часто.

Когда 304 становится проблемой

Посетители видят старую версию

На стенде мы изменили файл, но сохранили его размер и время изменения. nginx строит ETag из этих двух величин, поэтому метка осталась прежней. По F5 сервер ответил 304, и Chromium показал старый текст. Помогла только жёсткая перезагрузка. Так бывает после выкладки, если программа копирования сохраняет даты файлов, а правка не изменила их размер.

Сервер никогда не отвечает 304

Вторая ситуация обратная: сервер не принимает условные запросы.

Тогда браузеры и роботы каждый раз скачивают страницу целиком. Ошибки посетитель не видит, но сайт тратит больше трафика и времени. Типичные причины по нашим замерам включают: PHP-страница без меток, ETag, который меняется при каждом запросе, и суффикс -gzip у Apache.

Ошибка 304 у пользователя

Сообщение «ошибка 304» браузер сам не показывает: код скрыт от пользователя, а страница открывается из кэша. Признаки неполадок другие — устаревший контент после обновления сайта или белый экран. Если вместо страницы белый экран, а в журнале 304, значит, сервер отвечает 304 без повода. Посетителю стоит обновить страницу через Ctrl+Shift+R или очистить кэш браузера для этого сайта — удалять всю историю и ставить дополнительные программы нет необходимости. Помогает и режим инкогнито: в этом режиме браузер начинает с пустым кэшем. Если проблема возникает у всех посетителей, а не у одного, исправлять её нужно на стороне сервера, а не на компьютере. Проверять компьютер на вирусы и переустанавливать драйверы, как советуют некоторые статьи, бесполезно: код отдаёт сервер, а не Windows.

Обход: сколько сайтов отвечают 304

Мы запросили главные страницы 2056 сайтов из Германии, взяли из ответа ETag и Last-Modified и повторили запрос с ними. Кодом 200 ответили 1469 сайтов.

Что нашлиСайтов из 1469
Есть ETag393
Есть Last-Modified585
Нет ни ETag, ни Last-Modified861
Ответили 304 хотя бы на один условный запрос490

Больше половины сайтов не сообщают меток вовсе, и 304 у них не может быть в принципе. Среди тех, кто ETag отдаёт, 304 по нему вернули 194 из 393. У 184 ETag изменился между двумя запросами подряд — 164 из них стоят за DDoS-Guard. Ещё у 14 метка была той же, а ответ всё равно 200; у 11 из них ETag с суффиксом -gzip, как у Apache на нашем стенде.

По Last-Modified 304 вернули 471 из 585. У 62 сайтов дата менялась при каждом запросе: сервер ставит текущее время, и проверка «изменилась ли страница» всегда отвечает «да».

Наш сайт отвечает 304 по обоим заголовкам: страница статьи по условному запросу весит 0 байт тела вместо 57 595.

Влияние кода 304 на SEO

Google в документации о своих краулерах пишет:

Google's crawling infrastructure supports heuristic HTTP caching as defined by the HTTP caching standard, specifically through the ETag response- and If-None-Match request header, and the Last-Modified response- and If-Modified-Since request header.

Если есть оба заголовка, Google берёт ETag и рекомендует именно его, «as ETag doesn't have date formatting issues». Googlebot использует кэш при повторном обходе страниц для поиска.

В справочнике кодов Яндекс Вебмастера про 304 сказано: «Если страница не изменилась с момента последнего обращения робота, рекомендуется выдавать этот код». Яндекс советует его для изображений, CSS и JavaScript и добавляет: «Это ускорит индексирование и уменьшит трафик».

Правильный 304 не поднимет позиции, но робот тратит меньше времени на неизменные страницы и быстрее доходит до новых — это важно для больших сайтов с ограниченным краулинговым бюджетом. Неправильный 304 опаснее: робот сочтёт изменённую страницу прежней. Дата изменения пригодится и в lastmod карты сайта.

Как устранить проблему 304

  1. Проверьте ответ. Запросите страницу, возьмите ETag и повторите: curl -sI -H 'If-None-Match: "6ad43807-4e"' https://сайт/. 304 — всё правильно.
  2. Apache со сжатием. Добавьте в конфигурацию DeflateAlterETag NoChange или Remove. На стенде оба варианта вернули 304 со сжатым ответом.
  3. nginx. Директивы etag on и if_modified_since exact включены по умолчанию. Значение before разрешает 304, если дата файла не позже присланной.
  4. PHP и CMS. Скрипт должен сам отдать ETag или Last-Modified и сравнить их с заголовками запроса. На стенде хватило нескольких строк кода; для WordPress и других CMS есть плагины кэширования.
  5. Старая страница после выкладки. Это решение для ситуаций, когда новая версия находится на сервере, а посетителям отображаются старые страницы. Убедитесь, что выкладка меняет время файлов, или задайте Cache-Control: no-cache для HTML — тогда браузер будет спрашивать сервер каждый раз.
  6. За защитой и CDN. Если ETag меняется на каждый запрос, проверьте настройки кэша у провайдера защиты. Такие системы часто применяют свои параметры кэширования поверх настроек сервера.
  7. После исправления повторите проверку из пункта 1 и посмотрите журнал сервера: при повторных посещениях в нём должны появиться ответы 304. Это самый простой инструмент проверить результат.

Источники

  • RFC 9110, разделы 15.4.5, 13.1.3, 13.2.2 — rfc-editor.org
  • Google: обзор краулеров, раздел HTTP Caching — developers.google.com
  • Яндекс Вебмастер: справочник HTTP-кодов — yandex.ru/support/webmaster
  • nginx: директивы etag и if_modified_since — nginx.org/ru/docs

Похожие ошибки

Границы замера

Стенд — nginx 1.22.1, Apache 2.4.68 и PHP 8.3 в Docker, Chromium 149. Обход 18.10.2026 из Германии, по одному обычному и одному-двум условным запросам на главную страницу; внутренние страницы и картинки мы не проверяли. Почему у сайтов за DDoS-Guard ETag меняется, мы не выясняли.

Коротко

Код 304 — не ошибка, а ответ «страница не изменилась, берите копию». Работает он через ETag и Last-Modified. Статику nginx и Apache отдают с 304 сами, PHP-страницы — нет. Проблемы две: 304 при изменённой странице показывает старую версию, а отсутствие 304 заставляет каждый раз скачивать всё целиком. Первое лечится жёсткой перезагрузкой у посетителя и правкой выкладки у владельца, второе — настройкой сервера.

Вопросы и ответы

FAQ по теме

Что означает код 304?+
«304 Not Modified» — «не изменено». Браузер или робот спросил сервер, изменилась ли страница с прошлого раза, и сервер ответил: нет, берите сохранённую копию. Тела в таком ответе нет, поэтому он почти ничего не весит.
Ошибка 304 — это плохо?+
Нет. Это нормальная работа кэша, а не сбой. Проблема бывает в двух случаях: сервер отвечает 304, хотя страница изменилась, и посетитель видит старую версию, или сервер вообще не умеет отвечать 304 и каждый раз отдаёт страницу целиком.
Почему после правки сайта видна старая страница?+
Если сервер решает «не изменилась» по дате и размеру файла, а после выкладки дата и размер остались прежними, он ответит 304, и браузер покажет сохранённую копию. На стенде это вылечила жёсткая перезагрузка Ctrl+Shift+R: браузер запросил страницу без условий.
Как проверить, отдаёт ли сайт 304?+
Запросите страницу, возьмите из ответа ETag или Last-Modified и повторите запрос с заголовком If-None-Match или If-Modified-Since. Если в ответ пришёл 304 без тела — сервер работает правильно. Если снова 200 с полной страницей — условные запросы не поддерживаются.
Влияет ли код 304 на SEO?+
Косвенно. Google пишет, что Googlebot поддерживает кэширование при повторном обходе через ETag и Last-Modified, а Яндекс рекомендует отдавать 304, если страница не менялась с прошлого визита робота: это ускоряет индексирование и уменьшает трафик.
Читайте также

Связанные материалы

SEO

ERR_CACHE_MISS: «Подтвердите повторную отправку формы»

ERR_CACHE_MISS Chrome показывает, когда вы возвращаетесь кнопкой «Назад» на страницу после отправки формы, а сайт запретил её сохранять. Проверили на стенде, какие заголовки дают ошибку, и посчитали, у скольких сайтов она возможна.

SEO

lastmod в карте сайта: как он врёт и как мы это чинили

Дата изменения в sitemap.xml обычно равна дате сборки — тогда карта сообщает «изменилось всё». Мы взяли даты из истории git и проверили результат: 31 статья из 66 всё равно показывает не ту дату. Разбор с замером.

SEO

301 или 302: как выбрать и что бывает при ошибке

Прошли цепочки редиректов у 264 доменов Екатеринбурга. По http отвечает 211, из них 182 отдают 301, четыре — 302, а 23 не переадресуют вовсе. Чем постоянный редирект отличается от временного и что ломает лишний хоп.

SEO

С какой скоростью сайт отдаёт данные и как это померить

Время ответа сервера — не то же самое, что скорость сайта. Замер по выборке из 75 сайтов: медиана 159 мс, а рукопожатие TLS стоит дороже самого ответа.