So lösen Sie CaptchaFox in Python mit requests und httpx

solve captchafox in python - How to Solve CaptchaFox in Python With requests and httpx

Um CaptchaFox in Python zu lösen, rufen Sie solver.captchafox() aus dem Paket capskip mit dem sitekey und der Seiten-URL auf, setzen den zurückgegebenen Token in das Formularfeld cf-captcha-response und senden diese Anfrage mit dem User-Agent, der zusammen mit dem Token zurückkam. Am letzten Schritt scheitert Python-Code meistens. requests und httpx geben sich standardmäßig beide im User-Agent-Header selbst zu erkennen, und eine Website, die den Token von dem Browser erwartet, der ihn ausgestellt hat, lehnt diese Anfrage ab. So kann ein Lösevorgang, der einwandfrei funktioniert hat, beim Absenden trotzdem scheitern. CapSkip hat CaptchaFox in Version 1.4.0 hinzugefügt. Dieser Leitfaden behandelt den Schlüssel, den Aufruf, das Absenden, Wiederholungsversuche und das parallele Ausführen mehrerer Lösevorgänge.

Was Sie brauchen

  • CapSkip 1.4.0 oder neuer auf einem Windows-Rechner. Dieses Release hat CaptchaFox hinzugefügt, zusammen mit Friendly Captcha und Capy Puzzle.
  • Python 3.10 oder neuer und Version 1.3.0 oder neuer des Pakets capskip, das erste Release mit einer Methode captchafox(). Die Beispiele verwenden außerdem requests, und der Abschnitt über parallele Lösevorgänge verwendet httpx.
  • Zwei Werte von der Zielseite: der sitekey und die URL der Seite, auf der das Widget läuft. Schritt 1 zeigt, wo der Schlüssel steht und welches Script-Tag Sie sich bei der Gelegenheit ansehen sollten.
  • Eine Adresse für den Solver. Im Local-Modus antwortet CapSkip auf 127.0.0.1 nur für dieses Gerät; im Server-Modus lauscht es auf Ihrer Netzwerkadresse oder öffentlichen IP, damit ein Skript auf einem anderen Rechner es über die API aufrufen kann. Eingestellt werden beide Modi unter Verbindungseinstellungen.
# Quoted, so cmd.exe does not read >= as a redirect
pip install "capskip>=1.3.0" requests httpx

Schritt 1: Den sitekey und die Widget-Quelle auslesen

Der sitekey ist öffentlich, für jeden Besucher gleich und beginnt üblicherweise mit sk_. Die meisten Seiten tragen ihn am Container des Widgets, einem div mit der Klasse captchafox und einem Attribut data-sitekey. Eine Seite, die das Widget aus ihrem eigenen Skript aufbaut, übergibt den Schlüssel stattdessen an einen Aufruf von captchafox.render, und wenn keins von beiden im abgerufenen HTML auftaucht, steht der Schlüssel im Network-Tab: Er ist das Pfadsegment nach /captcha/ in der Anfrage an api.captchafox.com.

Prüfen Sie beim Lesen der Seite auch, welches Skript das Widget lädt. Die meisten Websites laden es von cdn.captchafox.com und bekommen einen einfachen Token. Manche Plattformen binden stattdessen ein Paket von s.uicdn.com/mampkg/ ein, und diese Websites erwarten einen Token, der mit MAM_ beginnt. Wer für die falsche Variante löst, bekommt trotzdem einen Token, allerdings in einem Format, das die Website dann ablehnt. Diese Prüfung erspart Ihnen also einen verwirrenden Nachmittag. Auf MAM-Seiten kann der Schlüssel im src des Skripts selbst stehen, nach ?key=, und dasselbe CDN liefert auch andere, nicht verwandte Pakete aus. Gleichen Sie deshalb den Paketpfad von captchafox ab und nicht den Host.

import re

import requests

PAGE_URL = "https://example.com/signup"
session = requests.Session()
html = session.get(PAGE_URL, timeout=30).text

# The container: <div class="captchafox" data-sitekey="sk_...">
tag = re.search(r'<[^>]*class="(?:[^"]*\s)?captchafox(?:\s[^"]*)?"[^>]*>', html)
key = tag and re.search(r'data-sitekey="([^"]+)"', tag.group(0))
# MAM pages may carry the key in the script src instead.
key = key or re.search(r'captchafox[^"]*/api\.js\?key=([^"&]+)', html)
sitekey = key.group(1) if key else None

# The MAM build expects a MAM_ token; everything else is the default.
uses_mam = "mampkg/@mamdev/core.frontend.libs.captchafox" in html
print(sitekey, uses_mam)

Das Klassenmuster ist durch Leerzeichen begrenzt, damit ein Wrapper-Element mit einer Klasse wie captchafox-container nicht versehentlich passt. Es erwartet doppelte Anführungszeichen um Attributwerte, so wie das eigene Snippet von CaptchaFox sie schreibt.

Schritt 2: Der Aufruf von captchafox()

Um CaptchaFox in Python zu lösen, brauchen Sie eine einzige Methode. Sie nimmt den sitekey und die Seiten-URL sowie optionale Keyword-Argumente entgegen. Für das Standard-Widget braucht sie nur diese beiden.

# pip install "capskip>=1.3.0"
from capskip import CapSkip

solver = CapSkip(host="127.0.0.1", port=8080)

result = solver.captchafox("YOUR_SITEKEY", "https://example.com/signup")

print(result["token"])           # goes in cf-captcha-response
print(result.get("userAgent"))   # send this as the User-Agent

Das Ergebnis ist ein einfaches dict. token und code enthalten dieselbe Zeichenfolge, und token ist nach dem Feld benannt, in das der Wert gehört. userAgent ist die Identität des Browsers, der den Token ausgestellt hat. Das ist der eigene Browser von CapSkip und nichts, was Sie gesendet haben. Dieser Schlüssel ist nur vorhanden, wenn das Lösen einen User-Agent gemeldet hat. Lesen Sie ihn also mit result.get() und nicht mit eckigen Klammern, sonst löst der seltene Lösevorgang ohne ihn einen KeyError aus, und zwar genau in der Zeile, die das Formular hätte absenden sollen.

Die Seiten-URL muss die Seite sein, auf der das Widget wirklich läuft. CaptchaFox registriert jeden Schlüssel für eine Liste erlaubter Domains und prüft den Host, bevor es irgendetwas ausstellt. Ein mit der falschen Seite gesendeter Schlüssel wird deshalb jedes Mal abgelehnt, nie nur sporadisch. Eine Weiterleitung, ein Kurzlink oder ein Suchergebnis reicht nicht.

Optionen, die die Methode annimmt

Übergeben Sie für eine Seite, die das MAM-Paket lädt, den Paketpfad aus ihrem Script-Tag als api_server. Das SDK entfernt jedes Keyword-Argument mit dem Wert None, bevor die Anfrage hinausgeht. Sie können die Option also bei jedem Aufruf übergeben und die Prüfung aus Schritt 1 entscheiden lassen.

# Copied from the script tag on MAM pages.
MAM_PACKAGE = "https://s.uicdn.com/mampkg/@mamdev/core.frontend.libs.captchafox/"

result = solver.captchafox(
    sitekey,
    PAGE_URL,
    # None is dropped, so the standard widget sends nothing extra.
    api_server=MAM_PACKAGE if uses_mam else None,
)

Neben api_server nimmt captchafox() proxy, proxytype und useragent an, dazu timeout und polling_interval pro Aufruf, beide in Sekunden. Die Option useragent wird zur Kompatibilität mit anderen Diensten akzeptiert und bewusst nicht angewendet, denn CapSkip löst in einem echten Browser mit dessen eigener, stimmiger Identität. Jedes andere Keyword, ein leerer sitekey oder eine leere URL, ein proxy-dict ohne type und uri oder ein anderer Proxy-Typ als HTTP, HTTPS, SOCKS5 oder SOCKS5H löst eine ValidationException aus, bevor eine Anfrage gesendet wird.

Schritt 3: Mit dem User-Agent absenden, der den Token ausgestellt hat

Wenn Sie CaptchaFox in Python lösen, entscheidet dieser Schritt darüber, ob die Website den Token akzeptiert. Ohne weitere Einstellung sendet requests als User-Agent python-requests, gefolgt von seiner Versionsnummer, und httpx sendet python-httpx, gefolgt von seiner eigenen. Keins von beiden ist der Browser, der den Token erzeugt hat. Übernehmen Sie den zurückgegebenen Wert in die Anfrage, die den Token trägt.

# session is the one Step 1 fetched the page with, so it carries its cookies.
ua = result.get("userAgent")
resp = session.post(
    PAGE_URL,  # or wherever the form's action attribute points
    data={"email": "YOUR_EMAIL", "cf-captcha-response": result["token"]},
    # Per request, not on session.headers: the next token may differ.
    headers={"User-Agent": ua} if ua else {},
    timeout=30,
)
print(resp.status_code)

Ein an post() übergebener Header wird für diese eine Anfrage über die Standardwerte der Session gelegt. Die Session behält also ihre Cookies, und jede spätere Anfrage geht wie zuvor hinaus. Würden Sie stattdessen session.headers setzen, bekäme jede folgende Anfrage den User-Agent eines einzigen Lösevorgangs, auch das Absenden des nächsten Tokens. Bei httpx rufen Sie die Seite über einen einzigen httpx.Client ab und senden auch darüber ab, damit die Cookies erhalten bleiben, und übergeben data, headers und timeout auf dieselbe Weise an dessen post().

Zwei weitere Regeln ergeben sich daraus, wie CaptchaFox den Token aufseiten der Website prüft. Jeder Token lässt sich nur einmal verifizieren, und das nur innerhalb kurzer Zeit. Lösen Sie also erst, wenn Sie zum Absenden bereit sind, und senden Sie dann sofort ab. Und behandeln Sie den Token als opak: Kürzen Sie ihn nicht, und kodieren oder formatieren Sie ihn nicht um. Manche Websites senden ihn in einem JSON-Body statt als Formular-POST. Senden Sie das Formular also einmal von Hand mit geöffneten DevTools ab und bilden Sie genau nach, was die Seite sendet.

Schritt 4: Wiederholungen, Challenge-Typen und Timeouts

Welche Challenge CaptchaFox ausspielt, können Sie nicht wählen. Bei den meisten Lösevorgängen wird gar nichts angezeigt, weil die Indizien des Browsers von selbst ausreichen, und wenn ein Slider-Puzzle erscheint, erledigt CapSkip es meistens. Bildauswahl- und Audio-Challenges sind selten und werden nicht gelöst: Sie kommen als ApiException zurück, deren Meldung ERROR_CAPTCHA_UNSOLVABLE enthält, und zwar innerhalb von Sekunden statt erst am Ende des Timeouts. Bei einem neuen Versuch kommt meist eine andere Challenge, Sie haben also zwei Möglichkeiten für Wiederholungen.

  • In CapSkip selbst. Im Abschnitt CaptchaFox der Einstellungen finden Sie Retries (0-3), standardmäßig auf 0 gesetzt. Ist der Wert höher, versucht CapSkip es bei nicht unterstützten Challenges, bei Versuchen mit Zeitüberschreitung und bei Browserfehlern von selbst noch einmal mit einer neu ausgespielten Challenge; einen Schlüssel, den die Website ablehnt, versucht es nie erneut. Jede zusätzliche Wiederholung kann einen einzelnen Aufruf um bis zu ein Row Timeout verlängern, standardmäßig 150 Sekunden. Übergeben Sie captchafox() also ein längeres timeout, wenn Sie den Wert erhöhen.
  • In Ihrem Code. Fangen Sie die Exception ab und rufen Sie die Methode erneut auf, wie unten gezeigt. Der einzige Haken: Ein abgelehnter Schlüssel erscheint über die API ebenfalls als unlösbar, daher wird auch ein Schlüssel, der auf der falschen Domain verwendet wird, erneut versucht. Er scheitert bei jedem Versuch innerhalb von Sekunden und gelingt kein einziges Mal, und genau daran erkennen Sie ihn.
from capskip.exceptions import ApiException


def solve_captchafox(sitekey, url, attempts=3, **options):
    for attempt in range(1, attempts + 1):
        try:
            return solver.captchafox(sitekey, url, **options)
        except ApiException as exc:
            # Select, audio and unreadable slide draws come back
            # unsolvable; redraw. Anything else, such as a wrong
            # API key, is final.
            if "UNSOLVABLE" not in str(exc) or attempt == attempts:
                raise

captchafox() pollt mit dem recaptchaTimeout des Clients, standardmäßig 300 Sekunden, denn es handelt sich um eine echte Browser-Sitzung. CapSkip hat zusätzlich eigene Zeitlimits. Eine Aufgabe kann bis zu 250 Sekunden (Wait Timeout) auf einen der 10 CaptchaFox-Threads (Max. Threads) warten, und ein einzelner Versuch bekommt 150 Sekunden (Row Timeout). Steht Retries auf 0 und ist ein Thread frei, erreicht Sie ein gescheiterter Versuch als ApiException von CapSkip, lange bevor die 300 Sekunden des SDK abgelaufen sind; steht die Aufgabe lange in der Warteschlange, kann das SDK sein Limit zuerst erreichen und stattdessen eine TimeoutException auslösen.

Mehrere Tokens gleichzeitig lösen

AsyncCapSkip ist in Python ein echter asyncio-Client und kein Alias, daher führt asyncio.gather mehrere Lösevorgänge parallel aus. Kombinieren Sie ihn mit dem asynchronen Client von httpx, und halten Sie jeden Token bis zum Absenden mit seinem eigenen User-Agent zusammen.

import asyncio

import httpx
from capskip import AsyncCapSkip

solver = AsyncCapSkip(host="127.0.0.1", port=8080)


async def solve_and_submit(client, sitekey, url, form):
    await client.get(url)  # the form's cookies land in client
    result = await solver.captchafox(sitekey, url)
    ua = result.get("userAgent")
    return await client.post(
        url,
        data={**form, "cf-captcha-response": result["token"]},
        headers={"User-Agent": ua} if ua else {},
    )


async def main(jobs):
    async with httpx.AsyncClient(timeout=30) as client:
        return await asyncio.gather(
            *(solve_and_submit(client, *job) for job in jobs),
            return_exceptions=True,
        )

Dabei gelten zwei Grenzen. CapSkip führt standardmäßig 10 CaptchaFox-Lösevorgänge gleichzeitig aus, und die übrigen warten bis zum Wait Timeout von 250 Sekunden auf einen freien Thread. Ein gather über fünfzig Jobs ist bei normalen Lösezeiten also kein Problem; bei größeren Batches erhöhen Sie Max. Threads oder rufen gather für kleinere Gruppen auf. Und CaptchaFox bewertet neben dem Browser auch das Netzwerk, sodass viele Lösevorgänge von einer einzigen Adresse die Challenge-Rate steigen lassen. Konfigurieren Sie Proxys im Abschnitt CaptchaFox von CapSkip oder übergeben Sie bei jedem Aufruf ein proxy-dict mit type und uri, und senden Sie das Formular über denselben Ausgang ab. Mehr zu asyncio-Mustern steht im Leitfaden zum parallelen Lösen von Captchas in Python.

Den Löser auf einer anderen Maschine betreiben

127.0.0.1 ist richtig, solange das Skript und CapSkip auf demselben Windows-PC laufen. Sobald der Python-Code auf einen VPS, in einen Container, auf einen CI-Runner oder in ein gehostetes Notebook umzieht, zeigt Loopback auf den falschen Rechner, und der erste Lösevorgang löst eine NetworkException aus. Schalten Sie CapSkip in den Server-Modus, dann lauscht es auf Ihrer Netzwerkadresse oder öffentlichen IP, sodass jede dieser Umgebungen es über dieselbe API aufrufen kann. Verwenden Sie eine statische öffentliche IP, wenn der Weg über das Internet führt, aktivieren Sie die Validierung des API-Schlüssels und beschränken Sie den Port mit einer Regel in der Windows Firewall auf die Adressen, die Sie erwarten. Der Solver bleibt Ihr eigener Windows-Rechner, und abgerechnet wird pro Lösung weiterhin nichts.

Das SDK liest Umgebungsvariablen nicht von selbst. Lesen Sie CAPSKIP_HOST, CAPSKIP_PORT und CAPSKIP_API_KEY in Ihrem Code aus und übergeben Sie die Werte an den Konstruktor, wie es das vollständige Beispiel tut. So läuft dasselbe Skript an Ihrem Schreibtisch und auf einem Server.

Vollständiges lauffähiges Beispiel

# pip install "capskip>=1.3.0" requests
import os
import re

import requests
from capskip import CapSkip
from capskip.exceptions import (ApiException, CapSkipError,
                                TimeoutException, ValidationException)

PAGE_URL = "https://example.com/signup"
# Copied from the script tag on MAM pages.
MAM_PACKAGE = "https://s.uicdn.com/mampkg/@mamdev/core.frontend.libs.captchafox/"

solver = CapSkip(
    apiKey=os.getenv("CAPSKIP_API_KEY", "capskip"),
    host=os.getenv("CAPSKIP_HOST", "127.0.0.1"),
    port=int(os.getenv("CAPSKIP_PORT", "8080")),
)
session = requests.Session()

html = session.get(PAGE_URL, timeout=30).text
tag = re.search(r'<[^>]*class="(?:[^"]*\s)?captchafox(?:\s[^"]*)?"[^>]*>', html)
key = tag and re.search(r'data-sitekey="([^"]+)"', tag.group(0))
key = key or re.search(r'captchafox[^"]*/api\.js\?key=([^"&]+)', html)
if not key:
    raise SystemExit("No sitekey in the HTML; find it in DevTools.")
api_server = MAM_PACKAGE if "mampkg/@mamdev/core.frontend.libs.captchafox" in html else None

try:
    for attempt in range(1, 4):
        try:
            result = solver.captchafox(key.group(1), PAGE_URL,
                                       api_server=api_server)
            break
        except ApiException as exc:
            # Select, audio and unreadable slide draws come back unsolvable.
            if "UNSOLVABLE" not in str(exc) or attempt == 3:
                raise
            print(f"attempt {attempt}: {exc}")
except ValidationException as exc:
    raise SystemExit(f"not sent: {exc}")
except TimeoutException:
    raise SystemExit("gave up waiting; recaptchaTimeout is 300 seconds")
except CapSkipError as exc:
    # A third unsolvable draw, a refused key, or CapSkip unreachable.
    raise SystemExit(f"solve failed: {exc!r}")

ua = result.get("userAgent")
resp = session.post(
    PAGE_URL,  # or wherever the form's action attribute points
    data={"email": "YOUR_EMAIL", "cf-captcha-response": result["token"]},
    headers={"User-Agent": ua} if ua else {},
    timeout=30,
)
print(resp.status_code, "UA sent:", bool(ua))

Wenn das Lösen bei jedem Durchlauf sofort scheitert, prüfen Sie zuerst die Seiten-URL, denn ein Schlüssel, der außerhalb seiner registrierten Domains verwendet wird, scheitert jedes Mal auf dieselbe Weise. Findet die Regex nichts, baut die Seite das Widget per Skript auf, und der Schlüssel steht im render-Aufruf oder im Network-Tab, wie in Schritt 1 beschrieben. Dokumentiert ist der rohe Endpunkt hinter dieser Methode in der CaptchaFox-API-Referenz.

Häufige Fehler und was sie bedeuten

Was Sie sehenUrsacheBeheben
Die Website lehnt einen Token ab, den CapSkip als gelöst zurückgegeben hatDas Absenden ging als python-requests oder python-httpx hinaus, nicht als der Browser, der den Token ausgestellt hatSenden Sie result.get("userAgent") als User-Agent-Header mit dieser Anfrage
Abgelehnt, obwohl der User-Agent stimmtDie Seite lädt das MAM-Paket, und das Lösen hat das Standard-Widget verwendet, oder umgekehrtLesen Sie das Script-Tag und setzen Sie api_server passend dazu
Ein KeyError bei userAgentDas Lösen hat keinen User-Agent gemeldet, und der Schlüssel ist nur vorhanden, wenn es einen gemeldet hatLesen Sie ihn mit result.get() und senden Sie den Header nur, wenn ein Wert vorhanden ist
Eine ApiException sofort und jedes Mal, bei einem bestimmten SchlüsselDie Seiten-URL liegt außerhalb der Domains, für die der Schlüssel registriert ist, oder der Schlüssel selbst ist falschSenden Sie die Seite, auf der das Widget läuft, keine Weiterleitung und kein Suchergebnis, und prüfen Sie den Schlüssel erneut
Gelegentlich eine ApiException mit ERROR_CAPTCHA_UNSOLVABLECaptchaFox hat eine Bildauswahl- oder Audio-Challenge ausgespielt oder eine Slider-Variante, die CapSkip nicht lesen konnteWiederholen Sie im Code, oder erhöhen Sie Retries in den CaptchaFox-Einstellungen von CapSkip
Ein Token, der einmal funktioniert hat, scheitert beim zweiten MalJeder Token lässt sich nur einmal verifizieren und läuft schnell abLösen Sie für jedes Absenden einen neuen Token und senden Sie sofort ab
Mit fortschreitendem Durchlauf erst mehr Challenges, dann AblehnungenJedes Lösen kommt von einer einzigen Adresse, und CaptchaFox bewertet das NetzwerkVerteilen Sie die Lösungen auf einen Proxy-Pool und senden Sie über denselben Ausgang ab
ValidationException, bevor überhaupt etwas gesendet wirdEin leerer sitekey oder eine leere URL, ein Keyword-Argument, das die Methode nicht annimmt, oder ein Proxy-Typ, den CapSkip nicht akzeptiertPrüfen Sie, ob der sitekey gefunden wurde, und korrigieren oder entfernen Sie das Argument, das die Meldung nennt
NetworkException beim ersten AufrufCapSkip läuft nicht, oder Host und Port sind falschStarten Sie CapSkip und prüfen Sie dann, ob es im Local-Modus oder im Server-Modus laufen soll

FAQ

Unterscheidet sich result["code"] von result["token"]?

Nein, bei CaptchaFox ist es dieselbe Zeichenfolge. code ist das Feld, das jede CapSkip-Methode füllt, damit älterer Code unverändert weiter funktioniert, und token ist der Name, der zu dem passt, was das Formular erwartet. Verwenden Sie in neuem Code token, damit er sich wie das Feld liest, das er füllt.

Kann ich den Token in einer Playwright- oder Selenium-Sitzung verwenden?

Ja, solange das Absenden mit dem User-Agent hinausgeht, den CapSkip zurückgegeben hat. Playwright legt den User-Agent beim Erstellen eines Kontexts fest. Lösen Sie also zuerst, öffnen Sie dann den Kontext mit browser.new_context(user_agent=ua), laden Sie das Formular, schreiben Sie den Token in das Feld cf-captcha-response und senden Sie ab. In Selenium mit Chrome fügen Sie den Chrome-Optionen vor dem Start des Drivers den Schalter user-agent mit diesem Wert hinzu, oder Sie stellen eine laufende Sitzung mit driver.execute_cdp_cmd("Network.setUserAgentOverride", {"userAgent": ua}) um. Wenn Ihre Automatisierung sonst keinen Browser braucht, ist der oben gezeigte Weg mit requests einfacher.

Kann ein Python-Skript auf einer gehosteten Plattform den Solver erreichen?

Ja. Schalten Sie CapSkip in den Verbindungseinstellungen in den Server-Modus, damit es auf einer Netzwerkadresse statt auf Loopback lauscht, lesen Sie diese Adresse in Ihrem Skript aus CAPSKIP_HOST und übergeben Sie sie an CapSkip(). Ein VPS, ein Container-Host, ein CI-Runner und ein gehostetes Notebook verbinden sich alle über dieselbe HTTP-API. Verwenden Sie eine statische öffentliche IP und eine Firewall-Regel, wenn der Weg über das Internet führt. Der Solver bleibt auf Hardware, die Ihnen gehört, an der Art, wie Lösungen gezählt werden, ändert sich also nichts.

Worin unterscheidet sich das von der C#-Version?

Der Aufruf und die Regeln sind gleich; die Fallen sind andere. In C# sendet HttpClient überhaupt keinen User-Agent, solange Sie keinen hinzufügen. In Python senden beide gängigen Clients stattdessen ihren eigenen Namen, python-requests oder python-httpx, und den kann eine Website genauso leicht ablehnen. Wie es auf der .NET-Seite aussieht, zeigt der C#-Leitfaden zu CaptchaFox.

Die Kurzfassung

Um CaptchaFox in Python zu lösen, lesen Sie den sitekey aus dem Container mit der Klasse captchafox, aus dem render-Aufruf oder aus dem Network-Tab und achten darauf, ob die Seite das MAM-Paket lädt. Rufen Sie solver.captchafox() mit dem sitekey und der echten Seiten-URL auf und fügen Sie api_server nur für MAM-Seiten hinzu. Senden Sie result["token"] in cf-captcha-response mit result.get("userAgent") als User-Agent-Header ab, einmal und sofort. Versuchen Sie es bei unlösbaren Challenges erneut, fügen Sie Proxys hinzu, wenn das Volumen wächst, und wechseln Sie in den Server-Modus, sobald das Skript den Rechner des Solvers verlässt.

Nach einer Bildauswahl-Challenge neu zu lösen ist die einzige Gewohnheit, die dieser Typ verlangt, und da ein lokaler Captcha-Löser auf Ihrem eigenen Rechner läuft, kostet jeder erneute Versuch ein paar Sekunden statt einer weiteren abgerechneten Lösung.