curl gibt 403 zurück, aber der Browser funktioniert: Finden Sie das fehlende Teil

Der Browser lädt es. curl erhält 403. Die Lücke zwischen diesen beiden Anfragen ist immer endlich und immer auffindbar – hier erfahren Sie, wie Sie sie in fünf Minuten halbieren können.

Sie fügen eine URL in Chrome ein und die Seite lädt. Sie fügen dieselbe URL in curl ein und erhalten 403 Verboten. Nichts an der Ressource hat sich in diesen zwei Sekunden geändert, also liegt der Unterschied vollständig in der Anfrage – und eine Anfrage ist eine endliche, überprüfbare Sache. Diese Anleitung ist ein Halbierungsverfahren: Spielen Sie genau das ab, was der Browser gesendet hat, und entfernen Sie dann Teile, bis der 403 zurückkommt. Was auch immer Sie zuletzt entfernt haben, ist Ihre Antwort. Die Verdächtigen, in der Reihenfolge, in der sie normalerweise schuldig sind, sind User-Agent, Referer, Cookies, TLS-Fingerabdruck und JavaScript.

Schritt 0: Beweisen Sie, dass die Anfragen wirklich unterschiedlich sind

Bevor Sie spekulieren, schauen Sie sich an, was curl tatsächlich sendet. Mit -v sehen Sie die Anforderungszeile, jeden Header und den TLS-Handshake. Eine Standard-curl-Anfrage ist überraschend dünn – typischerweise Host, User-Agent: curl/8.x und Accept: */*. Ein Browser sendet ein Dutzend mehr.

# what you send, what you get back, and the TLS details
curl -v -o /dev/null https://target.example/page

# just the response headers, quickly
curl -sS -o /dev/null -D - https://target.example/page

Lesen Sie die Antwort-Header so sorgfältig wie die Statuszeile. Einer von ihnen klärt die Frage in den häufigsten Fällen: Vary: User-Agent bedeutet, dass der Server absichtlich unterschiedliche Antworten liefert, je nachdem, wer Sie zu sein behaupten. In einem gut dokumentierten Stack Overflow-Fall gab curl -f gegen einen einfachen Apache 2.4.38-Host 403 zurück, während wget die identische Datei mit 200 abrief – und die erfolgreiche Antwort trug genau diesen Vary: User-Agent-Header. Das Übergeben von -A 'Wget/1.21.2' an curl behob es sofort. Der Website-Besitzer hatte den User-Agent von curl nach Missbrauch auf die schwarze Liste gesetzt; nichts anderes an der Anfrage spielte eine Rolle.

Während Sie die Ausgabe lesen: curl: (22) Die angeforderte URL gab Fehler: 403 zurück ist kein separates Problem. Exit-Code 22 ist das, was -f/--fail mit jedem HTTP-Fehler macht – das Flag unterdrückt den Body und lässt den Befehl fehlschlagen. Entfernen Sie -f vorübergehend, damit Sie tatsächlich die Blockseite lesen können, die normalerweise das System benennt, das Sie gestoppt hat.

Schritt 1: Kopieren als cURL, die 30-Sekunden-Antwort

Beide großen Browser können Ihnen die genaue Anfrage geben, die sie gerade gemacht haben. Öffnen Sie DevTools, gehen Sie zum Netzwerk-Tab, klicken Sie mit der rechten Maustaste auf die Anfrage und wählen Sie "Kopieren als cURL". Chrome bietet dies seit Version 26 und Firefox seit 31 an, und die Ausgabe enthält jeden Header, jedes Cookie und den Referer. Fügen Sie es in Ihr Terminal ein: Wenn es 200 zurückgibt, liegt Ihr Problem definitiv in der Form der Anfrage, und Schritt 2 findet heraus, welcher Teil es ist.

Ein Stolperstein verschwendet hier viel Zeit. Wenn die URL umleitet, wird das Netzwerk-Panel bei der Navigation geleert und Sie kopieren die falsche Anfrage. Aktivieren Sie "Protokoll beibehalten" in Chrome oder "Persistente Protokolle" in Firefox zuerst, damit Sie sowohl die Anfrage sehen können, die umgeleitet wurde, als auch die, die schließlich den Inhalt bereitstellte. Umleitungs-Ketten sind wichtig: In einem bekannten Unix Stack Exchange-Thread überprüfte der Server den Referer, dann sprang er durch einen 302 zu einem Ort, der nichts überprüfte – was das Versagen zufällig erscheinen ließ, bis die gesamte Kette sichtbar war.

Seitenvergleich einer Chrome-Browser-Anfrage und einer Standard-curl-Anfrage mit Header-Anzahl, Cookies, TLS-Fingerabdruck und JavaScript-Unterstützung
Jeder 403 in diesem Szenario verbirgt sich in dieser Lücke. Schließen Sie sie eine Spalte nach der anderen.

Schritt 2: Halbieren Sie die Header

Beginnen Sie mit dem funktionierenden "Kopieren als cURL"-Befehl und löschen Sie Header einzeln, indem Sie nach jeder Löschung erneut ausführen. Die erste Löschung, die den 403 zurückbringt, nennt Ihren Schuldigen. In der Praxis ist es fast immer einer von vier.

curl -sS -o /dev/null -w '%{http_code}\n' \
  -A 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36' \
  -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' \
  -H 'Accept-Language: en-GB,en;q=0.9' \
  -e 'https://target.example/' \
  -b 'session=abc123; consent=1' \
  -L \
  'https://target.example/page'

Zwei abschließende Details für diese Stufe. Zitieren Sie die URL: Eine Abfragezeichenfolge, die & oder ein Zugriffstoken enthält, wird andernfalls von Ihrer Shell durcheinandergebracht, und der resultierende 403 hat nichts mit dem Server zu tun. Und wenn Sie von PHP oder Node aus debuggen und nicht von der Shell, replizieren Sie dort denselben Header-Satz – die Standardwerte von libcurl innerhalb von PHP unterscheiden sich von denen des Befehlszeilentools, weshalb die identische Anfrage in einem Terminal bestehen und im Code fehlschlagen kann. Unsere curl-Proxy-Rezepte decken die Flag-Syntax vollständig ab.

Schritt 3: Wenn identische Header immer noch 403 zurückgeben

Wenn eine bytegenaue Kopie der Browser-Header immer noch fehlschlägt, wurde die Entscheidung getroffen, bevor Ihre Header analysiert wurden. Zwei Schichten liegen darunter.

TLS-Fingerabdruck. Ihr ClientHello – Chiffren, Erweiterungen, Kurvenpräferenzen, ALPN sowie das HTTP/2-Einstellungs-Frame, das folgt – wird zu einem JA3- oder JA4-Wert gehasht. curl, das gegen OpenSSL gebaut wurde, erzeugt einen, den kein Browser jemals erzeugt, und Anti-Bot-Systeme vergleichen ihn mit Ihrem behaupteten User-Agent. Sich als Chrome auszugeben, während man sich wie OpenSSL handshakt, ist ein Widerspruch, den sie zu erkennen gebaut sind. Die Lösung ist ein Client, der Browser-Handshakes reproduziert: curl-impersonate an der Befehlszeile oder curl_cffi aus Python.

# pip install curl_cffi
from curl_cffi import requests

proxy = "http://USER:PASS@gate.quantumproxies.io:8000"

r = requests.get(
    "https://target.example/page",
    impersonate="chrome",          # browser ClientHello + HTTP/2 settings
    proxies={"http": proxy, "https": proxy},
    timeout=20,
)
print(r.status_code, r.headers.get("content-type"))

Ihre IP. Der Browser, der funktioniert, ist normalerweise mit Ihrer Heimverbindung verbunden, während curl auf einem VPS läuft. Hosting-ASNs sind veröffentlicht und vorbewertet, sodass dieselbe Anfrage von einer Wohnadresse anders beurteilt wird, bevor sie überhaupt gelesen wird. Das Ändern des Ausgangs ist eine einzeilige Änderung mit residential proxies – über 90 Millionen IPs in über 200 Ländern, HTTP und SOCKS5 in jedem Plan – und es ist der schnellste Weg, das Netzwerk auszuschließen. Die Mechanik der Fingerabdruckschicht finden Sie in JA3/JA4 TLS-Fingerprinting.

Schließen Sie das Netzwerk mit Residential Proxies aus

Entscheidungsbaumfluss von einem curl 403 zu einer 200-Antwort: Kopieren als cURL, Header halbieren, TLS imitieren, dann rendern oder eine Scraper-API verwenden
Vier Schritte, jeder ein Test. Stoppen Sie, sobald der Status 200 wird – steigen Sie nicht weiter, als Sie müssen.

Schritt 4: Die Seite benötigt einen Browser, keinen Client

Manchmal ist der 403 kein Urteil über Sie – es ist der Fehlermodus einer Herausforderung, die Sie nie versucht haben. Eine öffentliche GitHub-Diskussion über Link-Checker, die npmjs.com treffen, sagt es klar: curl kann keine gültige Herausforderungslösung produzieren, daher wird die Anfrage mit einem 403 blockiert. Der Server stellt ein kleines JavaScript-Problem aus, wartet einen Moment auf die Antwort und verweigert alles, was es nicht ausführen kann. Kein Header-Set, kein Fingerabdruck und keine IP bestehen einen Test, der das Ausführen von Code erfordert.

An diesem Punkt haben Sie drei ehrliche Optionen: einen echten Browser betreiben und die Kosten tragen, den JSON-Endpunkt finden, den die Seite selbst aufruft (oft im selben Netzwerk-Tab, den Sie bereits geöffnet haben), oder die URL einem Dienst übergeben, der bei Bedarf rendert. Die QuantumProxies Scraper API erledigt das Letzte – browserfähiges TLS, Wohnanschlüsse, JavaScript-Rendering nur dort, wo eine Seite es benötigt, und Markdown, JSON oder rohes HTML zurück von einer Anfrage. Wenn das, was Sie erhalten, eine leere Seite anstelle einer verbotenen ist, ist das eine andere Diagnose: siehe warum Ihr Scraper eine leere Seite zurückgibt. Und wenn die Blockseite eine Cloudflare Ray ID trägt, gehen Sie zu Cloudflare-Fehler 1020 stattdessen.

Häufig gestellte Fragen

Warum erhält curl 403, wenn mein Browser es nicht tut?

Weil curl ungefähr drei Header, keine Cookies, keinen Referer und einen nicht-browserbasierten TLS-Fingerabdruck sendet, während Ihr Browser ein Dutzend Header, ein Cookie-Glas und einen Chrome-Handshake sendet. Der Server verweigert die Anfrage, nicht die Ressource. Spielen Sie die genaue Anfrage des Browsers mit "Kopieren als cURL" ab und entfernen Sie dann Header einzeln, um herauszufinden, welcher Unterschied wichtig ist.

Warum gelingt wget, wo curl 403 erhält?

Fast immer der User-Agent. Einige Server setzen curl's UA nach Missbrauch speziell auf die schwarze Liste, während sie wget's in Ruhe lassen – ein dokumentierter Fall zeigte einen Vary: User-Agent-Antwort-Header, der bestätigte, dass der Server darauf verzweigt, und curl -A 'Wget/1.21.2' stellte die 200 wieder her. wget sendet auch standardmäßig Accept-Encoding und Connection, was gelegentlich auch eine Rolle spielt.

Wie setze ich einen User-Agent in curl?

Verwenden Sie -A 'string' oder das entsprechende -H 'User-Agent: string'. Bevorzugen Sie eine vollständige, aktuelle Browser-Zeichenfolge gegenüber einem gekürzten Mozilla/5.0, die einige Server jetzt ablehnen, gerade weil kein echter Browser nur zwei Tokens sendet. Kombinieren Sie es mit passenden Accept und Accept-Language-Werten, damit das gesamte Set kohärent bleibt.

Was bedeutet curl Fehler 22?

Exit-Code 22 wird von -f/--fail erzeugt, wann immer der Server einen HTTP-Fehler zurückgibt, und die Nachricht zitiert den Status – häufig 403. Es ist ein Berichts-Flag, kein eigenständiger Fehler. Entfernen Sie -f, um den Antwort-Body zu sehen, der normalerweise die Blockierung weit besser erklärt als der Exit-Code.

Kann ein Proxy einen curl 403 beheben?

Er behebt den Teil, der durch IP-Reputation oder Geografie verursacht wird – ein großer Teil, wenn Ihr Skript auf einem Cloud-Host läuft und Ihr Browser nicht. Er wird keinen fehlenden Referer, kein fehlendes Cookie oder eine JavaScript-Herausforderung beheben. Testen Sie zuerst die Header, da sie nichts kosten, und ändern Sie dann die Ausgangs-IP, um die Netzwerkschicht zu isolieren.

Es gibt hier kein Geheimnis, nur eine Lücke: Der Browser hat eine Anfrage gesendet und Sie eine andere. Kopieren Sie die des Browsers, verkleinern Sie sie, bis sie fehlschlägt, und Sie werden immer das Teil finden, das wichtig war – normalerweise ein Header, manchmal ein Fingerabdruck, gelegentlich eine Herausforderung, die einen echten Browser zur Antwort benötigt.

Rufen Sie jede Seite mit der Scraper API ab