Jak rozwiązać błąd 429 Too Many Requests
Błąd 429 Too Many Requests to kod statusu HTTP zdefiniowany w RFC 6585, który sygnalizuje, że klient przekroczył limit żądań narzucony przez serwer lub pośredni serwer proxy. Serwer odmawia dalszych żądań do momentu zresetowania okna limitowania, opcjonalnie zwracając nagłówek Retry-After, który informuje klienta, jak długo musi czekać.
W przeciwieństwie do błędu 503 Service Unavailable, który odzwierciedla awarię pojemności po stronie serwera, błąd 429 jest celowym, opartym na polityce odrzuceniem. Zrozumienie tej różnicy jest kluczowe: rozwiązanie nie zawsze polega na skalowaniu infrastruktury — chodzi o zidentyfikowanie *kto* wysyła zbyt wiele żądań, *dlaczego*, a następnie skorygowanie zachowania na właściwej warstwie stosu.
Co tak naprawdę powoduje błąd 429
Błąd pojawia się na wielu warstwach, a ich mylenie prowadzi do błędnej diagnozy. Przyczyna źródłowa należy do jednej z czterech kategorii:
- Limitowanie żądań po stronie serwera — serwery WWW (Apache, Nginx), odwrotne serwery proxy (HAProxy, Varnish) lub węzły brzegowe CDN (Cloudflare, Fastly) egzekwują progi żądań per IP lub per token.
- Ograniczanie przepustowości na warstwie aplikacji — wtyczki WordPress, niestandardowe oprogramowanie pośredniczące lub bramy API narzucają własne limity niezależnie od serwera WWW.
- Wyczerpanie limitu zewnętrznego API — Twoja aplikacja wywołuje zewnętrzne API (Google Maps, Stripe, OpenAI) szybciej, niż pozwala na to limit dostawcy, a błąd 429 jest propagowany z powrotem do użytkownika końcowego.
- Złośliwy lub niekontrolowany ruch automatyczny — próby logowania metodą brute-force, agresywne skrobaki, błędnie skonfigurowane skrypty monitorujące lub źle napisane crawlery nasycają budżety żądań.
Często pomijany przypadek brzegowy: środowiska hostingu współdzielonego, w których skok ruchu sąsiedniego najemcy zużywa współdzielone pule połączeń, powodując, że Twoja aplikacja otrzymuje odpowiedzi 429 od nadrzędnego load balancera, mimo że Twój własny kod działa poprawnie. Jeśli korzystasz z planu Shared Web Hosting i widzisz sporadyczne skoki błędów 429 bez odpowiadającego im wzrostu własnego ruchu, jest to pierwsza hipoteza do sprawdzenia.
Krok 1: Zidentyfikuj źródło nadmiernych żądań
Naprawianie błędu 429 bez zidentyfikowania jego źródła to zgadywanie. Zacznij od danych.
Odczytywanie logów dostępu Apache
grep " 429 " /var/log/apache2/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20To polecenie wyodrębnia każdą odpowiedź 429, zlicza wystąpienia per adres IP i szereguje je. IP pojawiający się tysiące razy w ciągu minut to bot, błędnie skonfigurowany skrypt lub atakujący.
Odczytywanie logów dostępu Nginx
awk '$9 == 429 {print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20Korelowanie ze ścieżkami żądań
grep " 429 " /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20Jeśli /wp-login.php lub /xmlrpc.php dominuje w wynikach, masz do czynienia z kampanią brute-force lub credential stuffing. Jeśli na szczycie listy znajduje się endpoint API taki jak /api/v1/search, winowajcą jest prawdopodobnie błędnie skonfigurowany klient lub skrobak.
Używanie fail2ban do wykrywania wzorców
fail2ban-client status
fail2ban-client status nginx-req-limitJeśli fail2ban jest skonfigurowany z więzieniem nginx-req-limit, pokaże Ci dokładnie, które adresy IP zostały zablokowane z powodu naruszeń limitów żądań, oszczędzając znaczny czas na parsowaniu logów.
Krok 2: Skonfiguruj limitowanie żądań na poziomie serwera WWW
Apache: Używanie mod_ratelimit i mod_evasive
Fragment kodu .htaccess powszechnie krążący w sieci używa mod_rewrite do zwracania błędu 403, a nie właściwego 429. Bardziej semantycznie poprawne i operacyjnie solidne podejście używa mod_evasive do łagodzenia ataków DoS.
Zainstaluj i skonfiguruj mod_evasive na Debian/Ubuntu:
apt install libapache2-mod-evasive
a2enmod evasiveNastępnie dodaj do wirtualnego hosta Apache lub konfiguracji globalnej:
<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>Blokuje to każdy adres IP, który trafia na tę samą stronę więcej niż 5 razy na sekundę lub na całą witrynę więcej niż 50 razy na sekundę, na 10-sekundowy okres ochłodzenia.
Aby uzyskać właściwą odpowiedź 429 przez .htaccess w Apache z mod_rewrite, potrzebujesz niestandardowego dokumentu błędu:
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 z właściwą obsługą serii żądań
Dyrektywa ngx_http_limit_req_module Nginx jest jednym z najskuteczniejszych dostępnych narzędzi do limitowania żądań. Kluczowe parametry, które są często błędnie konfigurowane, to burst i nodelay.
W /etc/nginx/nginx.conf lub dedykowanym pliku include:
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;
}
}
}Kluczowa subtelność: Bez limit_req_status 429 Nginx domyślnie zwraca 503 dla żądań objętych limitowaniem. Ustawienie go na 429 jest semantycznie poprawne i pozwala klientom implementować właściwą logikę wycofywania Retry-After.
nodelay vs. brak flagi:
- Bez
nodelay: nadmiarowe żądania są kolejkowane i obsługiwane z dodatkowym opóźnieniem, zużywając połączenia robocze. - Z
nodelay: nadmiarowe żądania przekraczające serię są natychmiast odrzucane z błędem 429, szybciej zwalniając zasoby. Używajnodelaydla endpointów logowania i publicznych API.
Dodawanie nagłówka Retry-After
Klienci respektujący RFC 6585 będą honorować nagłówek Retry-After. W Nginx dodaj go do odpowiedzi błędu:
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
add_header Retry-After 60 always;
}Krok 3: Diagnozowanie i naprawianie konfliktów wtyczek WordPress
WordPress jest częstym źródłem samodzielnie wywołanych błędów 429. Wtyczki, które odpytują zewnętrzne API przy każdym załadowaniu strony — narzędzia SEO pobierające dane o słowach kluczowych, wtyczki analityczne dzwoniące do domu lub rozszerzenia WooCommerce odpytujące bramki płatności — mogą szybko wyczerpać limity żądań.
Systematyczna procedura izolacji:
- Dezaktywuj wszystkie wtyczki przez panel WordPress lub, jeśli panel jest niedostępny, przez WP-CLI:
wp plugin deactivate --all- Reaktywuj wtyczki po jednej, testując po każdej aktywacji:
wp plugin activate plugin-slug- Monitoruj log dostępu w osobnym terminalu podczas reaktywacji:
tail -f /var/log/nginx/access.log | grep " 429 "- Po zidentyfikowaniu problematycznej wtyczki sprawdź jej ustawienia pod kątem interwałów odpytywania API lub opcji częstotliwości żądań przed jej trwałą dezaktywacją.
Częste winowajcy: Jetpack (moduły statystyk i synchronizacji), Yoast SEO (po połączeniu z MyYoast), WooCommerce Subscriptions oraz każda wtyczka używająca wbudowanej funkcji WordPress wp_remote_get() w pętli bez buforowania transientów.
Właściwe rozwiązanie prawie nigdy nie polega na usunięciu wtyczki — chodzi o zapewnienie, że odpowiedzi API są buforowane przy użyciu transientów 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;
}Krok 4: Implementacja ograniczania żądań API w kodzie aplikacji
Gdy Twoja aplikacja jest *klientem* trafiającym do zewnętrznego API, jesteś odpowiedzialny za przestrzeganie ich limitów żądań. Poleganie na reaktywnym przechwytywaniu odpowiedzi 429 to słaba inżynieria — implementuj proaktywne ograniczanie przepustowości.
Node.js z 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 z tenacity dla wykładniczego wycofywania
Samo ograniczanie przepustowości jest niewystarczające, jeśli API narzuca limity serii żądań. Połącz ograniczanie z wykładniczym wycofywaniem przy odpowiedziach 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()Ponawia próby do 5 razy z wykładniczym wycofywaniem (2s, 4s, 8s, 16s, 32s), ograniczonym do 60 sekund — wzorzec, który szanuje infrastrukturę dostawcy API, jednocześnie umożliwiając płynne odzyskiwanie.
Respektowanie nagłówka Retry-After
Jeśli API zwraca nagłówek Retry-After, użyj go zamiast stałego wycofywania:
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()Krok 5: Blokowanie botów i zarządzanie nimi na wielu warstwach
Boty rzadko ujawniają się uczciwie, ale pozostawiają odciski palców w ciągach user-agent, wzorcach żądań i anomaliach nagłówków.
Blokowanie znanych złośliwych botów w 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;
}
}Zarządzanie częstotliwością crawlowania przez robots.txt
User-agent: Googlebot
Crawl-delay: 2
User-agent: *
Crawl-delay: 10Należy pamiętać, że Crawl-delay nie jest honorowany przez wszystkie crawlery, ale sygnalizuje intencje i jest respektowany przez Bing, Yandex i większość dobrze zachowujących się botów.
Integracja z Web Application Firewall (WAF)
WAF działający na brzegu CDN (Cloudflare, AWS WAF, Sucuri) może egzekwować limity żądań zanim ruch dotrze do Twojego serwera źródłowego, drastycznie redukując obciążenie. Reguły Rate Limiting Cloudflare, na przykład, można skonfigurować tak, aby kwestionowały lub blokowały adresy IP przekraczające próg bez żadnych zmian w konfiguracji serwera źródłowego — znacząca przewaga operacyjna dla witryn o dużym ruchu.
Krok 6: Dostosowanie ustawień wtyczek bezpieczeństwa w WordPress
Jeśli używasz Wordfence, progi limitowania żądań są często ustawione konserwatywnie i mogą powodować fałszywe alarmy dla legalnych użytkowników, szczególnie na witrynach z intensywnym użyciem AJAX lub aktywnością zalogowanych użytkowników.
Przejdź do Wordfence > Firewall > All Firewall Options > Rate Limiting i sprawdź:
- How should we treat Google’s crawlers — ustaw na „Verified Google crawlers are not rate limited”, aby zapobiec wpływowi na SEO.
- If anyone’s requests exceed — zwiększ próg z domyślnego (np. z 240 do 480 żądań na minutę dla zalogowanych użytkowników na witrynach z dużą ilością treści).
- If a crawler’s page views exceed — dostosuj na podstawie rzeczywistych wymagań budżetu crawlowania.
Po dostosowaniu monitoruj widok Wordfence Live Traffic przez 24–48 godzin, aby potwierdzić, że legalni użytkownicy nie są już blokowani.
Krok 7: Czyszczenie pamięci podręcznej po stronie klienta i diagnozowanie problemów na poziomie przeglądarki
Buforowana odpowiedź 429 w przeglądarce jest rzadka, ale możliwa, jeśli odpowiedź zawierała nagłówki Cache-Control: max-age (błędna konfiguracja serwera). Standardowe odpowiedzi 429 nie powinny być buforowane.
Chrome:
Settings > Privacy and Security > Clear browsing dataWybierz Cached images and files i Cookies and other site data, a następnie wyczyść.
Zweryfikuj nagłówki odpowiedzi bezpośrednio używając curl, aby wykluczyć zachowanie specyficzne dla przeglądarki:
curl -I -X GET https://yourdomain.com/problematic-endpointSzukaj nagłówków Cache-Control, Retry-After i X-RateLimit-* w odpowiedzi. Te nagłówki ujawniają dokładnie, która warstwa egzekwuje limit i kiedy klient może ponowić próbę.
Porównanie: Podejścia do limitowania żądań według warstwy
| Warstwa | Narzędzie / Metoda | Granularność | Narzut | Najlepsze dla |
|---|
| — | — | — | — | — |
|---|
| CDN / Edge | Cloudflare Rate Limiting, AWS WAF | Per IP, per ścieżka, per nagłówek | Bardzo niski (przed serwerem źródłowym) | DDoS, łagodzenie skutków skrobaków |
|---|
| Odwrotny serwer proxy | Nginx `limit_req_zone` | Per IP, per strefa | Niski | Endpointy API, strony logowania |
|---|
| Serwer WWW | Apache `mod_evasive` | Per IP, per strona | Niski-średni | Hosting współdzielony, starsze stosy |
|---|
| Aplikacja | Ograniczanie przepustowości middleware, brama API | Per użytkownik, per token, per klucz | Średni | Wielodostępny SaaS, REST API |
|---|
| Wtyczka CMS | Wordfence, iThemes Security | Per IP, per rola użytkownika | Średni-wysoki | Ochrona specyficzna dla WordPress |
|---|
| Kod klienta | `tenacity`, `p-throttle`, wycofywanie | Per żądanie wychodzące | Po stronie aplikacji | Konsumpcja zewnętrznych API |
|---|
Kiedy skontaktować się z dostawcą hostingu
Eskaluj do dostawcy hostingu, gdy:
- Błąd 429 pochodzi z nadrzędnego load balancera lub odwrotnego serwera proxy, nad którym nie masz kontroli.
- Analiza logów pokazuje, że Twoja aplikacja mieści się w oczekiwanych wolumenach żądań, ale błąd nadal występuje.
- Potrzebujesz tymczasowego zwolnienia z limitu żądań podczas planowanego skoku ruchu (premiera produktu, kampania marketingowa).
- Błąd pojawia się tylko w określonych regionach geograficznych, co sugeruje problemy z routingiem CDN lub anycast.
Korzystając z planu VPS Hosting, masz bezpośredni dostęp do plików konfiguracyjnych serwera i możesz wdrożyć wszystkie opisane powyżej zmiany Nginx i Apache bez otwierania zgłoszenia do pomocy technicznej. Na zarządzanej infrastrukturze, takiej jak Dedicated Servers, zespół wsparcia dostawcy może pomóc w śledzeniu połączeń na poziomie jądra i regułach sprzętowego firewalla, które wykraczają poza możliwości konfiguracji na poziomie aplikacji.
Jeśli Twój stos zawiera panel sterowania, VPS z cPanel udostępnia ustawienia ModSecurity i limitowania żądań Apache przez GUI, co upraszcza konfigurację dla zespołów bez głębokiej wiedzy o wierszu poleceń.
Zabezpieczanie endpointów API za pomocą SSL
Często pomijany czynnik: niezaszyfrowane endpointy HTTP są bardziej podatne na ataki replay i credential stuffing, które napędzają błędy 429 wywołane przez brute-force. Wymuszanie HTTPS z ważnym certyfikatem SSL zapewnia, że tokeny uwierzytelniające i ciasteczka sesji nie mogą być przechwytywane i odtwarzane przez zautomatyzowane narzędzia, redukując u źródła jedną kategorię ruchu wyzwalającego limity żądań.
Macierz decyzji technicznych: Wybór właściwego rozwiązania
Użyj tej listy kontrolnej, aby skierować diagnozę do właściwego rozwiązania:
- 429 na
/wp-login.phplub/xmlrpc.php— wzmocnij Nginxlimit_reqdla tych ścieżek, zablokujxmlrpc.phpcałkowicie jeśli nie jest potrzebny, włącz ochronę Wordfence przed brute-force. - 429 na endpointach API z własnego kodu aplikacji — implementuj wykładnicze wycofywanie z parsowaniem nagłówka
Retry-After; dodaj buforowanie transientów/Redis, aby zmniejszyć częstotliwość wywołań wychodzących. - 429 dotyczący wszystkich użytkowników sporadycznie na hostingu współdzielonym — migruj na VPS dla izolowanych zasobów i konfigurowalnych limitów żądań.
- 429 z zewnętrznego API konsumowanego przez Twoją aplikację — przeprowadź audyt częstotliwości wywołań, implementuj kolejkowanie żądań, agresywnie buforuj odpowiedzi i skontaktuj się z dostawcą API w celu omówienia zwiększenia limitu.
- 429 spowodowany przez konkretnego bota lub crawler — blokuj na poziomie WAF lub Nginx
mapwedług user-agent; weryfikuj legalne crawlery (Googlebot) przez odwrotny DNS przed blokowaniem. - 429 pojawiający się tylko w przeglądarce, nie w
curl— wyczyść pamięć podręczną przeglądarki; sprawdź, czy service worker nie buforuje odpowiedzi błędu; sprawdź nagłówkiCache-Controlw odpowiedzi 429. - 429 bez identyfikowalnego wzorca w logach — sprawdź logi nadrzędnego CDN lub load balancera; limit może być egzekwowany na warstwie infrastruktury niewidocznej w logach aplikacji.
FAQ
Jaka jest różnica między błędem 429 a 503?
Błąd 429 to celowe, oparte na polityce odrzucenie wydawane, gdy klient przekracza zdefiniowaną częstotliwość żądań. Błąd 503 wskazuje, że serwer jest tymczasowo niezdolny do obsługi żądań z powodu przeciążenia lub konserwacji. Rozwiązaniem dla błędu 429 jest dostosowanie limitu żądań lub korekta zachowania klienta; rozwiązaniem dla błędu 503 jest skalowanie pojemności lub odzyskiwanie usługi.
Czy zawsze powinienem zwiększać limity żądań, gdy widzę błąd 429?
Nie. Zwiększanie limitów jest właściwe tylko wtedy, gdy legalny ruch jest blokowany. Jeśli błąd 429 jest spowodowany przez boty, próby brute-force lub błędnie skonfigurowany skrypt, podniesienie limitu pogarsza problem, przepuszczając więcej złośliwego ruchu. Zawsze najpierw zidentyfikuj źródło.
Co robi nagłówek Retry-After i czy zawsze powinienem go dołączać?
Nagłówek Retry-After informuje klienta, ile sekund czekać przed ponowieniem próby. RFC 6585 zaleca dołączanie go do każdej odpowiedzi 429. Dobrze zachowujące się klienty HTTP i konsumenci API będą go honorować, redukując burze ponownych prób, które potęgują pierwotny problem z limitowaniem żądań.
Czy błąd 429 może zaszkodzić mojemu SEO?
Tak, jeśli Googlebot konsekwentnie otrzymuje odpowiedzi 429, zmniejszy częstotliwość crawlowania Twojej witryny, co może opóźnić indeksowanie nowych lub zaktualizowanych treści. Wordfence i podobne wtyczki powinny być skonfigurowane tak, aby zwalniały zweryfikowane crawlery Google z limitowania żądań. Monitoruj raport Crawl Stats w Google Search Console pod kątem skoków błędów serwera.
Jak zapobiec wyzwalaniu błędów 429 przez własną aplikację w zewnętrznych API?
Implementuj kombinację proaktywnego ograniczania przepustowości (ogranicz częstotliwość żądań wychodzących poniżej udokumentowanego progu API), agresywnego buforowania odpowiedzi (przechowuj wyniki API w Redis lub Memcached z odpowiednimi TTL) i reaktywnego wykładniczego wycofywania (parsuj nagłówki Retry-After i wycofuj się odpowiednio). Nigdy nie wykonuj wywołań API synchronicznie przy każdym załadowaniu strony bez warstwy buforowania przed nimi.
