Scarnox · Blog

Selenium-Captcha-Solver in Python: funktionierendes Beispiel (2026)

Selenium steuert einen echten Browser, daher werden Seite und Skripte so gerendert und ausgeführt, wie sie es bei einem Menschen würden. Der einzige Schritt, den Selenium nicht selbst erledigen kann, ist das Lösen des PopularCaptcha-Widgets. Dieser Leitfaden ergänzt diesen Schritt: den Sitekey aus der gerenderten Seite lesen, mit einem API-Aufruf ein Token holen, das Token ins Formular schreiben und absenden.

Er behandelt das PopularCaptcha-Widget, das Scarnox heute proxyless löst. Starte mit kostenlosem Testguthaben, ohne Karte und probiere das Skript zuerst auf einem Testformular aus.

Was Selenium tun muss

Der Ablauf hat vier Teile:

  1. Die Seite laden und warten, bis das Widget gerendert ist.
  2. Das Attribut data-sitekey aus dem Widget lesen.
  3. Ein Token von der API holen und ins Formular geben.
  4. Das Formular absenden, bevor das Token abläuft.

Nur der dritte Schritt berührt das Captcha. Alles andere ist normale Selenium-Arbeit.

Die Pakete installieren

pip install selenium requests

Selenium 4.6 und neuer findet einen passenden ChromeDriver selbst, du musst den Treiber also nicht von Hand herunterladen.

Das vollständige Skript

import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

API_KEY = "scarnox_YOURAPIKEY"
API_URL = "https://api.scarnox.com/api/tasks/create"
PAGE_URL = "https://example.com/signup"


def solve(sitekey: str, page_url: str, invisible: bool = False) -> str:
    body = {
        "captcha_type": "PopularCaptchaTaskProxyless",
        "site_key": sitekey,
        "site_url": page_url,
    }
    if invisible:
        body["is_invisible"] = True

    r = requests.post(
        API_URL,
        headers={"Authorization": f"Bearer {API_KEY}"},
        json=body,
        timeout=185,  # blockiert, bis das Token bereit ist
    )
    data = r.json()
    if data.get("errorId") != 0:
        raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}")
    return data["solution"]["token"]


INJECT_TOKEN_JS = """
const token = arguments[0];
let field = document.querySelector('[name="h-captcha-response"]');
if (!field) {
    field = document.createElement("textarea");
    field.name = "h-captcha-response";
    field.style.display = "none";
    document.querySelector("form").appendChild(field);
}
field.value = token;
let extra = document.querySelector('[name="g-recaptcha-response"]');
if (!extra) {
    extra = document.createElement("textarea");
    extra.name = "g-recaptcha-response";
    extra.style.display = "none";
    document.querySelector("form").appendChild(extra);
}
extra.value = token;
"""


def main() -> None:
    driver = webdriver.Chrome()
    try:
        driver.get(PAGE_URL)

        widget = WebDriverWait(driver, 15).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "[data-sitekey]"))
        )
        sitekey = widget.get_attribute("data-sitekey")
        invisible = widget.get_attribute("data-size") == "invisible"

        token = solve(sitekey, driver.current_url, invisible=invisible)

        # Erst die übrigen Felder ausfüllen, dann das Token kurz vor dem Absenden einfügen,
        # weil das Token in etwa zwei Minuten abläuft.
        driver.find_element(By.NAME, "email").send_keys("you@example.com")
        driver.execute_script(INJECT_TOKEN_JS, token)

        driver.find_element(By.CSS_SELECTOR, "form button[type=submit]").click()
        WebDriverWait(driver, 15).until(EC.url_changes(PAGE_URL))
        print("Submitted. Now at:", driver.current_url)
    finally:
        driver.quit()


if __name__ == "__main__":
    main()

Für eine proxyless PopularCaptcha-Lösung braucht das Skript keinen Proxy. Lass das Feld proxy weg und lass die Seite deine normale Verbindung sehen.

Die Reihenfolge der Schritte ist der Teil, der am häufigsten schiefgeht. Fülle zuerst den Rest des Formulars aus, dann löse, dann füge ein, dann klicke. Wenn du vor dem Ausfüllen der anderen Felder löst, kann eine langsame Seite oder ein langsames Formular den Absendevorgang über die Lebensdauer des Tokens hinaus verschieben. Halte die Lücke zwischen Lösung und Klick so kurz wie möglich und prüfe die Ergebnisseite auf einen Fehler, bevor du annimmst, dass das Captcha bestanden wurde.

Warum das Token per JavaScript eingefügt wird

Die meisten PopularCaptcha-Widgets schreiben das Token in eine versteckte Textarea namens h-captcha-response, wenn eine Person sie löst. Da Selenium keinen Menschen ersetzt, schreibt das Skript dasselbe Feld selbst. Das Snippet INJECT_TOKEN_JS tut zwei Dinge:

Es füllt außerdem g-recaptcha-response, weil viele Seiten aus Kompatibilitätsgründen diesen Namen lesen.

Unsichtbare Widgets

Ein unsichtbares Widget hat kein Kästchen. Es läuft im Hintergrund und startet meist beim Absenden des Formulars. Das Skript prüft data-size="invisible" und sendet is_invisible: true, wenn es das sieht. Manche Seiten hängen außerdem einen JavaScript-Callback an das Widget. Wenn das Formular nach dem Einfügen des Tokens stehen bleibt, suche nach einem Attribut data-callback und rufe diese Funktion mit dem Token auf. Unser Leitfaden zu unsichtbaren Captchas behandelt diesen Fall.

Verwendung in Tests

Selenium ist außerdem das übliche Werkzeug für End-to-End-Tests. Wenn deine eigene Staging-Seite ein Captcha zeigt, lässt sich mit demselben Code ein Test daran vorbeiführen. Halte die Testumgebung von der Produktion getrennt und führe sie nicht gegen Seiten aus, die dir nicht gehören. Die Einrichtung für Testsuiten steht unter Captcha in automatisierten Tests.

Häufige Probleme

Preise

Du zahlst pro erfolgreicher Lösung. Fehlgeschlagene Lösungen werden nicht berechnet. Die Raten findest du auf der Preisseite, und starte mit kostenlosem Testguthaben, ohne Karte.

Nächste Schritte