Scarnox · Blog

Selenium-captchasolver in Python: werkend voorbeeld (2026)

Selenium draait een echte browser, dus de pagina wordt weergegeven en de scripts draaien zoals voor een persoon. De enige stap die het niet kan zetten, is de PopularCaptcha-widget oplossen. Deze gids voegt die stap toe: lees de sitekey uit de gerenderde pagina, haal een token op met één API-aanroep, zet het token in het formulier en verstuur.

Hij behandelt de PopularCaptcha-widget, die Scarnox vandaag oplost op een proxyless basis. Begin met gratis proefkrediet, zonder creditcard en probeer het script eerst op een testformulier.

Wat Selenium moet doen

De flow heeft vier onderdelen:

  1. De pagina laden en wachten tot de widget is weergegeven.
  2. Het attribuut data-sitekey van de widget lezen.
  3. Een token ophalen bij de API en het in het formulier zetten.
  4. Het formulier versturen voordat het token verloopt.

De derde stap is de enige die de captcha raakt. Al het andere is gewoon Selenium-werk.

De pakketten installeren

pip install selenium requests

Selenium 4.6 en later vindt zelf een passende ChromeDriver, dus je hoeft de driver niet met de hand te downloaden.

Het volledige script

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,  # blokkeert tot het token klaar is
    )
    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)

        # Vul eerst de overige velden in, en plaats het token vlak voor het verzenden,
        # omdat het token na ongeveer twee minuten verloopt.
        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()

Het script heeft geen proxy nodig voor een proxyless PopularCaptcha-solve. Laat het veld proxy weg en laat de site je gewone verbinding zien.

De volgorde van handelingen is het deel dat het vaakst misgaat. Vul eerst de rest van het formulier in, daarna de solve, dan de injectie, dan de klik. Als je oplost voordat je de andere velden invult, kan een trage pagina of een traag formulier het verzenden voorbij de levensduur van het token duwen. Houd de tijd tussen de solve en de klik zo kort mogelijk, en controleer de resultaatpagina op een fout voordat je aanneemt dat de captcha is gepasseerd.

Waarom het token met JavaScript wordt ingevoerd

De meeste PopularCaptcha-widgets schrijven het token in een verborgen textarea met de naam h-captcha-response wanneer een persoon ze oplost. Omdat Selenium nooit de persoon ziet, schrijft het script hetzelfde veld zelf. Het fragment INJECT_TOKEN_JS doet twee dingen:

Het vult ook g-recaptcha-response, omdat veel sites die naam lezen voor compatibiliteit.

Onzichtbare widgets

Een onzichtbare widget heeft geen vinkje. Hij draait op de achtergrond en wordt meestal gestart bij het verzenden van het formulier. Het script controleert op data-size="invisible" en stuurt is_invisible: true wanneer het dat ziet. Sommige sites koppelen ook een JavaScript-callback aan de widget. Als het formulier blijft staan nadat je het token hebt ingevoerd, zoek dan naar een attribuut data-callback en roep die functie aan met het token. Onze gids over onzichtbare captcha behandelt dit geval.

Gebruik in tests

Selenium is ook het gebruikelijke hulpmiddel voor end-to-end tests. Als je eigen staging-site een captcha toont, laat dezelfde code een test die captcha passeren. Houd de testomgeving gescheiden van productie, en draai het niet tegen sites die je niet beheert. De opzet voor testsuites staat in captcha in geautomatiseerde tests.

Veelvoorkomende problemen

Prijzen

Je betaalt per geslaagde solve. Mislukte solves worden niet in rekening gebracht. Zie actuele prijzen voor de tarieven, en begin met gratis proefkrediet, zonder creditcard.

Volgende stappen