So lösen Sie Captchas in Browser Use mit einem eigenen Tool

Um Captchas in Browser Use in Ihrem eigenen Browser zu lösen, registrieren Sie ein eigenes Tool, das den sitekey des Widgets von der Seite liest, bei CapSkip einen Token anfordert und ihn in das Formular schreibt, und teilen dem Agenten dann in seiner Systemnachricht mit, dass es dieses Tool gibt. Damit ist die Captcha-Behandlung in Browser Use auf einem lokalen Chromium abgedeckt, bis auf zwei Limits, die beide standardmäßig bei 180 Sekunden liegen und angehoben werden müssen, weil ein reCAPTCHA-Lösevorgang länger dauern kann als jedes der beiden. Der Teil mit der Systemnachricht ist nicht optional. Der Standard-System-Prompt von Browser Use sagt dem Modell, dass Captchas automatisch gelöst werden. Das stimmt auf den Cloud-Browsern von Browser Use und ist auf einem lokalen Chromium falsch, ohne die Systemnachricht wartet der Agent also auf eine Lösung, die nie kommt. Dieser Leitfaden baut das Captcha-Tool für Browser Use Schritt für Schritt auf, geprüft mit Browser Use 0.13.10.
Was Sie brauchen
- CapSkip auf einem Windows-Rechner. Das Tool unten verarbeitet reCAPTCHA v2, einschließlich unsichtbarer und Enterprise-Widgets, sowie das Cloudflare-Turnstile-Widget.
- Python 3.11 oder neuer, wie es Browser Use voraussetzt, mit browser-use und Version 1.3.0 oder neuer des Pakets capskip. Browser Use steuert einen Chrome oder Chromium, den es auf dem Rechner findet.
- Ein API-Schlüssel für das Chat-Modell, das Sie dem Agenten geben; für Claude setzen Sie ihn als ANTHROPIC_API_KEY. Die Beispiele verwenden Claude Opus 5.5 über ChatAnthropic mit eingeschaltetem adaptivem Thinking, und dieses Argument ist wichtig: Ohne dieses Argument erzwingt Browser Use 0.13.10 die Tool-Auswahl des Modells, was Claude Opus 5.5 und Sonnet 5.5 ablehnen, sodass jeder Schritt scheitert.
- 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 Agent 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 browser-use "capskip>=1.3.0"
Warum ignoriert Browser Use Captchas in einem lokalen Browser?
Weil es so angewiesen wurde. Die Browser-Regeln im System-Prompt, den Browser Use mit seinen Standardeinstellungen verwendet, enthalten die Zeile "CAPTCHAs are automatically solved by the browser" (Captchas werden vom Browser automatisch gelöst), gefolgt von der Anweisung, nicht zu versuchen, sie von Hand zu lösen. Das beschreibt die Cloud-Browser von Browser Use, die Captchas in ihrem eigenen Proxy lösen und das der Bibliothek melden. Die Bibliothek hat einen passenden Watchdog, eingeschaltet über die Einstellung captcha_solver auf BrowserProfile (standardmäßig aktiv), der den Agenten pausiert, während ein Cloud-Browser löst. Er lauscht nur auf Events, die diese Cloud-Browser senden.
Auf einem Chromium auf Ihrem eigenen Rechner kommt nie ein solches Event an. Der Agent sieht das Widget, glaubt den Regeln und wartet, scrollt oder versucht einen anderen Weg, bis ihm die Schritte ausgehen. Endet ein Lauf so, schlägt Browser Use vor, auf seine Cloud-Browser umzusteigen. Die Alternative, wenn Sie den Browser auf Ihrer eigenen Hardware haben wollen: Geben Sie dem Agenten ein Tool, das das Widget wirklich löst, und korrigieren Sie die Regel, die ihm vorgegeben wurde.
Schritt 1: Ein solve_captcha-Tool registrieren
Eigene Tools sind async-Funktionen, die mit dem Decorator tools.action auf einer Tools-Instanz registriert werden. Browser Use injiziert spezielle Parameter anhand ihres Namens: browser_session liefert Ihnen die laufende Sitzung und page_url die Adresse der aktuellen Seite. Das Tool braucht zwei kleine JavaScript-Stücke, eines, um das Widget zu finden, und eines, um den Token einzusetzen.
FIND = """() => {
const w = document.querySelector(
'.g-recaptcha[data-sitekey], .cf-turnstile[data-sitekey]');
if (!w) return null;
return {
kind: w.classList.contains('cf-turnstile') ? 'turnstile' : 'recaptcha',
sitekey: w.dataset.sitekey,
invisible: w.dataset.size === 'invisible' || w.tagName !== 'DIV',
enterprise: !!document.querySelector(
'script[src*="recaptcha/enterprise.js"]'),
callback: w.dataset.callback || null,
};
}"""
FILL = """(kind, token, callback) => {
const name = kind === 'turnstile' ? 'cf-turnstile-response'
: 'g-recaptcha-response';
const fields = document.querySelectorAll(`[name="${name}"]`);
fields.forEach(f => { f.value = token; });
if (callback && typeof window[callback] === 'function') {
window[callback](token);
}
return fields.length;
}"""Beide sind als Arrow-Funktionen geschrieben, weil die evaluate-Methode des Page-Objekts nichts anderes akzeptiert. Die Methode übergibt zusätzliche Argumente als JSON und gibt immer einen String zurück: Ein Objekt kommt JSON-kodiert zurück, eine Zahl als ihre Ziffern und null als leerer String. FILL schreibt den Token in das Antwortfeld, das das Widget angelegt hat, und ruft die in data-callback genannte Funktion auf, falls das Widget eine deklariert, denn manche Formulare warten auf diesen Callback, statt das Feld auszulesen.
FIND liest außerdem zwei Dinge aus, von denen das Lösen abhängt. Ein an einen Button gebundenes Widget ist auch ohne data-size-Attribut unsichtbar, daher gilt jedes g-recaptcha-Element, das kein div ist, als unsichtbar. Und eine Seite, die das Skript enterprise.js von Google lädt, wird als reCAPTCHA Enterprise gelöst, denn Enterprise-Widgets verwenden dasselbe Markup wie die Standard-Widgets.
@tools.action(
"Solve the reCAPTCHA v2 or Cloudflare Turnstile widget on the current "
"page. Call it after the other fields are filled, then submit the form "
"unless the page has already moved on."
)
async def solve_captcha(browser_session: BrowserSession, page_url: str):
page = await browser_session.must_get_current_page()
raw = await page.evaluate(FIND)
widget = json.loads(raw) if raw else None
if not widget:
return ActionResult(error="No reCAPTCHA or Turnstile widget found.")
try:
if widget["kind"] == "turnstile":
result = await solver.turnstile(widget["sitekey"], page_url)
else:
extra = {"invisible": 1} if widget["invisible"] else {}
result = await solver.recaptcha(
widget["sitekey"], page_url,
enterprise=int(widget["enterprise"]), **extra)
except CapSkipError as exc:
return ActionResult(error=f"CapSkip did not solve it: {exc!r}")
filled = await page.evaluate(
FILL, widget["kind"], result["code"], widget["callback"])
if filled == "0":
return ActionResult(error="Solved, but no response field to fill.")
return ActionResult(
extracted_content=f"Solved the {widget['kind']} CAPTCHA on {page_url} "
"and filled in the token. Submit the form now, "
"unless the page has already moved on.",
)Den Beschreibungs-String liest das Modell, wenn es entscheidet, welche Aktion es ausführt. Er sagt deshalb, wann das Tool aufzurufen ist, und nicht nur, was es tut. Die Erfolgsmeldung gehört allein in extracted_content. Setzt ein ActionResult zusätzlich long_term_memory, zeigt Browser Use dem Modell diesen Memory-Wert und verwirft den Content, sodass eine Anweisung wie "Submit the form now" (Formular jetzt absenden) im Content nie ankommt. Jeder Fehlschlag kommt als ActionResult mit einer Fehlermeldung zurück, die das Modell lesen und auf die es reagieren kann, statt als Exception.
Verwenden Sie hier AsyncCapSkip, nicht den synchronen Client CapSkip. Browser Use betreibt die Browser-Verbindung auf demselben Event-Loop wie Ihr Tool, und ein blockierender Lösevorgang würde das alles einfrieren, solange er dauert. In Python ist AsyncCapSkip ein echter asyncio-Client und kein Alias.
Schritt 2: Dem Agenten mitteilen, dass es das Tool gibt
Übergeben Sie die Tools an den Agenten und ergänzen Sie seine Systemnachricht um einen Absatz. extend_system_message wird hinter den Standard-Prompt angehängt und steht damit nach der Regel, die es korrigieren soll.
EXTRA = (
"This browser does not solve CAPTCHAs on its own, whatever the rules "
"above say. When a page shows a reCAPTCHA or Turnstile widget, fill in "
"the other fields, call solve_captcha, then submit the form unless the "
"page has already moved on. Never click the CAPTCHA checkbox or "
"challenge yourself."
)
agent = Agent(
task="Sign up at https://example.com/signup with YOUR_EMAIL.",
llm=ChatAnthropic(model="claude-opus-5-5", thinking={"type": "adaptive"}),
tools=tools,
extend_system_message=EXTRA,
step_timeout=420,
)Die Reihenfolge in diesem Absatz ist wichtig. Ein reCAPTCHA-Token ist nur etwa zwei Minuten gültig, wie aus dem Leitfaden zum Ablaufen von reCAPTCHA-Tokens hervorgeht, und jeder Modellschritt dauert Sekunden. Wer zuerst löst und danach ein langes Formular ausfüllt, riskiert, dass der Token vor dem Absenden abläuft, deshalb wird der Agent angewiesen, zuletzt zu lösen. Ein Modell kann alle drei Dinge in einem einzigen Schritt erledigen, also tippen, lösen und auf Absenden klicken, und Browser Use führt die Aktionen eines Schritts der Reihe nach aus. Der Zusatz, dass die Seite schon weitergegangen sein könnte, ist für unsichtbare Widgets gedacht. Ihr Callback sendet das Formular meist selbst ab, sodass die Seite schon weitergegangen ist, wenn FILL ihn aufgerufen hat, und ein zweiter Klick nur scheitern würde.
Das Argument thinking an ChatAnthropic ist keine Dekoration. Browser Use fragt Claude über einen Tool-Aufruf nach seiner nächsten Aktion, und in Version 0.13.10 erzwingt es ohne thinking diese Tool-Auswahl. Claude Opus 5.5 und Sonnet 5.5 lehnen eine erzwungene Tool-Auswahl mit Status 400 ab, der Agent würde also bei jedem Schritt scheitern. Mit eingeschaltetem adaptivem Thinking lässt Browser Use das Modell das Tool wählen, und die Anfrage geht durch.
Schritt 3: Die beiden 180-Sekunden-Limits anheben
Ein Captcha-Lösevorgang in Browser Use muss in zwei getrennte Zeitfenster passen, und beide stehen standardmäßig auf 180 Sekunden.
- Das Limit pro Aktion. Jede Aktion ist in ein Timeout eingepackt, das aus der Umgebungsvariable BROWSER_USE_ACTION_TIMEOUT_S gelesen wird, und der Agent übergibt nie einen eigenen Wert. Die Variable wird einmal gelesen, wenn Browser Use sein tools-Modul zum ersten Mal lädt, was jeder Import von Agent oder Tools auslöst. Sie danach zu setzen hat daher keine Wirkung.
- Das Schritt-Timeout. Der Parameter step_timeout von Agent deckt einen ganzen Schritt ab: das Vorbereiten des Seitenzustands, den Modellaufruf, dem Browser Use selbst je nach Modell bis zu 90 Sekunden gibt, und jede Aktion im Schritt.
Auf der anderen Seite pollt das SDK ein reCAPTCHA bis zu 300 Sekunden lang (recaptchaTimeout), und die eigenen reCAPTCHA-Einstellungen von CapSkip erlauben einer Aufgabe bis zu 250 Sekunden Wartezeit auf einen Thread und weitere 250 zum Lösen. Die meisten Lösevorgänge sind weit früher fertig, aber eine Warteschlange oder ein langsamer Proxy kann einen Lösevorgang auf über 180 Sekunden bringen. Stehen beide Limits auf ihren Standardwerten, greift zuerst das Schritt-Timeout, weil der Schritt vor der Aktion begonnen hat, und der Agent meldet, dass der Schritt nach 180 Sekunden abgelaufen ist. Erhöhen Sie nur step_timeout, übernimmt das Limit pro Aktion: Es bricht das Lösen mitten im Polling ab und meldet, der Browser reagiere möglicherweise nicht, unter Verweis auf einen toten CDP-WebSocket. Diese Meldung führt hier in die Irre. Dem Browser fehlt nichts; das Lösen hat einfach länger gedauert als das Limit. Setzen Sie beide Limits höher als das Limit des SDK.
import os
# Before anything imports Agent or Tools from browser_use.
os.environ.setdefault("BROWSER_USE_ACTION_TIMEOUT_S", "330")
from browser_use import Agent # noqa: E402
# Up to 300 s of SDK polling (a few more for the last poll), one
# model call (90 s for Claude) and the page state, with room to spare.
agent = Agent(task="...", llm=llm, tools=tools,
extend_system_message=EXTRA, step_timeout=420)Ein abgelaufener Schritt zählt außerdem als einer der aufeinanderfolgenden Fehlschläge des Agenten, und fünf in Folge stoppen den Agenten. Ein zu knappes Limit kostet also mehr als einen erneuten Versuch.
CapSkip auf einem Server betreiben
Das Tool läuft in Ihrem Python-Prozess, neben dem Agenten. Entscheidend ist, wo dieser Prozess läuft, nicht wo der Browser ist: Selbst wenn die cdp_url der Sitzung auf einen Chrome auf einem anderen Rechner zeigt, läuft die Lösungsanfrage trotzdem von Ihrem Skript zu CapSkip. Solange Skript und CapSkip auf demselben Windows-PC liegen, ist 127.0.0.1 richtig. Zieht der Agent auf einen VPS, einen CI-Runner oder einen geplanten Job auf einer anderen Maschine um, zeigt Loopback auf den falschen Rechner, und das Tool gibt eine NetworkException als Fehler zurück. Schalten Sie CapSkip in den Server-Modus, dann lauscht es auf Ihrer Netzwerkadresse oder öffentlichen IP, sodass der Agent 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. Der Solver bleibt auf Ihrem eigenen Windows-Rechner, und pro Lösung wird weiterhin nichts abgerechnet, ganz gleich, wie viele Captchas der Agent antrifft.
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 AsyncCapSkip, wie es das vollständige Beispiel tut.
Vollständiges lauffähiges Beispiel
# pip install browser-use "capskip>=1.3.0"
import asyncio
import json
import os
# Browser Use reads this once, when its tools load, so set it first.
os.environ.setdefault("BROWSER_USE_ACTION_TIMEOUT_S", "330")
from browser_use import ActionResult, Agent, BrowserSession, ChatAnthropic, Tools
from capskip import AsyncCapSkip, CapSkipError
solver = AsyncCapSkip(
apiKey=os.getenv("CAPSKIP_API_KEY", "capskip"),
host=os.getenv("CAPSKIP_HOST", "127.0.0.1"),
port=int(os.getenv("CAPSKIP_PORT", "8080")),
)
tools = Tools()
FIND = """() => {
const w = document.querySelector(
'.g-recaptcha[data-sitekey], .cf-turnstile[data-sitekey]');
if (!w) return null;
return {
kind: w.classList.contains('cf-turnstile') ? 'turnstile' : 'recaptcha',
sitekey: w.dataset.sitekey,
invisible: w.dataset.size === 'invisible' || w.tagName !== 'DIV',
enterprise: !!document.querySelector(
'script[src*="recaptcha/enterprise.js"]'),
callback: w.dataset.callback || null,
};
}"""
FILL = """(kind, token, callback) => {
const name = kind === 'turnstile' ? 'cf-turnstile-response'
: 'g-recaptcha-response';
const fields = document.querySelectorAll(`[name="${name}"]`);
fields.forEach(f => { f.value = token; });
if (callback && typeof window[callback] === 'function') {
window[callback](token);
}
return fields.length;
}"""
@tools.action(
"Solve the reCAPTCHA v2 or Cloudflare Turnstile widget on the current "
"page. Call it after the other fields are filled, then submit the form "
"unless the page has already moved on."
)
async def solve_captcha(browser_session: BrowserSession, page_url: str):
page = await browser_session.must_get_current_page()
raw = await page.evaluate(FIND)
widget = json.loads(raw) if raw else None
if not widget:
return ActionResult(error="No reCAPTCHA or Turnstile widget found.")
try:
if widget["kind"] == "turnstile":
result = await solver.turnstile(widget["sitekey"], page_url)
else:
extra = {"invisible": 1} if widget["invisible"] else {}
result = await solver.recaptcha(
widget["sitekey"], page_url,
enterprise=int(widget["enterprise"]), **extra)
except CapSkipError as exc:
return ActionResult(error=f"CapSkip did not solve it: {exc!r}")
filled = await page.evaluate(
FILL, widget["kind"], result["code"], widget["callback"])
if filled == "0":
return ActionResult(error="Solved, but no response field to fill.")
return ActionResult(
extracted_content=f"Solved the {widget['kind']} CAPTCHA on {page_url} "
"and filled in the token. Submit the form now, "
"unless the page has already moved on.",
)
EXTRA = (
"This browser does not solve CAPTCHAs on its own, whatever the rules "
"above say. When a page shows a reCAPTCHA or Turnstile widget, fill in "
"the other fields, call solve_captcha, then submit the form unless the "
"page has already moved on. Never click the CAPTCHA checkbox or "
"challenge yourself."
)
async def main():
agent = Agent(
task="Sign up at https://example.com/signup with YOUR_EMAIL, "
"then report what the page says.",
# Adaptive thinking lets Browser Use leave the tool choice to Claude.
llm=ChatAnthropic(model="claude-opus-5-5", thinking={"type": "adaptive"}),
tools=tools,
extend_system_message=EXTRA,
step_timeout=420,
)
history = await agent.run(max_steps=25)
print(history.final_result())
asyncio.run(main())Wir haben diese Schleife von Anfang bis Ende gegen Testseiten für ein Checkbox-Widget, ein an einen Button gebundenes unsichtbares Widget, eine Enterprise-Seite und ein Turnstile-Widget laufen lassen, mit einem geskripteten Ersatz für das Modell, damit jeder Schritt vorhersagbar war. Der Prompt kommt mit dem zusätzlichen Absatz nach den Standardregeln an, solve_captcha erscheint unter den Aktionen, die das Modell wählen kann, der Token landet im Formular, die data-callback-Funktion wird ausgelöst, die Anweisung des Tools erreicht das Modell, und das Absenden wird akzeptiert. Außerdem haben wir die Anfrage mitgeschnitten, die ChatAnthropic sendet, um zu bestätigen, dass adaptives Thinking die Tool-Auswahl dem Modell überlässt. Mit einem echten Modell besteht der einzige Unterschied darin, dass das Modell entscheidet, wann es das Tool aufruft, und genau dafür sind die Beschreibung und der zusätzliche Absatz da. Die rohen Endpunkte hinter beiden Methoden finden Sie in der API-Referenz.
Häufige Fehler und was sie bedeuten
| Was Sie sehen | Ursache | Beheben |
|---|---|---|
| Auf einer Seite mit Captcha wartet oder scrollt der Agent oder gibt auf, und das Tool ruft er nie auf | Der Standard-System-Prompt sagt, Captchas würden automatisch gelöst, und nichts hat das korrigiert | Übergeben Sie extend_system_message mit dem Absatz aus Schritt 2 |
| Jeder Schritt scheitert mit Status 400 und der Meldung, der tool_choice-Typ werde für das Modell nicht unterstützt | ChatAnthropic wurde ohne thinking erzeugt, daher hat Browser Use die Tool-Auswahl erzwungen | Übergeben Sie thinking={"type": "adaptive"} an ChatAnthropic |
| Ein Schritt ist nach 180 Sekunden abgelaufen | Ein langsamer Lösevorgang plus der Modellaufruf haben step_timeout überschritten | Übergeben Sie step_timeout=420 an Agent und erhöhen Sie auch das Limit pro Aktion |
| Fehlermeldung: Action solve_captcha timed out after 180s. The browser may be unresponsive (dead CDP WebSocket). | Nach dem Erhöhen von step_timeout hat das Lösen das Limit pro Aktion überschritten; dem Browser fehlt nichts | Setzen Sie BROWSER_USE_ACTION_TIMEOUT_S auf über 300, bevor Browser Use geladen wird |
| Die Variable ist gesetzt, und das Limit liegt trotzdem bei 180 Sekunden | Sie wurde gesetzt, nachdem Agent oder Tools bereits importiert waren | Verschieben Sie die Zuweisung an den Anfang des Einstiegsskripts, oberhalb jedes Imports, der browser_use einbindet |
| Der ganze Agent friert ein, während ein Captcha gelöst wird | Der synchrone Client CapSkip blockiert den Event-Loop, auf dem die Browser-Verbindung läuft | Verwenden Sie AsyncCapSkip und rufen Sie seine Methoden mit await auf |
| Das Tool meldet, dass kein Widget gefunden wurde | Die Seite rendert das Widget per Skript ohne data-sitekey, legt es in einen iframe oder verwendet ein anderes Captcha | Lesen Sie den sitekey in den DevTools aus der eigenen Anfrage des Widgets und erweitern Sie FIND und FILL für diese Seite; beide laufen im Top-Level-Dokument, ein Formular in einem iframe braucht also eine eigene Suche |
| Fehlermeldung: Solved, but no response field to fill | Das Turnstile-Widget benennt sein Feld mit data-response-field-name um oder schaltet es mit data-response-field ab | Lesen Sie dieses Attribut in FIND aus und schreiben Sie den Token in das genannte Feld |
| Der Token ist eingesetzt, und die Website lehnt das Absenden trotzdem ab | Der Token ist vor dem Absenden abgelaufen, oder das Formular wartet auf einen Callback, den es per Skript registriert hat | Lassen Sie den Agenten direkt vor dem Absenden lösen, und rufen Sie den eigenen Callback der Seite auf, wenn data-callback leer ist |
| Die Seite verwendet reCAPTCHA v3 auf einem Button | FIND behandelt es als v2 | Rufen Sie solver.recaptcha mit Version v3 und der Action der Seite auf |
| Der Fehler des Tools ist eine NetworkException | CapSkip läuft nicht, oder Host und Port passen nicht zu dem Rechner, auf dem der Agent läuft | Starten Sie CapSkip und prüfen Sie dann, ob es im Local-Modus oder im Server-Modus laufen soll |
FAQ
Löst Browser Use Captchas selbst?
Nur auf seinen Cloud-Browsern, wo das Lösen im eigenen Proxy von Browser Use passiert und die Bibliothek darauf wartet. Die Open-Source-Bibliothek liefert nichts mit, das ein Captcha in einem Browser löst, den Sie selbst betreiben, egal ob es sich um einen lokalen Chromium handelt oder um Ihren eigenen Chrome, den Sie über eine CDP-URL erreichen. Genau für dieses Setup ist dieser Leitfaden gedacht.
Kann ich dem Agenten stattdessen den MCP-Server von CapSkip geben?
Das geht. Browser Use kann die Tools eines MCP-Servers in seine Tools-Instanz laden, und der MCP-Server von CapSkip bietet für jeden unterstützten Typ ein Tool zum Lösen. Diese Tools geben allerdings den Token zurück, das Modell muss ihn also danach selbst mit einem eigenen Skript in die Seite schreiben. Das sind zwei Entscheidungen für das Modell statt einer, und die zweite muss zum Markup jeder einzelnen Seite passen. Das eigene Tool hält das Lesen und Schreiben der Seite im Code. Der MCP-Weg eignet sich für Agenten, denen Sie keinen Code hinzufügen können, und die MCP-Captcha-Solver-Seite zeigt, wie Sie einen solchen Agenten anbinden.
Was ist mit hCaptcha oder einer ganzseitigen Cloudflare-Challenge?
CapSkip löst kein hCaptcha, deshalb erfasst FIND nur die Klassen von reCAPTCHA und Turnstile und nie ein h-captcha-Widget. Eine ganzseitige Cloudflare-Challenge ist ein anderer Ablauf als das Turnstile-Widget: Hier braucht es die Werte cData und chlPageData der Challenge und den User-Agent, der mit dem Token zurückkommt, wie die Cloudflare-Turnstile-Löser-Seite erklärt. Dieses Tool deckt diesen Fall in der vorliegenden Form daher nicht ab. Weitere CapSkip-Typen wie GeeTest oder Capy Puzzle lassen sich als zusätzliche Zweige im selben Tool ergänzen.
Kann ein Agent, der in der Cloud läuft, meinen 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 dort, wo der Agent läuft, aus CAPSKIP_HOST und übergeben Sie sie an AsyncCapSkip. Ein VPS, ein Container-Host, ein CI-Runner und ein geplanter Job auf einer Cloud-Plattform 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, daher kostet ein langer Agent-Lauf, der auf jeder Seite auf ein Captcha trifft, nichts zusätzlich.
Die Kurzfassung
Die Captcha-Behandlung in Browser Use im eigenen Browser läuft auf vier Änderungen hinaus, dazu eine fünfte, sobald der Agent den Rechner des Solvers verlässt. Registrieren Sie ein solve_captcha-Tool, das den sitekey mit page.evaluate liest, AsyncCapSkip mit await aufruft und den Token zurückschreibt und dabei den Callback des Widgets aufruft, falls es einen hat. Korrigieren Sie die Standardregel mit extend_system_message, damit der Agent das Tool direkt vor dem Absenden aufruft. Übergeben Sie adaptives Thinking an ChatAnthropic, damit Claude die Anfrage akzeptiert. Erhöhen Sie BROWSER_USE_ACTION_TIMEOUT_S, bevor Browser Use geladen wird, und step_timeout von Agent, beide über die 300 Sekunden des SDK. Und schalten Sie CapSkip in den Server-Modus, wenn der Agent irgendwo anders läuft als auf dem Rechner des Solvers.
- Alle Captcha-Typen, die das Python-Paket verarbeitet, finden Sie auf der Python-Captcha-Solver-Seite.
- Wie die Checkbox- und die unsichtbaren Widgets funktionieren: die reCAPTCHA-v2-Solver-Seite.
Ein Agent, der stundenlang surft, kann auf jeder zweiten Seite auf eine Challenge treffen, und eine Captcha-Umgehung auf Ihrem eigenen Windows-Rechner löst jede davon ohne Gebühr pro Lösung.
