Scraping

Retry und Backoff: Wie Scraper aus kleinen Fehlern Sperren machen

Die meisten Scraper-Sperren sind selbst verschuldet. Eine naive Retry-Schleife beantwortet eine gedrosselte Antwort mit einem Schwall an Traffic, genau dann, wenn eine Seite um weniger gebeten hat.

Chris Collins

Chris Collins

23. August 2026 · 9 Min. Lesezeit

Ein Scraper trifft auf eine langsame Antwort, also versucht er es erneut. Der erneute Versuch schlägt ebenfalls fehl, also versucht er es sofort wieder, und dasselbe tun alle anderen Worker, die im selben Moment auf dieselbe Wand gestoßen sind. Innerhalb von Sekunden haben Sie eine Traffic-Welle auf eine Website losgelassen, die Ihnen bereits mitgeteilt hatte, dass sie weniger wollte, und aus einer vorübergehenden Drosselung ist nun eine harte Sperre für jede beteiligte Adresse geworden. Nicht die Website hat eskaliert. Ihre Retry-Schleife hat es getan.

Dies ist die häufigste Art, wie sich ein gut gebauter Scraper selbst schadet, und sie ist vollständig vermeidbar. Retry-Logik ist ein Lastabwurf-Mechanismus, kein Beharrungsmechanismus, und der Unterschied zwischen diesen beiden Konzepten ist der Unterschied zwischen einem Job, der graceful degradiert, und einem, der sich selbst sperren lässt. Die allgemeine Hygiene wird in avoiding blocks behandelt; hier geht es um die Mechanik des Retry-Pfads selbst.

Warum naive Retries die Lage verschlimmern

Drei Dynamiken verstärken sich gegenseitig, und sie tun dies gemeinsam.

Die erste ist, dass Retries genau dann Last hinzufügen, wenn Last das Problem ist. Ein 429 oder eine langsame Antwort ist eine Aufforderung, weniger zu senden, und darauf mit mehr Anfragen zu antworten, kehrt das Signal um. Die zweite ist Synchronisation. Worker, die im selben Moment fehlschlagen und dasselbe feste Intervall warten, werden auch im selben Moment erneut versuchen, sodass sie sich statt zu verteilen als koordinierte Welle einfinden, und jede Runde dieser Welle synchronisiert die nächste erneut. Die dritte ist, dass Retries üblicherweise pro Adresse gegen Sie gezählt werden, sodass das wiederholte Bombardieren eines Ziels von derselben IP diese Adresse von gedrosselt zu markiert bewegt, was ein Reputationsproblem ist, das den Vorfall überdauert und der Adresse in Ihren nächsten Job folgt.

Zusammengenommen macht eine naive Schleife aus einem erholbaren Zustand genau die Traffic-Form, die Anti-Bot-Systeme gebaut wurden, um sie zu erkennen. Derselbe Fehler, mit Zurückhaltung behandelt, hätte sich von selbst gelöst.

Klassifizieren, bevor Sie erneut versuchen

Die erste Regel ist, dass nicht jeder Fehler einen Retry verdient, und diejenigen, die es tun, verdienen unterschiedliche. Sortieren Sie Antworten in drei Kategorien.

Manche Fehler sind vorübergehend und einen Retry wert: Connection Resets, Timeouts, 502, 503, 504 und 429. Diese repräsentieren ein System, das momentan unfähig statt unwillig ist, und 429 im Besonderen ist eine explizite Anweisung zur Taktung, keine Ablehnung. Manche sind endgültig und dürfen niemals wiederholt werden: 404, 400, 401, ein 403, der über Adressen hinweg bestehen bleibt, und eine Seite, die sauber geparst wurde, aber nichts Gewünschtes enthielt. Diese zu wiederholen verbrennt Bandbreite und Reputation für ein Ergebnis, das sich nicht ändern kann, und ein Parsingfehler ist ein Code-Bug, den ein Retry für immer treu reproduzieren wird.

Die dritte Kategorie ist die gefährliche: Antworten, die erfolgreich aussehen, es aber nicht sind. Eine Challenge-Seite, ein generisches oder leeres Ergebnis, ein abgeschnittenes Listing oder eine Weiterleitung zu einer Landingpage können alle mit einem 200-Status ankommen, und ein Scraper, der sich nur auf Statuscodes verlässt, wird sie bereitwillig als Daten aufzeichnen. Validieren Sie den Body, bevor Sie eine Antwort als Erfolg zählen, was den Kern von detecting blocked or fake content ausmacht. Eine weiche Sperre ist ein wiederholbarer Fehler, aber nur, wenn Sie bemerken, dass es ein Fehler ist.

Exponentielles Backoff, und warum Jitter nicht optional ist

Für die wiederholbare Kategorie sollte die Verzögerung zwischen Versuchen wachsen, und die Standardform ist exponentiell: eine Sekunde warten, dann zwei, dann vier, dann acht. Wachstum ist wichtig, weil es einem kämpfenden Ziel zunehmend mehr Raum gibt statt eines konstanten Trommelschlags.

Aber exponentielles Backoff allein reicht nicht aus, und das ist der Teil, den Leute überspringen. Wenn hundert Worker gemeinsam fehlschlagen und alle genau eine Sekunde warten, versuchen sie es eine Sekunde später gemeinsam erneut. Das Backoff ist gewachsen, aber die Welle hat überlebt, und Sie haben lediglich denselben Ausschlag auf der Zeitachse verschoben. Die Lösung ist Jitter: randomisieren Sie jede Verzögerung, statt den berechneten Wert direkt zu verwenden. Full Jitter, das heißt eine zufällige Wartezeit gewählt zwischen null und der aktuellen Obergrenze, verteilt einen synchronisierten Fehlschlag in eine glatte Verteilung von Retries. Es ist eine Änderung von zwei Zeilen und die einzelne wirksamste Sache in diesem Artikel.

Zwei weitere Regeln gehören dazu. Beachten Sie Retry-After, wenn eine Website eines sendet, denn dieser Header ist das Ziel, das Ihnen genau mitteilt, wie lange Sie warten sollen, und ihn zugunsten Ihres eigenen Zeitplans zu ignorieren ist sowohl unhöflich als auch kontraproduktiv. Und begrenzen Sie sowohl die Verzögerung als auch die Anzahl der Versuche, denn eine Anfrage, die fünfmal fehlgeschlagen ist, wird beim sechsten Mal nicht erfolgreich sein, und ein unbegrenzter Retry ist nur eine langsame Art, bei etwas, das bereits verloren ist, niemals aufzugeben.

import random, time
import requests

PROXY = "http://customer-USERNAME-country-us:PASSWORD@p.shifter.io:443"
PROXIES = {"http": PROXY, "https": PROXY}

TRANSIENT = {429, 502, 503, 504}
MAX_ATTEMPTS = 5
BASE, CAP = 1.0, 60.0

def fetch(url):
    for attempt in range(MAX_ATTEMPTS):
        try:
            r = requests.get(url, proxies=PROXIES, timeout=20)
        except requests.RequestException:
            pass                                  # transient: fall through to backoff
        else:
            if r.status_code == 200 and is_valid(r.text):
                return r.text                     # validate the body, not just the code
            if r.status_code not in TRANSIENT:
                return None                       # terminal: do not retry
            after = r.headers.get("Retry-After")
            if after:
                time.sleep(min(float(after), CAP)) # the target told you the answer
                continue

        ceiling = min(CAP, BASE * (2 ** attempt))
        time.sleep(random.uniform(0, ceiling))     # full jitter, not a fixed delay
    return None

Rotieren oder Warten: die Entscheidung, die Retries meist falsch treffen

Bei residential Proxies gibt es eine zweite Achse. Ein Fehler kann mit Zeit, mit einer anderen Adresse oder mit beidem beantwortet werden, und die falsche Wahl verschwendet eines von beiden.

Warten Sie, wenn das Signal die Rate betrifft. Ein 429 oder ein Retry-After ist das Ziel, das sagt, dass Ihr Tempo zu hoch ist, und zu einer frischen Adresse zu wechseln, um dasselbe Tempo beizubehalten, ist genau das Verhalten, das wie Umgehung aussieht und einen ganzen Pool statt nur einer Route verbrennen lässt. Verlangsamen Sie stattdessen.

Rotieren Sie, wenn das Signal die Adresse betrifft. Eine Sperrseite, ein anhaltender 403 oder eine Challenge, die immer wieder auf einer Route erscheint, bedeutet, dass diese bestimmte Adresse nicht mehr vertrauenswürdig ist, und Warten wird sie nicht wiederherstellen. Ziehen Sie die Route zurück und fahren Sie mit einer frischen fort, was dem failover-Muster entspricht, und beachten Sie, dass die Reputation des Ersatzes darüber entscheidet, ob der Retry tatsächlich hilft. Der einzige Fall, in dem Rotation falsch ist, ist Arbeit mitten in einer Sitzung: Wenn ein Ablauf von einer gehaltenen Identität abhängt, bricht ein Adresswechsel ihn, sodass ein Fehler innerhalb einer sticky session bedeutet, die Sequenz auf einer neuen Sitzung neu zu starten, statt die Adresse unter der bestehenden auszutauschen.

Timeouts liegen zwischen den beiden und verdienen eine eigene Diagnose statt eines Reflexes, da die Gründe, warum Anfragen einen Timeout haben Ziel-Langsamkeit, eine ungesunde Route und eine zu hohe eigene Nebenläufigkeit umfassen.

Budgets und Circuit Breaker

Regeln für Retries pro Anfrage reichen für sich allein nicht aus, weil sie keine Sicht auf das System haben. Zwei Mechanismen verschaffen Ihnen diese Sicht.

Ein Retry-Budget begrenzt Retries als Anteil am Gesamt-Traffic, zum Beispiel indem Retries auf höchstens zehn Prozent der Anfragen an ein bestimmtes Ziel begrenzt werden. Unter normalen Bedingungen wird das Budget nie angetastet. Wenn etwas grundlegend kaputtgeht, ist das Budget sofort erschöpft und die zusätzlichen Retries finden einfach nicht statt, was die gewünschte Eigenschaft ist: Retries helfen bei isolierten Fehlern und sind während eines allgemeinen Ausfalls aktiv schädlich, und ein Budget ist das, was den Unterschied automatisch erkennt.

Ein Circuit Breaker geht weiter. Verfolgen Sie die Fehlerrate pro Ziel, und wenn sie eine Schwelle überschreitet, stoppen Sie das Senden an dieses Ziel vollständig für eine Abkühlperiode, statt es weiterhin mit einem Rinnsal aussichtsloser Anfragen zu sondieren. Nach der Abkühlung lassen Sie eine kleine Anzahl von Anfragen durch, und wenn sie erfolgreich sind, nehmen Sie den Betrieb wieder auf. Dies schützt das Ziel vor Ihrem Ansturm und schützt Ihre Adressen davor, Fehlschläge gegen eine Website anzuhäufen, die gerade niemandem antwortet. Beide Mechanismen sind pro Ziel statt global, denn eine kaputte Website sollte niemals einen Job stoppen, der von fünfzig anderen sammelt.

Retries kosten Geld und verstecken sich in Ihren Daten

Zwei Konsequenzen, die es klar zu benennen lohnt.

Jeder Retry ist eine Anfrage, für die Sie bezahlen. Bei bandbreitenbepreisten residential Proxies ist ein Retry-Sturm ein Kostenposten, und ein Job, der still fünfmal gegen eine Website erneut versucht, die den ganzen Nachmittag ausgefallen ist, kann eine überraschende Menge an Daten für nichts bewegen, was einer der weniger offensichtlichen Beiträge zum Kostenbild in cutting proxy bandwidth costs ist.

Und die Retry-Rate ist ein Frühindikator, der auf Ihr Dashboard gehört. Eine steigende Retry-Rate bei einem Ziel ist die früheste Warnung, dass sich dessen Abwehrmaßnahmen geändert haben oder Ihre Taktung abgedriftet ist, und sie zeigt sich deutlich, bevor die Erfolgsrate einbricht, weshalb Monitoring der Pipeline Versuche und Ergebnisse verfolgen sollte, nicht nur Endresultate. Ein Scraper, der sich still zu einer normal aussehenden Erfolgsrate durchretriet, versteckt das Problem, statt es zu lösen.

Wenn eine Anfrage schließlich ihre Versuche erschöpft, werfen Sie sie nicht weg. Schieben Sie sie in eine Dead-Letter-Queue und versuchen Sie es viel später erneut, im nächsten Lauf oder nach einer langen Abkühlung, statt in der aktuellen Welle. Die meisten Elemente, die während eines Vorfalls scheitern, gelingen eine Stunde später von selbst, und eine Queue macht aus einem harten Fehlschlag einen aufgeschobenen.

Das Fazit

Retry-Logik existiert, um vorübergehende Fehler abzufedern, nicht um zu beharren. Klassifizieren Sie den Fehler, bevor Sie handeln, wiederholen Sie nur, was wirklich vorübergehend ist, und validieren Sie Response-Bodies, damit eine weiche Sperre als der Fehler behandelt wird, der sie ist. Machen Sie Backoff exponentiell und immer mit Jitter, beachten Sie Retry-After, und begrenzen Sie sowohl Verzögerung als auch Versuche. Unterscheiden Sie Ratensignale, die zum Warten aufrufen, von Adresssignale, die zur Rotation aufrufen, und beantworten Sie niemals eine Drosselung, indem Sie Adressen wechseln, um dasselbe Tempo aufrechtzuerhalten. Fügen Sie ein Retry-Budget und einen Circuit Breaker pro Ziel hinzu, damit ein breiter Ausfall sich nicht in eine selbstverschuldete Flut verwandeln kann. Tun Sie dies, und die meisten Sperren, die Teams der Anti-Bot-Eskalation zuschreiben, hören einfach auf zu passieren, weil es von Anfang an nie Eskalation war.

Die andere Hälfte ist, einen Ort zu haben, zu dem man ausweichen kann, was residential proxies bieten: einen großen Pool echter, heimischer IPs, sodass eine ausgemusterte Route durch eine saubere ersetzt wird, statt durch dieselbe Adresse, die es erneut versucht. Die Preisgestaltung pro GB ist auch der Grund, warum diszipliniertes Retry-Verhalten sich selbst bezahlt macht, da Sie nur für die Anfragen bezahlen, die Sie tatsächlich stellen, und ein Sturm, den Sie nie senden, Bandbreite ist, die Sie nie kaufen.

Bereit, loszulegen?

Testen Sie Shifters Residential-Proxys, 205M+ IPs, 195+ Länder, ab $0.75/GB.

Jetzt starten