Captchas in Retool Workflows lösen (REST-Blöcke)

retool workflows captcha - How to Solve CAPTCHAs in Retool Workflows (REST Blocks)

Ein Captcha-Lösevorgang in Retool Workflows besteht aus drei Blöcken: absenden, warten, lesen. Bauen Sie sie als REST resource query block statt als JavaScript- oder Python-code block, denn Retool führt code blocks in einem separaten, per Sandbox abgeschotteten Dienst aus, dessen Standard-Firewallregeln private Adressen ablehnen. Eine resource query ist Konfiguration statt eigener Code, sie läuft also nicht über diesen Dienst und erreicht einen Solver in Ihrem eigenen Netzwerk ganz ohne diese Diskussion.

Was Sie brauchen

  • Eine Retool-Organisation mit Workflows, auf Retool Cloud oder selbst gehostet. Beides funktioniert, mit unterschiedlicher Netzwerkkonfiguration.
  • CapSkip läuft auf einem Windows-Rechner. Local-Modus, wenn auf diesem Rechner auch ein selbst gehostetes Retool läuft, in jedem anderen Fall Server-Modus.
  • Der sitekey und die Seiten-URL der Challenge, die Sie lösen.
  • Ein Ort für den API-Schlüssel. Retool Secrets sind aus code blocks und aus der Resource-Konfiguration erreichbar, es muss also nichts in einen Block eingefügt werden.

CapSkip spricht auf Port 8080 die 2captcha-kompatible API, Retool braucht also keinen Connector und keine eigene Integration. Es ist eine ganz normale REST-Resource, die auf einen Rechner zeigt, der Ihnen gehört.

Schritt 1: eine REST-Resource auf den Solver richten

Legen Sie eine REST-API-Resource mit der Basis-URL des Rechners an, auf dem CapSkip läuft. Lassen Sie die Authentifizierung leer. Der API-Schlüssel wird bei jeder Anfrage als ganz normaler Parameter mitgeschickt, so funktioniert das 2captcha-kompatible Protokoll.

# Base URL for the resource. Loopback only works when Retool
# is self-hosted on the same Windows box as the solver.
http://127.0.0.1:8080

# Server mode, which is what you want everywhere else.
http://192.168.1.40:8080

Jeder Workflow, der etwas löst, nutzt danach diese eine Resource weiter. Zwei Query-Blöcke reichen für die gesamte Aufgabe.

Schritt 2: die Challenge absenden

Fügen Sie einen resource query block hinzu, nennen Sie ihn submitCaptcha, setzen Sie den Action-Typ auf POST und den Pfad auf den Submit-Endpunkt. Der Body ist ein kleines JSON-Objekt.

{
  "key": "YOUR_KEY",
  "method": "userrecaptcha",
  "googlekey": "YOUR_SITEKEY",
  "pageurl": "https://example.com/page-with-recaptcha",
  "json": 1
}

Die Antwort enthält die id, mit der Sie abfragen.

{ "status": 1, "request": "2122988149" }

Dieser Body ist reCAPTCHA v2. Die anderen Typen, die CapSkip unterstützt, sind derselbe Aufruf mit anderen Parametern: invisible oder enterprise auf 1 setzen, oder version auf v3 mit einem Action-Namen, oder die Methode auf turnstile oder geetest umstellen. Die vollständige Parameterliste finden Sie in der CapSkip-API-Dokumentation.

Ein resource query block übergibt drei Eigenschaften an alles, was nachgelagert ist. Der Response-Body kommt als data an, eine Fehlermeldung als error, und metadata trägt den Rest. Die gerade eingesammelte id steht dem nächsten Block also als submitCaptcha.data.request zur Verfügung.

Schritt 3: warten, dann den Token einmal lesen

Fügen Sie einen Wait block hinzu. Fünfzehn Sekunden sind eine sinnvolle erste Wartezeit für eine reCAPTCHA-v2-Checkbox. Bild-Captchas kommen nach etwa einer Sekunde zurück, v3 nach zehn bis fünfzehn, GeeTest nach etwa fünf. Ein Wait block nimmt eine Zahl oder einen JavaScript-Ausdruck entgegen, lässt sich in Sekunden, Minuten, Stunden oder Tagen konfigurieren, bis zu einer Obergrenze von sechzig Tagen, und pausiert nur die direkt nachgelagerten Blöcke.

Fügen Sie dann einen zweiten resource query block namens readResult hinzu, eingestellt auf GET.

# GET, with the id from step 2 in the query string.
/res.php?key=YOUR_KEY&action=get&id={{ submitCaptcha.data.request }}&json=1

Zwei Antworten sind möglich. Ein fertiges Ergebnis hat status auf 1 und den Token im Feld request. Ein Ergebnis, das noch arbeitet, hat status auf 0 und die Zeichenkette CAPCHA_NOT_READY im Feld request, geschrieben ohne das T, und das heißt weiterwarten und nicht etwa, dass etwas schiefgegangen ist. Die Geschichte dieser Schreibweise steht in der ausführlichen Aufarbeitung der CAPCHA_NOT_READY-Antwort.

Behandeln Sie die beiden Fälle mit einem Branch block. Bedingungen sind einfaches JavaScript gegen einen vorgelagerten Block, der Test lautet also readResult.data.status === 1. Der If-Pfad trägt den Token weiter. Der Else-Pfad bekommt ein zweites Wait von zwanzig Sekunden und einen zweiten Lesevorgang.

Widerstehen Sie der Versuchung, das durch einen Loop block zu ersetzen. Dafür gibt es zwei Gründe, und der zweite ist der, der wirklich weh tut. Ein Loop block hat ein Standard-Timeout von zehn Sekunden und eine Obergrenze von zwei Minuten, deutlich unter den dreihundert Sekunden, die CapSkip einem reCAPTCHA-Lösevorgang zugesteht, eine Schleife kann den langsamen Ausläufer also ohnehin nicht abdecken. Wichtiger noch: Ein CapSkip-Ergebnis ist nur einmal lesbar. Eine Schleife, die eine bereits eingesammelte id erneut liest, bekommt den Token kein zweites Mal.

Schritt 4: die Netzwerkregel, die alles entscheidet

Das ist der Retool-spezifische Teil, und er ist der Grund, warum diese Anleitung den Lösevorgang aus resource query blocks aufbaut.

Retool führt Ihr JavaScript und Ihr Python in einem separaten Code-Executor-Dienst aus, per NsJail in einer Sandbox. Bei einem selbst gehosteten Deployment bringt dieser Dienst iptables-Regeln mit, die Link-Local-Adressen und den gesamten Bereich 192.168.0.0/16 abdecken, und Retool dokumentiert einen einzigen Schalter, der sie abschaltet: DISABLE_IPTABLES_SECURITY_CONFIGURATION. Retool sagt außerdem klar, dass es empfiehlt, den Code Executor privilegiert zu betreiben, damit eigener Code in der Sandbox bleibt. Ein code block, der nach einem Solver unter 192.168.1.40 greift, verlangt also von Ihnen, die Sandbox für die gesamte Instanz zu schwächen. Eine Resource-Query ist kein eigener Code und läuft dort nicht.

Davon unabhängig muss der Solver überhaupt erreichbar sein. CapSkip hat dafür zwei Verbindungsmodi. Local bindet an 127.0.0.1 und bedient nur dieses Gerät. Server bindet an Ihre Netzwerkadresse oder öffentliche IP, sodass ein anderer Rechner, ein Container-Host oder eine gehostete Plattform denselben Windows-Rechner über die API erreichen kann. Beide finden Sie unter Verbindungseinstellungen, und der Server-Modus ändert nur, auf welcher Adresse der Löser lauscht. Es ist weiterhin Ihre Hardware, und es wird weiterhin nicht pro Lösung abgerechnet.

Wo Retool läuftWelcher Modus, und was sonst noch
Selbst gehostet auf demselben Windows-Rechner wie CapSkipLocal-Modus. Die Basis-URL bleibt auf Loopback
Selbst gehostet auf einem anderen Rechner oder in Docker in Ihrem NetzwerkServer-Modus mit der LAN-Adresse des Solvers. Verwenden Sie einen resource query block, keinen code block
Retool CloudServer-Modus mit einer statischen öffentlichen IP, dazu eine eingehende Firewallregel für die ausgehenden Adressen von Retool

Retool Cloud ruft Ihre Resources von einem festen, veröffentlichten Satz an Adressen aus auf, und die Dokumentation sagt, dass Cloud-Instanzen sicherstellen müssen, dass konfigurierte Resources den Zugriff von dort erlauben. Die Standardregion ist AWS us-west-2.

# Retool Cloud outbound ranges, us-west-2, the default region.
35.90.103.132/30
44.208.168.68/30

# eu-central-1
3.77.79.248/30

Erlauben Sie diese in der Firewall vor Port 8080 und weisen Sie alles andere ab. Das ist eine viel kleinere Öffnung, als es aussieht, und damit ist zu Retool Cloud alles gesagt.

Schritt 5: die Timeouts, die entscheiden, ob ein langsamer Lösevorgang durchkommt

Retool veröffentlicht für verschiedene Blocktypen unterschiedliche Obergrenzen, und die sind hier wichtig, weil ein Lösevorgang von Natur aus langsam ist.

Welches LimitWertWarum es für eine Lösung wichtig ist
Resource query block, asynchroner LaufBis zu 10 MinutenReichlich. Ein einzelner Lesevorgang kommt in deutlich unter einer Sekunde zurück
Resource query block, synchroner LaufBis zu 2 MinutenFür einen Lesevorgang immer noch in Ordnung, weil das Warten in einem Wait block passiert
Loop blockStandardmäßig 10 Sekunden, höchstens 2 MinutenDer Grund, warum eine Polling-Schleife hier die falsche Form ist
Ganzer Lauf, asynchron30 Stunden, und unbegrenzt mit Wait blocksNichts an einem Lösevorgang kommt dem nahe
Ganzer Lauf, synchron15 Minuten bis zum ersten Response block eines WebhooksDie Falle. Siehe den Absatz unten
Gleichzeitige externe Anfragen pro Workflow50 gleichzeitigDie eigentliche Obergrenze für einen Stapel von Lösevorgängen in einem Lauf
Intervall des Schedule-TriggersMindestens eine MinuteIn Ordnung, und es kostet nichts, das so oft laufen zu lassen

Die synchrone Zahl ist die, um die herum Sie planen sollten. Ein Webhook-Trigger, der die Verbindung offen hält und mit einem Response block antwortet, gibt Ihnen fünfzehn Minuten. Das klingt großzügig, bis man sich daran erinnert, dass ein Aufrufer, der zwei Minuten lang auf einer offenen HTTP-Verbindung sitzt und auf ein reCAPTCHA wartet, schon für sich genommen ein schlechtes Design ist. Starten Sie den Workflow asynchron und lassen Sie ihn den Token dorthin schicken, wo er gebraucht wird, oder beantworten Sie den Webhook sofort und erledigen Sie den Lösevorgang dahinter.

Resource query blocks haben außerdem eigene Einstellungen für die Anzahl der Wiederholungen und für exponentielles Backoff. Schalten Sie diese für submitCaptcha ein und für readResult aus, aus dem oben genannten Grund, dass nur einmal gelesen werden kann.

Wenn Sie lieber Code schreiben

Auf einer selbst gehosteten Instanz, auf der der Code Executor den Solver erreichen kann, schrumpft der ganze Ablauf auf einen einzigen Python-Block, weil das SDK für Sie abfragt. Fügen Sie capskip zuvor im Tab Libraries in die requirements.txt des Workflows ein.

# pip install capskip - add it in the Libraries tab instead.
from capskip import CapSkip

# host is the solver machine. Keep 127.0.0.1 only when Retool
# runs on the same Windows box as CapSkip.
solver = CapSkip(host="192.168.1.40", port=8080)

result = solver.recaptcha(
    sitekey="YOUR_SITEKEY",
    url="https://example.com/page-with-recaptcha",
)

# Python blocks serialize their output as JSON, so return
# the token rather than the client object.
{"token": result["code"]}

Das SDK beginnt mit einem Polling-Abstand von 250 Millisekunden und geht auf fünf Sekunden hoch, statt ein festes Intervall zu schlafen, deshalb kommt diese Variante meist schneller zurück als der Ablauf mit Wait blocks. Ihre Obergrenze für reCAPTCHA, Turnstile und GeeTest liegt bei dreihundert Sekunden, innerhalb des asynchronen Timeouts von zehn Minuten für code blocks. Retool Cloud betreibt standardmäßig Python 3.10, und die entsprechenden Varianten mit einem einzigen Aufruf für Node.js, PHP und C# finden Sie hier: Die Seite zu den SDKs fürs Captcha-Lösen.

Senden Sie den Token im unmittelbar folgenden Block ab. Ein reCAPTCHA-Token ist etwa zwei Minuten gültig, ein Workflow, der löst, dann auf einem langen Wait block wartet und erst danach absendet, scheitert also an einem Token, der bei seiner Erstellung gültig war. Mehr zu diesem Fehlerfall steht im Leitfaden zur Gültigkeitsdauer von reCAPTCHA-Token.

Häufige Fehler und was sie bedeuten

Was Sie sehenUrsacheBeheben
Ein code block läuft beim Zugriff auf eine LAN-Adresse in einen TimeoutDie Standard-iptables-Regeln des selbst gehosteten Code Executors decken 192.168.0.0/16 abVerlegen Sie den Aufruf in einen REST resource query block
Verbindung auf Port 8080 abgewiesenCapSkip ist an Loopback gebunden und Retool läuft woandersWechseln Sie in den Server-Modus und verwenden Sie die Netzwerkadresse des Lösers
Retool Cloud erreicht die Resource überhaupt nichtDie Firewall lässt die ausgehenden Adressen von Retool nicht durchErlauben Sie die veröffentlichten Bereiche für Ihre Region auf Port 8080
readResult liefert jedes Mal CAPCHA_NOT_READYDer Wait block ist kürzer, als der Lösevorgang dauertErhöhen Sie die erste Wartezeit, oder ergänzen Sie ein zweites Warten und Lesen im Else-Pfad
Der zweite Lesevorgang derselben id kommt leer zurückEin CapSkip-Ergebnis ist nur einmal lesbarBehalten Sie den Token in der Blockausgabe, lesen Sie die id nie erneut
ERROR_WRONG_USER_KEY in der AntwortDer Parameter key wurde zu einer leeren Zeichenkette aufgelöstPrüfen Sie den Namen des Secrets, auch die genaue Groß- und Kleinschreibung
Ein gültiges Token wird von der Zielwebsite abgelehntEs ist zwischen Lösung und Absenden abgelaufenSenden Sie im nächsten Block ab, ohne ein Wait dazwischen
Ein Stapel von Lösevorgängen bleibt mittendrin steckenEin Workflow darf 50 externe Anfragen gleichzeitig offen habenVerarbeiten Sie den Loop block in Stapeln, oder verteilen Sie die Arbeit auf mehrere Läufe

FAQ

Kann ich CapSkip aus Retool Cloud heraus nutzen?

Ja, mit dem Server-Modus. Retool Cloud ruft Ihre Resources aus der eigenen Infrastruktur auf, der Solver muss also auf einer Adresse lauschen, die von dort erreichbar ist: einer öffentlichen IP, idealerweise einer statischen. Retool veröffentlicht die ausgehenden Bereiche, aus denen es aufruft, die Firewallregel ist also eng statt offen für die ganze Welt. Am Solver selbst ändert sich nichts und nichts wird abgerechnet. Der einzige Unterschied ist die Adresse, auf der er lauscht.

Warum nicht einfach einen JavaScript-Block mit axios verwenden?

Wegen des Orts, an dem dieser Code läuft. Retool führt code blocks in einem separaten, mit NsJail abgeschotteten Dienst aus, und bei einem selbst gehosteten Deployment installiert dieser Dienst Firewallregeln, die private Bereiche abdecken. Sie abzuschalten ist ein dokumentierter Schalter, aber eben eine instanzweite Entscheidung, getroffen nur, um einen einzigen Workflow einfacher zu machen, und Retool rät davon ab. Ein resource query block erreicht denselben Solver ohne diese Diskussion. Nutzen Sie code blocks für die Logik und resource query blocks für das Netzwerk.

Soll der Workflow in einer Schleife laufen, bis der Token da ist?

Nein. Ein Loop block ist bei zwei Minuten am Ende, deutlich unter den dreihundert Sekunden, die einem reCAPTCHA-Lösevorgang zugestanden werden, und er durchläuft alle Iterationen, die Sie ihm gegeben haben, statt früher abzubrechen. Dazu kommt, dass ein Ergebnis nur einmal gelesen werden kann, wiederholte Lesevorgänge derselben id sind also vergebliche Wege. Ein Wait block der richtigen Länge plus ein einzelner Lesevorgang ist korrekt und günstig, und ein Branch mit einem zweiten Warten und Lesen dahinter deckt die langsamen Fälle ab.

Wie ist das im Vergleich zu n8n oder Pipedream?

Die beiden Anfragen sind in allen drei Tools identisch. Unterschiedlich ist nur das Hindernis, das jedes Tool davorstellt.

  • Bei n8n ist das Hindernis das Container-Networking, hier durchgearbeitet: die n8n-Workflow-Anleitung.
  • Bei Pipedream sind es die Step-Laufzeit und der Ort, an dem die Secrets liegen, behandelt in dem Pipedream-Leitfaden.
  • Bei Retool ist es die eigene Firewall des Code Executors, und deshalb legt der Ablauf oben nie einen HTTP-Aufruf in einen code block.

Die Kurzfassung

Richten Sie eine REST-Resource auf den Solver, senden Sie die Challenge per POST, warten Sie fünfzehn Sekunden mit einem Wait, holen Sie das Ergebnis per GET und verzweigen Sie danach, ob es fertig ist. Lassen Sie das HTTP in resource query blocks statt in code blocks, denn die Standard-Firewallregeln des Code Executors decken private Adressen ab, und sie zu lockern ist eine instanzweite Entscheidung. Stellen Sie CapSkip auf Server-Modus um, sobald Retool nicht auf dem Rechner des Solvers selbst läuft, und lassen Sie in Retool Cloud nur die veröffentlichten ausgehenden Bereiche zu Port 8080 durch. Warten Sie nie innerhalb eines synchronen Webhooks auf einen Lösevorgang.

Eines sollten Sie abwägen, bevor Sie einen geplanten Workflow jede Minute darauf ansetzen: CapSkip ist ein lokaler Captcha-Löser und läuft auf Hardware, die Sie bereits besitzen, sodass ein Workflow, der jede Minute startet, und einer, der zweimal täglich startet, genau gleich viel kosten.