Napraw 429 Too Many Requests: Wycofanie, Budżety i Rozpraszanie IP
429 to jedyna blokada, która mówi ci dokładnie, jak ją naprawić — jeśli przeczytasz nagłówki odpowiedzi zamiast po prostu ponawiać próbę. Oto matematyka stojąca za bezpiecznym przepustowością scrapingu.
HTTP 429 Too Many Requests to najbardziej uczciwa blokada, jaką może wysłać ci strona internetowa. W przeciwieństwie do 403, nazywa problem — byłeś zbyt szybki — i często dostarcza lekarstwo w nagłówku odpowiedzi. Jednak standardową reakcją jest opakowanie wywołania w pętlę ponawiania i nadzieja, co zamienia rozwiązywalny problem tempa w powolny, generujący blokady bałagan. Ten przewodnik traktuje 429 jako to, czym jest: problem matematyczny z czterema dźwigniami. Przeczytaj odpowiedź, dostosuj tempo do opublikowanego limitu, poprawnie wycofaj się, gdy przekroczysz, i rozłóż pozostałe obciążenie na tożsamości.
Co oznacza 429 i kiedy kłamie
Ogranicznik szybkości liczy żądania na tożsamość — zwykle adres IP, czasami klucz API lub ciasteczko sesji — w ramach okna czasowego. Przekrocz próg i otrzymasz 429 zamiast treści. Implementacje różnią się: token buckets przydzielają stały przydział, który uzupełnia się według harmonogramu, sliding windows liczą w okresie ruchomym zamiast minut zegarowych, a systemy warstwowe dławią przy miękkim limicie przed twardym blokowaniem przy wyższym. To, z którym się spotykasz, decyduje, czy krótka przerwa wystarczy, czy musisz poczekać na całe okno.
Teraz zastrzeżenie, które oszczędza godziny: 429 przy twoim pierwszym żądaniu nie jest ograniczeniem szybkości. To odpowiedź bota w przebraniu ograniczenia szybkości. Szeroko czytany wątek na Stack Overflow opisuje dokładnie to — pierwsze wywołanie scrapera zwróciło stronę z napisem „Misbehaving Content Scraper Please use robots.txt Your IP has been rate limited” wraz z 429. Nic nie zostało przekroczone; serwer po prostu zdecydował, że klient to bot i wybrał ten kod. Jeśli widzisz 429, zanim wyślesz jakąkolwiek ilość, traktuj to jako problem wykrywania i pracuj nad nagłówkami i kontrolami IP w naszym przewodniku po 403 forbidden errors.
Przeczytaj odpowiedź, zanim zmienisz jakikolwiek kod
Dobrze zachowujące się serwery mówią ci, kiedy wrócić. Retry-After zawiera albo liczbę sekund, albo datę HTTP. Wiele API dodaje X-RateLimit-Limit (sufit), X-RateLimit-Remaining (co zostało w bieżącym oknie) i X-RateLimit-Reset (kiedy się uzupełnia). Te trzy zamieniają reaktywne ponawianie w proaktywne dostosowywanie tempa: możesz zwolnić przed blokadą, a nie po niej.
import requests
r = requests.get("https://target.example/api/items", timeout=20)
print(r.status_code)
for h in ("Retry-After", "X-RateLimit-Limit", "X-RateLimit-Remaining", "X-RateLimit-Reset"):
if h in r.headers:
print(f"{h}: {r.headers[h]}")
# No headers at all? The limit is undocumented - measure it:
# send a slow ramp (1 req/s, then 2, then 4) and note where 429 starts.
Jeśli nic użytecznego nie wraca, zmierz limit samodzielnie za pomocą rampy: uruchom jedno żądanie na sekundę przez minutę, potem dwa, potem cztery i zanotuj tempo, przy którym pojawiają się 429. Dziesięć minut pomiaru bije tydzień zgadywania, a liczba, którą znajdziesz, staje się budżetem, na którym opiera się wszystko inne.

Arytmetyka tempa
Weź udokumentowany limit i podziel. Limit 100 żądań na minutę oznacza 60 / 100 = 0,6 sekundy między żądaniami jako absolutne minimum — a minimum to nie cel. Opóźnienie sieciowe się zmienia, twój zegar i serwerowy się nie zgadzają, a wybuch na granicy okna może podwoić twoje pozorne tempo. Celuj w 70-80% limitu: około 0,8 sekundy na żądanie w tym przykładzie, co nadal daje ci 75 stron na minutę.
Współbieżność wynika z tej samej liczby. Jeśli chcesz 1,25 żądania na sekundę, a każde żądanie trwa 2 sekundy w obie strony, potrzebujesz 1,25 x 2 = 2,5 żądania w trakcie — więc semafor 3, a nie 50, które domyślnie ustawia twój asynchroniczny kod. Nieograniczone asynchroniczne rozpraszanie jest najczęstszą przyczyną 429: sto korutyn uruchomionych jednocześnie przybywa jako jeden natychmiastowy wybuch, niezależnie od tego, jak uprzejmie wygląda średnia. Jeśli scrapujesz z asyncio, wzorce semaforów w async Python scraping with httpx and aiohttp są rozwiązaniem.
Wycofanie, które działa: wykładnicze, z limitem, z jitterem
Kiedy trafisz na 429, uszanuj Retry-After jeśli jest obecny. W przeciwnym razie zacznij od jednej sekundy i podwajaj — 1, 2, 4, 8, 16 — do twardego limitu, aby uszkodzony cel nie mógł zablokować twojej kolejki na zawsze. Następnie dodaj jitter. Bez losowości, każdy pracownik, który trafił na ścianę w tym samym momencie, ponawia próbę w tym samym momencie, odtwarzając wybuch, który spowodował problem.
import random, time, requests
def get_with_backoff(session, url, max_tries=6, cap=120.0):
for attempt in range(max_tries):
r = session.get(url, timeout=20)
if r.status_code != 429:
return r
ra = r.headers.get("Retry-After", "")
wait = float(ra) if ra.isdigit() else 2.0 ** attempt # 1, 2, 4, 8, 16, 32
wait = min(wait, cap)
wait += random.uniform(0, wait * 0.3) # jitter: break the lockstep
time.sleep(wait)
raise RuntimeError(f"still 429 after {max_tries} attempts: {url}")
Jeszcze lepiej, zamknij pętlę. Additive-increase/multiplicative-decrease daje ci scrapera, który sam znajduje limit i pozostaje tuż pod nim: zwiększaj tempo, gdy odpowiedzi są czyste, zmniejszaj je o połowę, gdy pojawi się 429. Trzymaj jednego dostosowującego tempo na domenę — limity są na hosta, a jeden agresywny cel nie powinien spowalniać pozostałych czterdziestu.
class Pacer:
"""One per domain. Additive increase, multiplicative decrease."""
def __init__(self, rps=2.0, floor=0.2, ceiling=8.0):
self.rps, self.floor, self.ceiling = rps, floor, ceiling
def ok(self): # clean response: creep faster
self.rps = min(self.ceiling, self.rps + 0.05)
def throttled(self): # 429: halve immediately
self.rps = max(self.floor, self.rps / 2)
@property
def gap(self):
return 1.0 / self.rps
Rozpraszanie obciążenia: budżet jest na tożsamość, nie na projekt
Gdy już dostosujesz tempo i nadal potrzebujesz większej przepustowości, jedyną dźwignią, która pozostaje, są tożsamości. Ponieważ licznik jest przypisany do twojego IP, N wyjściowych IP daje ci N razy większy budżet — arytmetyka jest tak prosta. Jeśli strona toleruje 60 żądań na minutę na adres, a ty potrzebujesz 1,200 stron na minutę, to 20 równoczesnych wyjść działających wygodnie poniżej limitu, a nie jedno wyjście działające dwadzieścia razy ponad nim.
To właśnie do tego służą rotujące proxy. Rotująca brama przydziela każdemu żądaniu inny adres IP z puli ponad 90 milionów adresów w ponad 200 krajach, więc liczniki na IP nigdy się nie wypełniają. Dwa zasady robią różnicę między rozpraszaniem obciążenia a spalaniem puli: utrzymuj tempo na IP poniżej limitu nawet po rotacji (rotacja mnoży twój budżet, nie usuwa go) i używaj sesji lepkich dla każdego przepływu, który obejmuje kilka żądań — logowanie, koszyk, zestaw wyników stronicowanych — aby sesja nie przerwała się w połowie. Gdy potrzebujesz tego samego IP przez kilka minut i nowego po tym, kompromisy są przedstawione w sticky versus rotating sessions.
Pomnóż swój budżet szybkości z IP rezydencyjnymi

Tańsze niż więcej IP: wysyłaj mniej żądań
- Deduplikuj przed pobieraniem. Większość kolejek crawl zawiera ten sam URL pod parametrami śledzenia i końcowymi ukośnikami - najpierw kanonizuj.
- Używaj warunkowych GET. Wyślij If-Modified-Since lub If-None-Match, a 304 kosztuje cię ułamek przepustowości i nadal liczy się jako jedno żądanie.
- Preferuj końcówki JSON nad renderowanym HTML. Jedno wywołanie API często zastępuje dziesięć pobrań stron, a limity API są zazwyczaj udokumentowane.
- Agresywnie buforuj podczas rozwoju. Ponowne uruchomienie parsera na zapisanych odpowiedziach kosztuje zero żądań i zero blokad.
- Scrapuj poza szczytem w lokalnej strefie czasowej celu. To samo tempo mniej obciąża serwer o 03:00 i jest rzadziej ograniczane.
- Pobieraj tylko to, co się zmienia. Codzienny pełny crawl katalogu, który aktualizuje się co tydzień, to sześć zmarnowanych crawlów.
Dyscyplina przepustowości płaci podwójnie — mniej żądań oznacza mniej 429 i mniejszy rachunek, co jest tym samym argumentem, który przedstawiamy w redukcji kosztów przepustowości proxy. A jeśli wolisz nie budować infrastruktury tempa w ogóle, QuantumProxies Scraper API absorbuje ponowienia, rotację i ograniczanie na domenę za jednym endpointem, który zwraca markdown, JSON lub HTML.
Często zadawane pytania
Jak uniknąć błędu HTTP 429 too many requests w Pythonie?
Ustaw celową przerwę między żądaniami na podstawie opublikowanego limitu celu, ogranicz współbieżność za pomocą semafora dostosowanego do szybkości razy opóźnienie, uszanuj Retry-After gdy się pojawi, i ponawiaj z wykładniczym wycofaniem plus jitter. Jeśli potrzebujesz większej przepustowości po tym, rozłóż żądania na rotujące IP proxy zamiast skracać przerwę.
Jak długo powinienem czekać po 429?
Dokładnie tak długo, jak mówi Retry-After, jeśli serwer go wysyła — może to być liczba sekund lub data HTTP. Bez tego nagłówka, zacznij od jednej sekundy i podwajaj przy każdym kolejnym 429 do limitu minuty lub dwóch, dodając losowy jitter, aby równoległe pracowniki nie ponawiały jednocześnie.
Czy proxy naprawiają błędy 429?
Mnożą twój budżet, nie usuwają limitu. Ponieważ liczniki są przypisane do IP klienta, rozpraszanie uruchomienia na wiele wyjść rezydencyjnych utrzymuje każdy adres poniżej progu. Ale pula, która jest obciążana dziesięciokrotnie ponad limit na IP, nadal zbiera 429 — i spala swoją reputację. Najpierw dostosuj tempo, potem rotuj.
Czy 429 to to samo, co ban?
Nie. 429 jest tymczasowe z założenia i znika, gdy okno się resetuje, co odróżnia go od blokady tożsamości 403. Ignorowanie go wielokrotnie to sposób, w jaki staje się trwałe: utrzymujące się przekroczenie to dokładnie sygnał, który promuje ograniczenie do dłużej trwającego bana IP.
Dlaczego dostaję 429 przy pierwszym żądaniu?
Ponieważ nic nie zostało faktycznie policzone. Niektóre serwery zwracają 429 każdemu klientowi, którego uważają za bota, niezależnie od ilości — kod statusu to po prostu ich wybrana odpowiedź. Sprawdź ciało odpowiedzi: jeśli wspomina o robots.txt, scraperach lub zaporze, popraw swoje nagłówki, odcisk TLS i wyjściowe IP zamiast tempa.
Traktuj limity szybkości jako budżet, który wydajesz celowo. Zmierz sufit, działaj na poziomie 70-80% jego wartości, wycofaj się z jitterem, gdy przekroczysz, i kup więcej tożsamości dopiero, gdy tempo jest właściwe. Zrobione w tej kolejności, 429 przestają być klasą błędów i stają się liczbą w pliku konfiguracyjnym.
Zdobądź rotujące proxy i przestań walczyć z limitami szybkości