Captchas in einem Pipedream-Code-Step lösen (Node.js)

pipedream captcha - How to Solve CAPTCHAs in a Pipedream Code Step (Node.js)

Ein Captcha in Pipedream zu lösen ist einfacher als dieselbe Aufgabe in Zapier oder Make.com, denn ein Code-Step ist eine echte Node.js-v20-Laufzeit mit npm-Imports. Sie installieren nichts, Sie schreiben gewöhnliches JavaScript, und das CapSkip SDK arbeitet genau wie auf Ihrem Laptop. Zwei Dinge sind anders, und beide betreffen den Ort, an dem der Code läuft. Pipedream führt in seiner eigenen Cloud aus, der Löser muss also aus dem Internet erreichbar sein. Und eine Workflow-Ausführung hat ein Zeitlimit, das kürzer ist als eine reCAPTCHA-Lösung, was entscheidet, ob Sie einen Step schreiben oder zwei.

Was Sie brauchen

  • Ein Pipedream-Workflow mit einem Code-Step. Node.js ist die unten verwendete Laufzeit. Weiter unten gibt es eine Python-Variante.
  • CapSkip im Server-Modus, auf einer aus dem Internet erreichbaren Maschine, mit einer statischen öffentlichen IP.
  • Der sitekey und die Seiten-URL der Website, die Sie automatisieren.
  • Zwei Pipedream-Umgebungsvariablen mit der Adresse des Lösers und seinem Schlüssel.

Warum die Loopback-Adresse hier nicht funktionieren kann

Pipedream-Workflows laufen auf der eigenen Infrastruktur von Pipedream, im AWS-Netz us-east-1. Eine Anfrage an 127.0.0.1 aus einem Code-Step heraus löst auf den Container auf, in dem der Step läuft, nicht auf Ihren Schreibtisch. Dort lauscht nichts, und das SDK wirft eine NetworkException.

CapSkip hat zwei Verbindungsmodi, und der zweite ist die Antwort. Local bindet sich an 127.0.0.1 und bedient nur dieses Gerät, was richtig ist, wenn Automatisierung und Löser sich eine Maschine teilen. Server bindet sich an Ihre Netzwerkadresse oder öffentliche IP, sodass eine gehostete Plattform dieselbe Windows-Maschine über die API erreicht. Eine statische öffentliche IP ist empfehlenswert, denn eine wechselnde Privatkundenadresse bricht den Workflow um drei Uhr nachts, ohne Ihnen Bescheid zu sagen. Beide Modi werden eingerichtet unter Verbindungseinstellungen.

Der Server-Modus ändert nur, wo der Löser läuft, sonst nichts. Es ist weiterhin Ihre Hardware und weiterhin ohne Verbrauchsabrechnung, ein Workflow, der zehntausendmal im Monat feuert, kostet also dasselbe wie einer, der zehnmal feuert.

Schritt 1: die Adresse in eine Umgebungsvariable legen

Schreiben Sie die öffentliche IP nicht fest in den Step. Pipedream hat Workspace-Umgebungsvariablen, und ein Code-Step liest sie aus der gewöhnlichen Prozessumgebung. Legen Sie zwei an.

VariablennameWert
Die mit dem Namen CAPSKIP_HOSTDie öffentliche IP Ihrer Löser-Maschine, ohne Schema und ohne Port
Die mit dem Namen CAPSKIP_API_KEYDer Schlüssel, den Sie in der CapSkip-App für diesen Workflow erzeugt haben

Geben Sie diesem Workflow einen eigenen Schlüssel, statt einen zu teilen. Einen Schlüssel zu widerrufen, der in einen gemeinsamen Workspace gelangt ist, sollte nicht den Rest Ihrer Automatisierung mitreißen.

Schritt 2: die ganze Lösung in einem Code-Step

Pipedream installiert ein npm-Paket in dem Moment, in dem Sie es importieren, es gibt also keinen Installationsschritt und keine Paketdatei. Im Import-Specifier pinnen Sie auch die Version, was sich bei allem lohnt, was unbeaufsichtigt läuft.

// npm install capskip - Pipedream installs it from this import.
// The package is CommonJS, so take the default and destructure.
import capskip from "capskip";

const { CapSkip } = capskip;

export default defineComponent({
  async run({ steps, $ }) {
    const solver = new CapSkip({
      host: process.env.CAPSKIP_HOST,
      port: 8080,
      apiKey: process.env.CAPSKIP_API_KEY,
    });

    const result = await solver.recaptcha(
      "YOUR_SITEKEY",
      "https://example.com/page-with-recaptcha"
    );

    return result.code;   // the token, for the next step
  },
});

Das ist alles. Jede reCAPTCHA-Variante ist dieselbe Methode mit einem Options-Objekt: invisible auf 1, enterprise auf 1, oder version auf v3 mit einem Action-Namen. Turnstile und GeeTest haben eigene Methoden derselben Form, und die vollständige Parameterliste steht in der CapSkip-API-Dokumentation.

Was der Step zurückgibt, landet in den Exports des Workflows, ein späterer Step liest das Token also über den Namen des Steps. Wenn Sie ihm lieber ein Label geben, verwenden Sie den Export-Helper.

// A named export reads better downstream than a bare return.
$.export("token", result.code);

// The next step then reads steps.solve_captcha.token

Das Ausführungs-Timeout, und wann ein Step nicht mehr reicht

Hier ist die Einschränkung, die alles andere prägt. Eine Pipedream-Ausführung hat ein Standardzeitlimit von 30 Sekunden für HTTP- und E-Mail-Trigger und 60 Sekunden für Cron-Trigger. In den Workflow-Einstellungen können Sie es anheben, auf bis zu 300 Sekunden in den kostenlosen Tarifen und 750 Sekunden in den kostenpflichtigen.

Eine reCAPTCHA-v2-Lösung liegt meist deutlich unter 30 Sekunden, aber meist ist nicht immer, und die eigene Obergrenze des SDK ist recaptchaTimeout bei 300 Sekunden. Die einstufige Variante oben ist also genau so zuverlässig wie Ihre Timeout-Einstellung. Liegt das Workflow-Limit unter der Lösungsdauer, wird die Ausführung mitten im Polling abgebrochen, und Sie erhalten einen fehlgeschlagenen Lauf ohne verwertbaren Inhalt.

Ihre SituationWas zu tun ist
Geringes Volumen, und Sie können das Ausführungslimit auf 300 Sekunden anhebenBleiben Sie bei der einstufigen Variante. Heben Sie das Timeout in den Workflow-Einstellungen an
Hohes Volumen, oder Sie zahlen für AusführungszeitTeilen Sie ihn auf und nutzen Sie den unten beschriebenen Rerun-Helper
Turnstile-Challenge-Seiten oder GeeTest, die länger dauernTeilen Sie ihn auf. Das sind die Typen, die ein kurzes Limit am ehesten überschreiten

Schritt 3: mit dem Rerun-Helper aufteilen

Pipedream hat ein Polling-Primitiv, das den meisten Automatisierungsplattformen fehlt. Der flow.rerun-Helper beendet den aktuellen Step, wartet und führt denselben Step erneut aus, mit einem Stück Zustand, das Sie ihm übergeben. Der Workflow läuft während des Wartens nicht, eine langsame Lösung kostet Sie also nichts und kann das Limit nicht reißen.

Drei Dinge machen das möglich. Der Run-Zähler beginnt bei 1 und erhöht sich mit jedem Rerun. Das Kontext-Objekt, das Sie übergeben, ist im nächsten Durchgang lesbar. Und das Überschreiten der Wiederholungsgrenze führt den Workflow zum nächsten Step weiter, statt fehlzuschlagen; werfen Sie also eine Exception, wenn Sie das nicht wollen.

// No SDK here. The raw endpoints suit a step that exits
// between polls, because nothing has to stay in memory.
const MAX_RETRIES = 20;
const DELAY = 15000;   // 15s, the recommended first wait for v2

export default defineComponent({
  async run({ steps, $ }) {
    const { run } = $.context;
    const base = `http://${process.env.CAPSKIP_HOST}:8080`;
    const key = process.env.CAPSKIP_API_KEY;

    if (run.runs === 1) {
      const params = new URLSearchParams({
        key,
        method: "userrecaptcha",
        googlekey: "YOUR_SITEKEY",
        pageurl: "https://example.com/page-with-recaptcha",
        json: "1",
      });
      const submitted = await fetch(`${base}/in.php?${params}`);
      const { request: id } = await submitted.json();

      // The id survives into the next run through the context.
      return $.flow.rerun(DELAY, { id }, MAX_RETRIES);
    }

    const { id } = $.context.run.context;
    const polled = await fetch(
      `${base}/res.php?key=${key}&action=get&id=${id}&json=1`
    );
    const data = await polled.json();

    if (data.request !== "CAPCHA_NOT_READY") {
      return data.request;   // the token
    }
    if (run.runs === MAX_RETRIES + 1) {
      throw new Error("Solve did not finish in time");
    }
    return $.flow.rerun(DELAY, { id }, MAX_RETRIES);
  },
});

Die Schreibweise dieser Warteantwort bringt viele durcheinander. Sie lautet CAPCHA_NOT_READY, ohne das T, und sie ist kein Fehler: Sie bedeutet, dass die Antwort noch nicht fertig ist und Sie erneut pollen sollten. Sie als Fehlschlag zu behandeln ist der häufigste Bug in einer handgeschriebenen Polling-Schleife, und es gibt eine ausführliche Beschreibung der CAPCHA_NOT_READY-Antwort.

Noch etwas zu diesem Endpunkt. Ein Ergebnis ist genau einmal lesbar. Wenn Sie den Response-Body protokollieren und ihn dann in einem späteren Step erneut lesen, kommt der zweite Lesevorgang leer zurück und sieht aus, als wäre die Lösung fehlgeschlagen.

Senden Sie das Token sofort ab

Ein reCAPTCHA-Token ist etwa zwei Minuten lang gültig. In einem Workflow ist das leichter zu verlieren, als es klingt, denn ein Delay-Step, ein langsamer HTTP-Aufruf oder ein Rerun, der zu lange gewartet hat, zehren alle am selben Budget. Setzen Sie den Step, der das Token absendet, direkt hinter den Step, der es erzeugt hat, und legen Sie keine Token auf Vorrat. Das vollständige Bild steht in dem Leitfaden zum Ablaufen von reCAPTCHA-Tokens.

Die Python-Variante

Pipedream führt auch Python-3.12-Code-Steps aus und installiert pip-Pakete genauso aus Ihren Imports. Das SDK liest von sich aus keine Umgebungsvariablen, deshalb liest der Step unten CAPSKIP_HOST, CAPSKIP_PORT und CAPSKIP_API_KEY aus und übergibt sie an den Konstruktor.

# pip install capskip - Pipedream installs it from this import
import os
from capskip import CapSkip

def handler(pd: "pipedream"):
    # Your Pipedream environment variables. The SDK does not read
    # them by itself, so pass them to the constructor.
    solver = CapSkip(
        host=os.environ["CAPSKIP_HOST"],
        port=int(os.environ["CAPSKIP_PORT"]),
        apiKey=os.environ["CAPSKIP_API_KEY"],
    )

    page_url = pd.steps["trigger"]["event"]["body"]["url"]
    result = solver.recaptcha(sitekey="YOUR_SITEKEY", url=page_url)

    # Downstream steps read pd.steps["solve"]["token"]
    return {"token": result["code"]}

Setzen Sie CAPSKIP_PORT auf 8080 zusätzlich zu den beiden anderen, wenn Sie diesen Weg gehen. Eine Einschränkung, die Sie vorher kennen sollten: Die Rerun- und Delay-Helper sind für Node.js dokumentiert, ein Python-Step ist also nur die einmalige Variante. Wenn Sie die aufgeteilte Polling-Form brauchen, schreiben Sie diesen einen Step in Node.

Den gerade geöffneten Port absichern

Der Server-Modus stellt einen Listener ins öffentliche Internet, behandeln Sie ihn also wie jeden anderen exponierten Dienst. Drei Dinge lohnen sich schon am ersten Tag.

  • Schalten Sie die API-Schlüsselprüfung in der CapSkip-App ein und geben Sie diesem Workflow einen eigenen Schlüssel. Ohne sie wird jede Zeichenkette als Schlüssel akzeptiert.
  • Stellen Sie den Löser hinter eine Firewall-Regel, statt 8080 für alles offen zu lassen.
  • Entscheiden Sie, wie Sie diese Regel formulieren. Der gewöhnliche ausgehende Verkehr von Pipedream kommt aus den üblichen AWS-Bereichen von us-east-1, die viel zu breit sind, um sinnvoll auf einer Allowlist zu stehen. Brauchen Sie eine enge Regel, bietet Pipedream eine VPC mit einer dedizierten statischen Ausgangs-IP pro Workspace, und genau diese Adresse setzen Sie auf die Allowlist.

Häufige Fehler und was sie bedeuten

Was Sie sehenUrsacheBeheben
NetworkException oder eine abgelehnte Verbindung auf Port 8080Der Löser ist im Local-Modus, oder die Host-Variable ist falschWechseln Sie in den Server-Modus und setzen Sie die Host-Variable auf die öffentliche IP
Die Ausführung wird mitten in der Lösung abgebrochenDas Zeitlimit des Workflows ist kürzer als die Lösung gedauert hatHeben Sie es in den Workflow-Einstellungen an oder wechseln Sie zur Rerun-Variante
Der Step gibt die wörtliche Warteantwort als Ergebnis zurückDer Polling-Zweig hat CAPCHA_NOT_READY als Antwort behandeltPrüfen Sie explizit darauf und führen Sie einen Rerun aus, statt sie zurückzugeben
ERROR_WRONG_USER_KEY vom rohen EndpunktDie Schlüsselvariable ist leer, es wurde also eine leere Zeichenkette gesendetPrüfen Sie den Namen der Umgebungsvariable, auch die Groß- und Kleinschreibung
Das Token ist beim zweiten Lesen leerEin Ergebnis kann nur einmal gelesen werdenEinmal lesen, in einer Variablen behalten und diese weitergeben
Ein gültiges Token wird von der Zielwebsite abgelehntEs ist zwischen Lösung und Absenden abgelaufenSetzen Sie den Absende-Step direkt hinter den Lösungs-Step
Cannot use import statement outside a moduleDer Step mischt import und requireWählen Sie einen Stil pro Step. Code-Steps sind ES-Module

FAQ

Kann ich CapSkip aus Pipedream nutzen, ohne etwas nach außen zu öffnen?

Nicht direkt, denn die Rechenleistung von Pipedream gehört Pipedream. Irgendetwas muss eine eingehende Verbindung annehmen. Der Server-Modus mit Schlüsselprüfung und einer Firewall-Regel ist die naheliegende Antwort. Verbietet Ihre Richtlinie einen offenen Port gänzlich, besteht die Alternative darin, die Captcha-Arbeit auf einer Maschine zu halten, die Sie kontrollieren, und Pipedream stattdessen den eigenen Endpunkt dieser Maschine aufrufen zu lassen, was die Exposition verlagert, statt sie zu beseitigen.

Zählt ein Rerun als eigene Ausführung?

Der Step läuft erneut, der Code wird also mehr als einmal ausgeführt, genau deshalb gibt es den Zähler. Der Sinn des Helpers ist, dass der Workflow über die Wartezeit hinweg nicht offen gehalten wird, eine langsame Lösung treibt eine einzelne Ausführung also nicht über das Zeitlimit. Prüfen Sie die Abrechnung Ihres Tarifs, wenn die Kosten wichtig sind, aber das Timeout-Problem ist so oder so gelöst.

Sollte ich das SDK oder die rohen Endpunkte verwenden?

Das SDK, wenn ein Step die ganze Arbeit macht, denn es übernimmt das Polling, steigert das Intervall ab 250 Millisekunden, statt ein festes Intervall abzuwarten, und liefert typisierte Fehler. Die rohen Endpunkte, wenn Sie über Reruns aufteilen, denn der Step endet zwischen den Polls, und es bleibt kein Client im Speicher, der die Aufgabe hält. Beide sprechen mit demselben Dienst auf demselben Port.

Worin unterscheidet sich das von n8n oder Zapier?

Vor allem die Laufzeitumgebung. Pipedream gibt Ihnen echtes Node.js mit npm-Imports, das SDK lässt sich also direkt einsetzen, und der Rerun-Helper bewältigt langsame Lösungen sauber. Der Code-Step von Zapier kann keine Pakete installieren, weshalb der Zapier-Captcha-Leitfaden um dessen Timeout herum gebaut ist. Make.com hat gar keinen Code-Step, weshalb die Make.com-Anleitung aus HTTP-Modulen zusammengesetzt ist. n8n lässt sich neben dem Löser selbst hosten, sodass der n8n-Leitfaden oft den Local-Modus behalten kann.

Die Kurzfassung

Versetzen Sie CapSkip in den Server-Modus, halten Sie Adresse und Schlüssel in Pipedream-Umgebungsvariablen und importieren Sie das SDK direkt in einen Node.js-Code-Step. Liegt das Zeitlimit des Workflows bequem über Ihrer langsamsten Lösung, ist ein Step die gesamte Integration. Ist es das nicht, teilen Sie den Step auf: an den rohen Endpunkt absenden, die id an den Rerun-Helper übergeben und beim Wiedereinstieg pollen. Senden Sie das Token sofort ab, nachdem Sie es erhalten haben, denn es läuft nach etwa zwei Minuten ab.

Die Node.js-Seite finden Sie auf die Node.js-Captcha-Solver-Seite, die Checkbox-Challenge auf die reCAPTCHA-v2-Solver-Seite, und die entsprechenden Aufrufe in Python, PHP und C# auf Die Seite zu den SDKs fürs Captcha-Lösen.

Gut zu wissen, bevor Sie das in etwas einbauen, das den ganzen Tag läuft: CapSkip erledigt Captcha-Umgehung auf Hardware, die Ihnen bereits gehört, ein Workflow, der ständig feuert, und einer, der gelegentlich feuert, kosten also exakt dasselbe.