So lösen Sie DataDome CAPTCHA in Python (requests)

datadome captcha in python - How to Solve DataDome CAPTCHA in Python (requests)

Um ein DataDome CAPTCHA in Python zu lösen, lesen Sie die 403-Sperrseite, bauen daraus die Challenge-Adresse und senden diese Adresse an den CapSkip-Solver für DataDome mit datadome() und wiederholen Ihre Anfrage mit dem zurückgegebenen Cookie. Die Antwort ist ein Cookie und kein Token für ein Formular, und laut der CapSkip-Dokumentation funktioniert es nur mit dem User-Agent und der IP-Adresse, mit denen es ausgestellt wurde. Dieser Leitfaden führt die ganze Schleife mit dem CapSkip-SDK für Python und requests in etwa 90 Zeilen aus. CapSkip läuft auf Ihrem eigenen Windows-PC ohne Gebühr pro Lösung, daher kostet eine Wiederholung nichts.

Was Sie brauchen

  • CapSkip 3.2.0 oder neuer, das auf einem Windows-PC läuft. Mit dieser Version kam das Lösen von DataDome für den Slider und die Geräteprüfung dazu. Die Einrichtungsanleitung führt durch den ersten Start.
  • Python 3.10 oder neuer und das Paket capskip ab Version 1.5.0. Frühere Versionen haben keine Methode datadome. Der Code unten lief auf Python 3.11.7 und 3.14.0 mit capskip 1.5.0 und requests 2.34.2. Python 3.10 wurde hier nicht ausprobiert.
  • Eine PowerShell-Eingabeaufforderung. Die Befehle verwenden PowerShell-Syntax.
  • Eine Seite, die Ihnen gehört oder die Sie automatisieren dürfen, hinter DataDome.
  • 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 Skript auf einem anderen PC, einem VPS oder einer gehosteten Plattform es über die API aufrufen kann. Eingestellt werden beide Modi in den Verbindungseinstellungen.
  • Ein Sticky-Proxy (ein Proxy, der dieselbe IP-Adresse behält) pro Aufgabe, sobald Sie über das Testen hinausgehen. Das Cookie ist an die IP-Adresse gebunden, mit der es ausgestellt wurde, was Schritt 3 erklärt.

So wurde getestet: Der Code lief gegen drei Mock-Server, die ich geschrieben habe, nicht gegen eine echte DataDome-Website. Einer bildet die Prüfungen nach, die im DataDome-Abschnitt der CapSkip API-Dokumentation, ein zweiter spielt eine geschützte Website, die eine 403-Sperrseite ausliefert und nur ein Cookie akzeptiert, das CapSkip ausgestellt hat, mit dem User-Agent, für den es ausgestellt wurde, und ein dritter spielt einen Forward-Proxy. Das SDK war das echte capskip 1.5.0. Die CapSkip-App lief nicht auf meinem PC, daher zeigt nichts hier, wie lange eine echte Lösung dauert oder was eine echte DataDome-Website akzeptiert. Die Regeln zum Cookie stammen aus der CapSkip-Dokumentation. Die eigene Cookie-Dokumentation von DataDome sagt, dass das Cookie datadome ein Jahr gültig ist, und warnt davor, seine Domain oder seinen Path zu ändern. Woran das Cookie gebunden ist, sagt sie nicht.

Schritt 1: Die Sperrseite lesen und die captcha_url bauen

Wenn DataDome an einer Anfrage zweifelt, antwortet die Website statt mit dem Inhalt mit dem Status 403, manchmal 401, und einer kleinen HTML-Seite. Diese Seite enthält ein Skript-Objekt namens dd und lädt die Challenge in einem iframe von geo.captcha-delivery.com. Die Adresse des iframe braucht CapSkip, und die Dokumentation nennt sie captcha_url. Enthält die Seite den iframe bereits, können Sie dessen src unverändert übernehmen. Die meisten Sperrseiten bauen den iframe stattdessen per Skript, daher setzt die Funktion unten dieselbe Adresse aus dem Objekt dd zusammen.

Der Wert von rt bestimmt den Pfad. Ein c steht für den Slider unter /captcha/, ein i für die Geräteprüfung unter /interstitial/. Auch der Wert t zählt: fe ist eine Challenge, und bv bedeutet, dass DataDome die IP-Adresse gesperrt hat, die die Seite abgerufen hat. Die erste Anfrage geht mit einem einfachen Chrome-User-Agent hinaus. Diese Zeichenfolge wird nie an CapSkip gesendet, daher muss ihre Chrome-Version zu nichts passen. Ich habe nicht getestet, ob eine echte DataDome-Website einem anderen User-Agent dieselbe Challenge ausliefert, betrachten Sie diesen Teil also als ungetestet.

# pip install capskip requests
import json
import re
from urllib.parse import urlencode

import requests

PAGE_URL = "https://www.example.com/"  # a page behind DataDome
BROWSER = {  # for the first request only; the cookie comes with its own User-Agent
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
                  "(KHTML, like Gecko) Chrome/156.0.0.0 Safari/537.36",
}


def get(headers, via=None):
    proxies = {"http": via, "https": via} if via else None
    return requests.get(PAGE_URL, headers=headers, proxies=proxies, timeout=30)


def captcha_url_from(resp):
    """Build the challenge address from a DataDome block page, or None."""
    if resp.status_code not in (401, 403):
        return None
    found = re.search(r"var\s+dd\s*=\s*(\{[^}]*\})", resp.text)
    if not found:
        return None
    dd = json.loads(found.group(1).replace("'", '"'))
    path = "interstitial" if dd["rt"] == "i" else "captcha"
    query = {"initialCid": dd["cid"], "hash": dd["hsh"], "cid": dd["cookie"]}
    if dd.get("t"):
        query["t"] = dd["t"]  # fe is a challenge, bv means the address is banned
    query.update(referer=PAGE_URL, s=dd["s"])
    for key in ("e", "b"):
        if dd.get(key):
            query[key] = dd[key]
    query["dm"] = "cd"
    return f"https://{dd.get('host', 'geo.captcha-delivery.com')}/{path}/?{urlencode(query)}"

Die Funktion gibt None zurück, wenn die Antwort keine Sperrseite ist, sodass ein Skript “nichts zu lösen” von “gelöst” unterscheiden kann. Jede Sperrseite ist eine neue Challenge. Verwenden Sie die captcha_url daraus bald, und rufen Sie die Seite für die nächste Aufgabe erneut ab, statt eine alte Adresse wiederzuverwenden.

Schritt 2: Mit datadome() lösen

Die SDK-Methode lautet datadome(captcha_url, pageurl, userAgent, proxy) und folgt der Argumentreihenfolge von 2Captcha. Die ersten beiden sind Pflicht. In CapSkip sind userAgent und proxy optional. Senden Sie keinen User-Agent, verwendet CapSkip den aus seinem eigenen Browser und gibt ihn im Ergebnis als userAgent zurück. Senden Sie doch einen, muss es Chrome für Windows mit derselben Hauptversion wie im Browser von CapSkip sein, daher ist das Weglassen die einfache Wahl. Die Methode wartet mit dem längeren Timeout von 300 Sekunden, den auch reCAPTCHA verwendet, weil CapSkip die Challenge in einem echten Browser besteht. Laut der API-Dokumentation dauert eine Lösung meist 3 bis 20 Sekunden, und ich habe keine gemessen.

Der Proxy ist derjenige, den Ihre späteren Anfragen verwenden. Übergeben Sie ihn, wenn Ihr Skript über einen Proxy nach außen geht, und übergeben Sie nichts, wenn die Anfragen von dem Rechner ausgehen, auf dem CapSkip läuft. Bei einem CapSkip auf einem Server ist dieser Rechner der Server.

from capskip import CapSkip

# Local mode. In Server mode, use your server's address instead.
solver = CapSkip(host="127.0.0.1", port=8080)


def proxy_arg(proxy_url):
    if not proxy_url:
        return None  # your requests leave from the PC that runs CapSkip
    scheme, rest = proxy_url.split("://", 1)
    return {"type": scheme.upper(), "uri": rest}  # e.g. HTTP, user:pass@ip:port


def solve(captcha_url, proxy_url=None):
    # No userAgent argument: CapSkip uses its own browser's and reports it.
    return solver.datadome(captcha_url, PAGE_URL, proxy=proxy_arg(proxy_url))

Lässt sich die Geräteprüfung nicht erfüllen, wechselt DataDome zu einem Slider. Laut der CapSkip-Dokumentation folgt der eine Aufruf dorthin, Sie brauchen also keinen getrennten Code für die beiden Challenges.

Schritt 3: Das Cookie mit seinem User-Agent und seiner IP-Adresse senden

Das Ergebnis ist ein Dictionary mit vier wichtigen Feldern. Das Feld code ist das Cookie genau so, wie DataDome es gesetzt hat, mit Max-Age, Domain und den anderen Attributen, und genau das will ein Cookie-Jar. Das Feld cookie ist nur das Paar aus Name datadome und Wert, und genau das will ein Cookie-Header. Das Feld userAgent ist der User-Agent, mit dem es ausgestellt wurde. Ein Feld proxy erscheint nur, wenn Sie keinen Proxy gesendet haben und CapSkip über die eigene Proxy-Liste von CapSkip für DataDome gelöst hat. Laut der CapSkip-Dokumentation lehnt DataDome das Cookie von einer anderen IP-Adresse oder mit einem anderen User-Agent ab. Senden Sie also jedes Mal denselben User-Agent, und wenn das Ergebnis einen Proxy nennt, senden Sie die Anfrage darüber. Dieses Feld proxy besteht nur aus Host und Port, ohne Schema und ohne Login. Die Funktion setzt http:// davor und geht daher von einem Listen-Proxy ohne Login aus. Hat Ihrer einen, ergänzen Sie ihn.

DataDome kann bei einer späteren Antwort auch ein Ersatz-Cookie senden. Die Funktion behält das neueste, wie es ein Browser täte.

def send_with_cookie(result, proxy_url=None):
    # The cookie works only from the address and User-Agent that earned it.
    via = proxy_url
    if not via and result.get("proxy"):
        via = "http://" + result["proxy"]  # CapSkip solved through its own list
    headers = {"User-Agent": result["userAgent"], "Cookie": result["cookie"]}
    resp = get(headers, via)
    fresh = resp.cookies.get("datadome")  # DataDome may rotate the cookie
    if fresh:
        headers["Cookie"] = f"datadome={fresh}"
    return resp, headers, via

Das Cookie wird von Hand im Header gesetzt, requests verwaltet es also nicht für Sie. Das ist Absicht: Der explizite Header hat Vorrang vor dem Session-Jar, und Cookie, User-Agent und Proxy bleiben an einer Stelle beisammen. Eines hat der Proxy-Lauf gezeigt: Der Text nach dem Schema geht so an CapSkip, wie Sie ihn geschrieben haben, halten Sie den Proxy-Login also frei von Zeichen, die eine Prozentkodierung brauchen. Für einen socks5-Proxy braucht requests außerdem sein Extra socks, installiert mit pip install requests[socks].

Schritt 4: Das vollständige funktionierende Beispiel

Der letzte Block fügt den Ablauf für das DataDome CAPTCHA in Python zusammen und ergänzt die Wiederholung. Speichern Sie alle vier Blöcke nacheinander in einer Datei namens datadome_demo.py und führen Sie sie mit python datadome_demo.py aus. Jeder Versuch ruft die Seite erneut ab, daher trägt jeder Versuch eine frische Challenge. Eine fehlgeschlagene Lösung löst ApiException aus, und die Schleife versucht es erneut. Auch ein Cookie, das trotzdem eine 403 bekommt, schickt die Schleife mit der neuen Sperrseite noch einmal los.

from capskip import ApiException


def fetch_protected(proxy_url=None):
    for attempt in range(1, 4):
        resp = get(BROWSER, proxy_url)  # a fresh block page, a fresh challenge
        captcha_url = captcha_url_from(resp)
        if captcha_url is None:
            return resp, BROWSER, proxy_url  # no block page on this response
        try:
            result = solve(captcha_url, proxy_url)
        except ApiException as err:
            print(f"attempt {attempt}: {err}")  # the next attempt gets a new page
            continue
        resp, headers, via = send_with_cookie(result, proxy_url)
        if resp.status_code != 200:
            print(f"attempt {attempt}: HTTP {resp.status_code} with the cookie")
            continue
        return resp, headers, via
    raise RuntimeError("DataDome not passed in 3 attempts")


if __name__ == "__main__":
    page, headers, via = fetch_protected()
    print(page.status_code, page.text[:40])
    again = get(headers, via)  # reuse the cookie while it lasts
    print(again.status_code)

Das SDK weist eine captcha_url mit t=bv ab, bevor etwas gesendet wird, weil keine Lösung für diese Challenge-Adresse bestehen kann. Diese ValidationException ist keine ApiException, daher fängt die Schleife sie nicht ab. Lassen Sie sie durchlaufen: Sie ist das Signal, die IP-Adresse zu wechseln und von vorn zu beginnen. Eine Sperre, die CapSkip stattdessen als ERROR_PROXY_BANNED meldet, kommt als ApiException an, und die Schleife wiederholt sie mit derselben IP-Adresse. Sehen Sie diesen Fehler in der Ausgabe, wechseln Sie den Proxy, bevor Sie erneut starten. Der Leitfaden zur Proxy-Rotation behandelt rotierende Proxys, und der Beitrag Captcha von einer Sperre unterscheiden behandelt den anderen Fall, in dem die Seite gar keine Challenge ist.

Im Mock-Lauf verhielt sich das Skript so:

Mock-EinstellungWas das Skript tat
Sperrseite mit Slider, jede Lösung beantwortetEine Aufgabe, dann Status 200 mit dem Cookie und bei Wiederverwendung wieder 200
Sperrseite mit GeräteprüfungDerselbe Code lief: Die captcha_url zeigte auf /interstitial/, und das Ergebnis war dasselbe
Die ersten zwei Lösungen abgelehntZwei Versuchszeilen, dann Status 200 bei der dritten Aufgabe
Die ersten drei Lösungen abgelehntDrei Versuchszeilen, dann RuntimeError
Das Ergebnis nennt einen Proxy, so wie es die eigene Liste von CapSkip tutDie Anfrage mit dem Cookie ging über diesen Proxy und bekam 200
Ihr eigener Proxy, an die Lösung übergebenin.php erhielt den Proxy und seinen Typ, und die Anfragen nutzten ihn
Sperrseite mit t=bvValidationException, und das Mock-CapSkip sah gar keine Anfrage
Cookie mit einem anderen User-Agent gesendetDie Mock-Website antwortete mit 403
Cookie von einer anderen IP-Adresse gesendetDie Mock-Website antwortete mit 403 auf ein Cookie, das CapSkip über einen Proxy ausgestellt hatte und das ohne ihn gesendet wurde

Die letzten zwei Zeilen testen die Regeln meines Mocks, die der CapSkip-Dokumentation folgen. Sie sind kein Beleg für den echten Dienst.

Häufige Fehler

FehlerUrsacheBeheben
ValidationExceptionEine captcha_url, die keine DataDome-Challenge-Adresse ist, eine Sperrseite mit t=bv, eine pageurl, die nicht http oder https ist, oder ein userAgent, der nicht Chrome für Windows ist. Die Meldung sagt, welcher dieser Fälle es istBauen Sie die Adresse aus einer frischen Sperrseite neu, wechseln Sie die IP-Adresse, falls sie gesperrt ist, und lassen Sie das Argument userAgent weg
ApiException mit ERROR_WRONG_USERAGENTDer User-Agent ist Chrome für Windows, aber seine Hauptversion weicht von der des CapSkip-Browsers abSenden Sie keinen userAgent und verwenden Sie den, den das Ergebnis meldet
ApiException mit ERROR_CAPTCHA_UNSOLVABLEDie Challenge wurde nicht bestandenRufen Sie die Seite erneut ab und senden Sie ihre neue captcha_url
ApiException mit ERROR_PROXY_BANNEDCapSkip lehnt eine Aufgabe ab, deren Sperrseite t=bv enthält, laut der API-DokumentationWechseln Sie den Proxy und rufen Sie die Seite erneut ab
ApiException mit ERROR_PROXY_CONNECT_REFUSEDCapSkip meldet diesen Fehler, wenn es sich nicht über den Proxy verbinden kann. Ich habe ihn nicht reproduziertPrüfen Sie Adresse, Login und Typ des Proxys
TimeoutExceptionCapSkip hat innerhalb der Wartezeit von 300 Sekunden nicht geantwortet. Das ist keine ApiException, daher fängt die Schleife sie nicht abPrüfen Sie, ob CapSkip läuft und löst, und führen Sie das Skript dann erneut aus
NetworkExceptionCapSkip läuft nicht, oder Host oder Port sind falschStarten Sie CapSkip und prüfen Sie die Verbindungseinstellungen
Weiterhin eine 403 mit dem CookieDie Anfrage ging von einer anderen IP-Adresse aus, nutzte einen anderen User-Agent, oder das Cookie ist abgelaufenSenden Sie jedes Mal den userAgent und den proxy des Ergebnisses, oder führen Sie die Schleife mit der neuen Sperrseite erneut aus

Den Löser auf einem Server betreiben

Das Skript braucht von CapSkip zwei Dinge: einen Host und einen Port. Im Local-Modus sind das 127.0.0.1 und Ihr eigener PC. Im Server-Modus lauscht CapSkip auf Ihrer Netzwerkadresse oder einer öffentlichen IP, sodass ein Skript auf einem anderen PC, einem VPS oder einer gehosteten Plattform es über dieselbe API aufrufen kann. Ändern Sie Host und Port im Konstruktor CapSkip, und nichts anderes ändert sich. Eine statische öffentliche IP wird für stabilen Fernzugriff empfohlen. Der Server-Modus bleibt Ihre eigene Hardware, und es fallen weiterhin keine Gebühren pro Lösung an. Er öffnet den Port allerdings für jede Adresse, fügen Sie daher eine Blockierregel der Windows Firewall für die Adressen hinzu, die ihn nicht erreichen sollen. Denken Sie daran, dass die Lösung auf diesem Rechner läuft, das Cookie also von der IP-Adresse des Servers ausgestellt wird. Wenn Sie keinen Proxy übergeben, muss auch die Anfrage, die das Cookie trägt, von diesem Server ausgehen. Mit einem Proxy übergeben Sie denselben an die Lösung und an Ihre Anfragen. Die Verbindungseinstellungen zeigen, wie Sie den Modus wechseln.

FAQ

Gibt der DataDome-Solver einen Token zurück?

Nein. Er gibt das Cookie datadome zurück. Dieses Cookie senden Sie im Cookie-Header der Anfrage, die blockiert wurde, zusammen mit demselben User-Agent. Es gibt kein Formularfeld, das auszufüllen wäre.

Brauche ich einen Proxy für DataDome?

Zum Testen nicht. Eine IP-Adresse reicht für einen ersten Lauf. Laut der CapSkip-Dokumentation funktioniert das Cookie nur von der IP-Adresse, mit der es ausgestellt wurde. Sobald Sie viele Anfragen senden, planen Sie daher einen Sticky-Proxy pro Aufgabe ein und übergeben Sie denselben Proxy an die Lösung und an Ihre Anfragen.

Funktioniert das sowohl für den Slider als auch für die Geräteprüfung?

Ja, über denselben Aufruf. Die captcha_url für einen Slider liegt unter /captcha/, die für eine Geräteprüfung unter /interstitial/. Laut der CapSkip-Dokumentation wird eine Geräteprüfung, die zu einem Slider eskaliert, dorthin verfolgt.

Kann eine gehostete Plattform das gegen mein CapSkip ausführen?

Ja, über den Server-Modus. Stellen Sie CapSkip so ein, dass es auf Ihrer Netzwerkadresse oder öffentlichen IP lauscht, richten Sie den CapSkip-Konstruktor auf diesen Host und Port, und die Schleife funktioniert genauso, mit einer Änderung: Die Lösung läuft dann auf dem Server, geben Sie also der Lösung und Ihren Anfragen denselben Proxy. Der Solver bleibt auf Ihrer Hardware.

Die Kurzfassung

Ein DataDome CAPTCHA in Python besteht aus vier Schritten: die Sperrseite lesen, die captcha_url bauen, datadome() aufrufen und die Anfrage mit dem Cookie sowie dem User-Agent und der IP-Adresse wiederholen, zu denen es gehört. Eine Wiederholung ist auf Ihrem eigenen Rechner kostenlos, und genau dafür ist ein lokaler Captcha-Löser da, wenn eine geschützte Website Ihnen immer wieder neue Challenges liefert. Für den Rest des SDK siehe die Python-Captcha-Solver-Seite.