Как Last-Modified и 304 экономят краулинговый бюджет

Каждый день поисковые роботы сканируют миллионы страниц. Когда сайт возвращает полный HTML на каждый запрос — даже если содержимое не изменилось — краулинговый бюджет расходуется впустую. Робот тратит время и ресурсы на загрузку уже известных данных, а новые или обновлённые страницы получают меньше внимания. Проблема решается корректной обработкой условных запросов через заголовки Last-Modified и If-Modified-Since.

Как работают Last-Modified и 304 Not Modified

Заголовок Last-Modified в ответе сервера указывает точную дату и время последнего изменения ресурса. Когда робот (или браузер) запрашивает страницу повторно, он отправляет заголовок If-Modified-Since с этой датой. Сервер сравнивает дату с фактической датой изменения файла. Если контент не менялся, сервер отвечает статусом 304 Not Modified и пустым телом ответа. Если контент обновлён — возвращается 200 OK с полным HTML.

Этот механизм — один из базовых протоколов HTTP. Его поддержка включена по умолчанию в большинстве веб-серверов (Apache, Nginx), но на практике настройки часто сбиваются при использовании CMS, кеширующих плагинов или CDN.

Почему это важно для SEO

Экономия краулингового бюджета

Поисковые системы выделяют каждому сайту определённый лимит на сканирование — краулинговый бюджет. Для крупных интернет-магазинов (10 000+ страниц) или новостных порталов бюджет критичен. Если робот тратит 80% запросов на страницы, которые не менялись неделями, новые товары или статьи индексируются медленно. Корректный 304 позволяет роботу пропустить неизменённые URL за 20–50 миллисекунд вместо 200–500 мс на полную загрузку. Освободившийся бюджет уходит на действительно важные страницы.

Скорость повторного сканирования

Даже если краулинговый бюджет не лимитирован (на маленьких сайтах), скорость реиндексации падает при высокой нагрузке на сервер. Если каждый повторный визит робота вызывает генерацию страницы через CMS, база данных и PHP, время ответа растёт. 304 Not Modified снимает эту нагрузку: сервер отдаёт только заголовки без обращения к базе данных. Робот быстрее покидает сайт и быстрее возвращается к нему в следующий раз.

Снижение нагрузки на сервер

Это косвенно влияет на SEO через скорость загрузки для реальных пользователей. Если сервер тратит ресурсы на обработку запросов роботов, время ответа для посетителей увеличивается. Особенно заметно на shared-хостинге или при высоком трафике.

Как проверить настройку Last-Modified на своём сайте

Проверка состоит из двух этапов: убедиться, что сервер отдаёт Last-Modified, и проверить, что на повторный запрос приходит 304.

Этап 1. Проверка заголовка Last-Modified

Откройте любую страницу сайта в браузере. Нажмите F12 → вкладка Network → перезагрузите страницу. Найдите запрос документа (обычно первый в списке), кликните на него и посмотрите заголовки ответа. Ищите строку Last-Modified: день, дата время GMT. Если заголовок отсутствует — сервер не сообщает дату изменения, и условные запросы работать не будут.

Этап 2. Проверка ответа 304 Not Modified

Самый надёжный способ — отправить запрос с заголовком If-Modified-Since вручную. Можно использовать curl:

curl -I -H "If-Modified-Since: Thu, 01 Jan 2024 00:00:00 GMT" https://ваш-сайт.ру/страница

Если страница не менялась после указанной даты, сервер должен вернуть HTTP/1.1 304 Not Modified и пустое тело. Если возвращается 200 OK — механизм не настроен.

Чтобы автоматизировать проверку для всего сайта, воспользуйтесь нашим бесплатным инструментом «Last-Modified / If-Modified-Since» oWeb Solutions. Он последовательно проверяет заголовок Last-Modified для списка URL и эмулирует повторный запрос с If-Modified-Since, показывая, какой статус возвращает сервер. Инструмент сразу подсвечивает проблемы: отсутствие заголовка, неверный формат даты или игнорирование условного запроса.

Как исправить проблемы с Last-Modified и 304

Случай 1: Last-Modified отсутствует

Если ваш сайт на статическом HTML — добавьте директиву в конфигурацию веб-сервера. Для Apache в .htaccess:

<IfModule mod_headers.c>
Header set Last-Modified "%{time:%a, %d %b %Y %H:%M:%S GMT}"
</IfModule>

Для Nginx:

location / {
if_modified_since before;
add_header Last-Modified $date_gmt;
}

Важно: эти директивы работают только для статичных файлов. Для динамических страниц (PHP, CMS) дату последнего изменения нужно передавать из кода.

Случай 2: CMS не отдаёт Last-Modified

WordPress, 1С-Битрикс, Joomla и другие популярные CMS могут не отправлять заголовок по умолчанию. Решения:

WordPress: установите плагин кеширования (WP Rocket, W3 Total Cache) — они добавляют Last-Modified при генерации статического кеша.

1С-Битрикс: в настройках компонента включите «Управляемый кеш» или добавьте в header.php код: Header("Last-Modified: ".gmdate("D, d M Y H:i:s", time())." GMT"); — но это не учитывает реальные изменения контента. Лучше использовать API для получения даты последнего обновления элемента инфоблока.

Самописная CMS: на странице детального просмотра записи вызовите header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModifiedTimestamp) . ' GMT'); перед любым выводом.

Случай 3: 304 не возвращается, хотя Last-Modified есть

Самая частая причина — кеширующий плагин или CDN не передаёт условный запрос на origin-сервер. Проверьте настройки:

Cloudflare: включите «Cache Level: Standard» и убедитесь, что не стоит правило, принудительно возвращающее 200.

Nginx + FastCGI cache: добавьте в конфигурацию: fastcgi_hide_header Last-Modified; не нужно, наоборот — убедитесь, что заголовок не удаляется.

Apache mod_expires: не блокирует Last-Modified, но если стоит Header unset Last-Modified — удалите.

Другая причина — динамическая генерация страницы с уникальным контентом при каждом запросе (например, случайные отзывы, счётчики, время сессии). В таких случаях сервер не может определить единую дату изменения, и условные запросы неэффективны. Решение — кешировать страницу целиком или исключить из индексации динамические параметры.

Практические рекомендации

Не используйте Last-Modified на динамических страницах без кеша. Если страница генерируется «на лету» с уникальным содержанием, заголовок будет меняться каждый раз, и 304 никогда не сработает. Кеширование обязательно.

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

Учитывайте часовые пояса. Last-Modified всегда должен быть в формате GMT. Неправильная временная зона приведёт к тому, что робот будет получать 200 вместо 304.

Мониторьте логи сервера. Если количество 304 ответов резко упало — что-то сломалось после обновления CMS или плагина.

Частые ошибки

Ошибка: Last-Modified совпадает с временем запроса. Если сервер отдаёт текущее время вместо времени последнего изменения файла, условный запрос всегда будет возвращать 304, даже если контент изменился. Это приведёт к тому, что робот не увидит обновления. Решение: проверьте, откуда берётся дата — из файла на диске или из базы данных.

Ошибка: 304 возвращается без проверки If-Modified-Since. Некоторые плагины кеширования принудительно отдают 304 на любые повторные запросы одного и того же URL в течение заданного времени. Это ломает реиндексацию: робот считает страницу неизменной, хотя она могла обновиться. Решение: убедитесь, что 304 возвращается только при совпадении дат, а не по таймеру.

Заключение

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