Як вирішити помилку 429 Too Many Requests
Помилка 429 Too Many Requests — це HTTP-код стану, визначений у RFC 6585, який сигналізує про те, що клієнт перевищив ліміт запитів, встановлений сервером або проміжним проксі. Сервер відхиляє подальші запити до скидання вікна обмеження швидкості, за бажанням повертаючи заголовок Retry-After, що вказує, скільки часу клієнт повинен зачекати.
На відміну від помилки 503 Service Unavailable, яка відображає збій пропускної здатності на стороні сервера, 429 — це навмисне відхилення, засноване на правилах. Розуміння цієї відмінності є критично важливим: виправлення не завжди полягає у масштабуванні інфраструктури — йдеться про визначення того, *хто* надсилає забагато запитів, *чому*, а потім про виправлення поведінки на відповідному рівні стека.
Що насправді спричиняє помилку 429
Помилка виникає на кількох рівнях, і їх змішування призводить до неправильної діагностики. Першопричина належить до однієї з чотирьох категорій:
- Обмеження швидкості на стороні сервера — веб-сервери (Apache, Nginx), зворотні проксі (HAProxy, Varnish) або вузли CDN (Cloudflare, Fastly) застосовують порогові значення запитів на IP або на токен.
- Обмеження на рівні застосунку — плагіни WordPress, власне проміжне програмне забезпечення або API-шлюзи встановлюють власні ліміти незалежно від веб-сервера.
- Вичерпання квоти стороннього API — ваш застосунок звертається до зовнішнього API (Google Maps, Stripe, OpenAI) швидше, ніж дозволяє квота провайдера, і помилка 429 передається кінцевому користувачу.
- Зловмисний або неконтрольований автоматизований трафік — спроби брутфорс-входу, агресивні скрейпери, неправильно налаштовані скрипти моніторингу або погано написані краулери вичерпують бюджети запитів.
Часто пропущений граничний випадок: середовища спільного хостингу, де сплеск трафіку сусіднього орендаря споживає спільні пули з’єднань, через що ваш застосунок отримує відповіді 429 від upstream-балансувальника навантаження, навіть якщо ваш власний код поводиться коректно. Якщо ви використовуєте план Shared Web Hosting і бачите переривчасті сплески 429 без відповідного зростання власного трафіку, це перша гіпотеза для перевірки.
Крок 1: Визначте джерело надмірних запитів
Виправлення помилки 429 без визначення її походження — це вгадування. Починайте з даних.
Читання журналів доступу Apache
grep " 429 " /var/log/apache2/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20Ця команда витягує кожну відповідь 429, підраховує кількість випадків на IP-адресу та ранжує їх. IP-адреса, що з’являється тисячі разів за хвилини, є або ботом, або неправильно налаштованим скриптом, або зловмисником.
Читання журналів доступу Nginx
awk '$9 == 429 {print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20Кореляція з шляхами запитів
grep " 429 " /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20Якщо /wp-login.php або /xmlrpc.php домінує у виводі, ви маєте справу з кампанією брутфорсу або підбору облікових даних. Якщо на першому місці знаходиться кінцева точка API на кшталт /api/v1/search, винуватцем, швидше за все, є неправильно налаштований клієнт або скрейпер.
Використання fail2ban для виявлення патернів
fail2ban-client status
fail2ban-client status nginx-req-limitЯкщо fail2ban налаштовано з пасткою nginx-req-limit, він покаже вам саме ті IP-адреси, які були заблоковані через порушення ліміту швидкості, що значно заощадить час на аналіз журналів.
Крок 2: Налаштуйте обмеження швидкості на рівні веб-сервера
Apache: використання mod_ratelimit та mod_evasive
Фрагмент .htaccess, що широко поширений в інтернеті, використовує mod_rewrite для повернення 403, а не коректного 429. Більш семантично правильний і операційно надійний підхід використовує mod_evasive для пом’якшення DoS-атак.
Встановіть і налаштуйте mod_evasive на Debian/Ubuntu:
apt install libapache2-mod-evasive
a2enmod evasiveПотім додайте до віртуального хосту Apache або глобальної конфігурації:
<IfModule mod_evasive20.c>
DOSHashTableSize 3097
DOSPageCount 5
DOSSiteCount 50
DOSPageInterval 1
DOSSiteInterval 1
DOSBlockingPeriod 10
DOSEmailNotify admin@yourdomain.com
DOSLogDir /var/log/mod_evasive
</IfModule>Це блокує будь-який IP, який звертається до однієї сторінки більше 5 разів на секунду або до всього сайту більше 50 разів на секунду, на 10-секундний період охолодження.
Для коректної відповіді 429 через .htaccess на Apache з mod_rewrite вам потрібен власний документ помилки:
ErrorDocument 429 "Too Many Requests"
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} ^.*(SemrushBot|AhrefsBot|MJ12bot|DotBot).*$ [NC]
RewriteRule .* - [R=429,L]
</IfModule>Nginx: limit_req_zone з правильною обробкою сплесків
Модуль ngx_http_limit_req_module Nginx є одним із найефективніших доступних інструментів обмеження швидкості. Ключові параметри, які часто налаштовуються неправильно, — це burst та nodelay.
У /etc/nginx/nginx.conf або виділеному файлі включення:
http {
# Zone keyed by client IP, 10MB shared memory, 10 requests/second baseline
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/s;
# Return 429 instead of the default 503
limit_req_status 429;
server {
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
}
location /wp-login.php {
limit_req zone=login_limit burst=3 nodelay;
}
}
}Критичний нюанс: без limit_req_status 429 Nginx за замовчуванням повертає 503 для запитів з обмеженою швидкістю. Встановлення значення 429 є семантично правильним і дозволяє клієнтам реалізувати коректну логіку відкату Retry-After.
nodelay проти відсутності прапора:
- Без
nodelay: надлишкові запити ставляться в чергу та обслуговуються із затримкою, споживаючи з’єднання воркерів. - З
nodelay: надлишкові запити понад сплеск негайно відхиляються з кодом 429, швидше звільняючи ресурси. Використовуйтеnodelayдля кінцевих точок входу та публічних API.
Додавання заголовка Retry-After
Клієнти, що дотримуються RFC 6585, враховуватимуть заголовок Retry-After. У Nginx додайте його до відповіді про помилку:
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
add_header Retry-After 60 always;
}Крок 3: Діагностуйте та виправте конфлікти плагінів WordPress
WordPress є поширеним джерелом самостійно спричинених помилок 429. Плагіни, які опитують зовнішні API при кожному завантаженні сторінки — SEO-інструменти, що отримують дані ключових слів, аналітичні плагіни, що звертаються додому, або розширення WooCommerce, що запитують платіжні шлюзи — можуть швидко вичерпати ліміти швидкості.
Систематична процедура ізоляції:
- Деактивуйте всі плагіни через панель керування WordPress або, якщо панель недоступна, через WP-CLI:
wp plugin deactivate --all- Реактивуйте плагіни по одному, тестуючи після кожної активації:
wp plugin activate plugin-slug- Відстежуйте журнал доступу в окремому терміналі під час реактивації:
tail -f /var/log/nginx/access.log | grep " 429 "- Після виявлення проблемного плагіна перевірте його налаштування щодо інтервалів опитування API або параметрів частоти запитів перед остаточною деактивацією.
Поширені порушники: Jetpack (модулі статистики та синхронізації), Yoast SEO (при підключенні до MyYoast), WooCommerce Subscriptions та будь-який плагін, що використовує вбудований wp_remote_get() WordPress у циклі без кешування транзієнтів.
Правильне виправлення майже ніколи не полягає у видаленні плагіна — потрібно забезпечити кешування відповідей API за допомогою транзієнтів WordPress:
$cached = get_transient( 'my_api_response' );
if ( false === $cached ) {
$response = wp_remote_get( 'https://api.example.com/data' );
set_transient( 'my_api_response', $response, HOUR_IN_SECONDS );
$cached = $response;
}Крок 4: Реалізуйте обмеження запитів API в коді застосунку
Коли ваш застосунок є *клієнтом*, що звертається до стороннього API, ви несете відповідальність за дотримання їхніх лімітів швидкості. Покладатися на реактивне перехоплення відповідей 429 — це погана інженерна практика; реалізуйте проактивне обмеження.
Node.js з p-throttle
import pThrottle from 'p-throttle';
const throttle = pThrottle({
limit: 10, // max 10 calls
interval: 1000 // per 1000ms (1 second)
});
const throttledFetch = throttle(async (url) => {
const response = await fetch(url);
return response.json();
});Python з tenacity для експоненційного відкату
Одного лише обмеження швидкості недостатньо, якщо API встановлює ліміти сплесків. Поєднуйте обмеження з експоненційним відкатом при відповідях 429:
import requests
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception
def is_rate_limited(exception):
return (
isinstance(exception, requests.HTTPError)
and exception.response.status_code == 429
)
@retry(
retry=retry_if_exception(is_rate_limited),
wait=wait_exponential(multiplier=1, min=2, max=60),
stop=stop_after_attempt(5)
)
def call_api(url):
response = requests.get(url)
response.raise_for_status()
return response.json()Це повторює спроби до 5 разів з експоненційним відкатом (2с, 4с, 8с, 16с, 32с), обмеженим 60 секундами — патерн, що поважає інфраструктуру провайдера API, забезпечуючи при цьому коректне відновлення.
Дотримання заголовка Retry-After
Якщо API повертає заголовок Retry-After, використовуйте його замість фіксованого відкату:
def call_with_retry_after(url):
response = requests.get(url)
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 5))
time.sleep(retry_after)
return call_with_retry_after(url)
response.raise_for_status()
return response.json()Крок 5: Блокуйте ботів і керуйте ними на кількох рівнях
Боти рідко чесно себе ідентифікують, але залишають відбитки в рядках user-agent, патернах запитів та аномаліях заголовків.
Блокування відомих шкідливих ботів у Nginx
map $http_user_agent $bad_bot {
default 0;
~*SemrushBot 1;
~*AhrefsBot 1;
~*MJ12bot 1;
~*DotBot 1;
~*PetalBot 1;
~*serpstatbot 1;
}
server {
if ($bad_bot) {
return 429;
}
}Керування швидкістю сканування через robots.txt
User-agent: Googlebot
Crawl-delay: 2
User-agent: *
Crawl-delay: 10Зверніть увагу, що Crawl-delay дотримуються не всі краулери, але він сигналізує про наміри та поважається Bing, Yandex і більшістю коректно поводящихся ботів.
Інтеграція Web Application Firewall (WAF)
WAF, що працює на межі CDN (Cloudflare, AWS WAF, Sucuri), може застосовувати ліміти швидкості до того, як трафік досягне вашого сервера-джерела, значно знижуючи навантаження. Правила обмеження швидкості Cloudflare, наприклад, можна налаштувати для виклику або блокування IP-адрес, що перевищують порогове значення, без будь-яких змін у конфігурації вашого сервера-джерела — це значна операційна перевага для сайтів з високим трафіком.
Крок 6: Налаштуйте параметри плагіна безпеки у WordPress
Якщо ви використовуєте Wordfence, порогові значення обмеження швидкості часто встановлені консервативно і можуть спричиняти хибні спрацьовування для легітимних користувачів, особливо на сайтах з інтенсивним використанням AJAX або активністю авторизованих користувачів.
Перейдіть до Wordfence > Firewall > All Firewall Options > Rate Limiting та перегляньте:
- How should we treat Google’s crawlers — встановіть значення «Verified Google crawlers are not rate limited», щоб запобігти впливу на SEO.
- If anyone’s requests exceed — збільшіть порогове значення від стандартного (наприклад, з 240 до 480 запитів на хвилину для авторизованих користувачів на сайтах з великим вмістом).
- If a crawler’s page views exceed — налаштуйте відповідно до ваших фактичних вимог до бюджету сканування.
Після налаштування відстежуйте перегляд Live Traffic у Wordfence протягом 24–48 годин, щоб переконатися, що легітимні користувачі більше не блокуються.
Крок 7: Очистіть кеш на стороні клієнта та діагностуйте проблеми на рівні браузера
Кешована відповідь 429 у браузері є рідкісною, але можливою, якщо відповідь містила заголовки Cache-Control: max-age (неправильна конфігурація сервера). Стандартні відповіді 429 не повинні кешуватися.
Chrome:
Settings > Privacy and Security > Clear browsing dataВиберіть Cached images and files та Cookies and other site data, потім очистіть.
Перевірте заголовки відповіді безпосередньо за допомогою curl, щоб виключити поведінку, специфічну для браузера:
curl -I -X GET https://yourdomain.com/problematic-endpointШукайте заголовки Cache-Control, Retry-After та X-RateLimit-* у відповіді. Ці заголовки точно вказують, який рівень застосовує обмеження і коли клієнт може повторити спробу.
Порівняння: підходи до обмеження швидкості за рівнями
| Рівень | Інструмент / Метод | Гранулярність | Накладні витрати | Найкраще для |
|---|
| — | — | — | — | — |
|---|
| CDN / Edge | Cloudflare Rate Limiting, AWS WAF | На IP, на шлях, на заголовок | Дуже низькі (до джерела) | DDoS, пом’якшення скрейпінгу |
|---|
| Зворотний проксі | Nginx `limit_req_zone` | На IP, на зону | Низькі | Кінцеві точки API, сторінки входу |
|---|
| Веб-сервер | Apache `mod_evasive` | На IP, на сторінку | Низькі-середні | Спільний хостинг, застарілі стеки |
|---|
| Застосунок | Проміжне ПЗ для обмеження, API-шлюз | На користувача, на токен, на ключ | Середні | Багатоорендний SaaS, REST API |
|---|
| Плагін CMS | Wordfence, iThemes Security | На IP, на роль користувача | Середні-високі | Захист специфічний для WordPress |
|---|
| Код клієнта | `tenacity`, `p-throttle`, відкат | На вихідний запит | На стороні застосунку | Споживання стороннього API |
|---|
Коли звертатися до хостинг-провайдера
Зверніться до хостинг-провайдера, коли:
- Помилка 429 надходить від upstream-балансувальника навантаження або зворотного проксі, яким ви не керуєте.
- Аналіз журналів показує, що ваш застосунок знаходиться в межах очікуваних обсягів запитів, але помилка зберігається.
- Вам потрібне тимчасове звільнення від ліміту швидкості під час запланованого сплеску трафіку (запуск продукту, маркетингова кампанія).
- Помилка з’являється лише в певних географічних регіонах, що вказує на проблеми з маршрутизацією CDN або anycast.
При використанні плану VPS Hosting ви маєте прямий доступ до файлів конфігурації сервера і можете реалізувати всі описані вище зміни Nginx та Apache без відкриття тікету підтримки. На керованій інфраструктурі, як-от Dedicated Servers, команда підтримки вашого провайдера може допомогти з відстеженням з’єднань на рівні ядра та правилами апаратного брандмауера, що виходять за межі можливостей конфігурації на рівні застосунку.
Якщо ваш стек включає панель керування, VPS з cPanel надає доступ до налаштувань ModSecurity та обмеження швидкості Apache через графічний інтерфейс, що спрощує конфігурацію для команд без глибокої експертизи в командному рядку.
Захист кінцевих точок API за допомогою SSL
Часто overlooked фактор: незашифровані HTTP-кінцеві точки більш вразливі до атак повторного відтворення та підбору облікових даних, що спричиняє брутфорс-індуковані помилки 429. Примусове використання HTTPS з дійсним SSL-сертифікатом гарантує, що токени автентифікації та сесійні файли cookie не можуть бути перехоплені та відтворені автоматизованими інструментами, усуваючи одну категорію трафіку, що спричиняє перевищення лімітів, у її джерелі.
Технічна матриця рішень: вибір правильного виправлення
Використовуйте цей контрольний список для спрямування діагностики до правильного рішення:
- 429 на
/wp-login.phpабо/xmlrpc.php— посильте Nginxlimit_reqдля цих шляхів, повністю заблокуйтеxmlrpc.php, якщо це не потрібно, увімкніть захист від брутфорсу Wordfence. - 429 на кінцевих точках API з вашого власного коду застосунку — реалізуйте експоненційний відкат з аналізом заголовка
Retry-After; додайте кешування транзієнтів/Redis для зменшення частоти вихідних викликів. - 429, що впливає на всіх користувачів переривчасто на спільному хостингу — перейдіть на VPS для ізольованих ресурсів і налаштовуваних лімітів швидкості.
- 429 від стороннього API, який споживає ваш застосунок — перевірте частоту викликів, реалізуйте чергування запитів, агресивно кешуйте відповіді та зверніться до провайдера API для обговорення збільшення квоти.
- 429, спричинений конкретним ботом або краулером — заблокуйте на рівні WAF або Nginx
mapза user-agent; перевіряйте легітимних краулерів (Googlebot) через зворотний DNS перед блокуванням. - 429, що з’являється лише в браузері, але не в
curl— очистіть кеш браузера; перевірте наявність service worker, що кешує відповідь про помилку; перевірте заголовкиCache-Controlу відповіді 429. - 429 без ідентифікованого патерну в журналах — перевірте журнали upstream CDN або балансувальника навантаження; ліміт може застосовуватися на рівні інфраструктури, невидимому в журналах застосунку.
FAQ
У чому різниця між помилками 429 та 503?
Помилка 429 — це навмисне відхилення на основі правил, що видається, коли клієнт перевищує визначену швидкість запитів. Помилка 503 вказує на те, що сервер тимчасово не може обробляти запити через перевантаження або технічне обслуговування. Виправлення для 429 — це коригування ліміту швидкості або поведінки клієнта; виправлення для 503 — масштабування потужності або відновлення сервісу.
Чи завжди слід збільшувати ліміти швидкості при появі помилки 429?
Ні. Збільшення лімітів доцільне лише тоді, коли блокується легітимний трафік. Якщо помилка 429 спричинена ботами, спробами брутфорсу або неправильно налаштованим скриптом, підвищення ліміту погіршить проблему, пропускаючи більше шкідливого трафіку. Завжди спочатку визначайте джерело.
Що робить заголовок Retry-After і чи завжди його слід включати?
Заголовок Retry-After повідомляє клієнту, скільки секунд чекати перед повторною спробою. RFC 6585 рекомендує включати його з кожною відповіддю 429. Коректно поводящіся HTTP-клієнти та споживачі API враховуватимуть його, зменшуючи шторми повторних спроб, що посилюють початкову проблему обмеження швидкості.
Чи може помилка 429 зашкодити моєму SEO?
Так, якщо Googlebot постійно отримує відповіді 429, він зменшить частоту сканування вашого сайту, що може затримати індексацію нового або оновленого вмісту. Wordfence та подібні плагіни слід налаштувати для звільнення перевірених краулерів Google від обмеження швидкості. Відстежуйте звіт Crawl Stats у Google Search Console на предмет сплесків серверних помилок.
Як запобігти тому, щоб мій власний застосунок спричиняв помилки 429 на зовнішніх API?
Реалізуйте комбінацію проактивного обмеження (обмежте швидкість вихідних запитів нижче задокументованого порогу API), агресивного кешування відповідей (зберігайте результати API в Redis або Memcached з відповідними TTL) та реактивного експоненційного відкату (аналізуйте заголовки Retry-After та відкочуйтеся відповідно). Ніколи не робіть виклики API синхронно при кожному завантаженні сторінки без рівня кешування перед ними.
