Warum der Proxy im Browser funktioniert, aber nicht im Code: Eine vollständige Analyse
Klassische Situation: Sie konfigurieren einen Proxy im Browser, öffnen eine Website – alles funktioniert. Sie starten ein Skript mit demselben Proxy – Verbindungsfehler, Timeout oder eine Sperre. Wir erklären, warum das passiert und wie Sie es beheben können.
Worin sich eine Browseranfrage von einer Code-Anfrage unterscheidet
Wenn Sie eine Website über einen Proxy im Browser öffnen, passiert viel mehr als nur eine einfache HTTP-Anfrage. Der Browser führt automatisch folgende Schritte durch:
- Sendet einen vollständigen Satz von Headern (User-Agent, Accept, Accept-Language, Accept-Encoding)
- Führt einen TLS-Handshake mit einem korrekten Satz von Chiffren durch
- Verarbeitet Weiterleitungen (Redirects) und Cookies
- Führt JavaScript aus und lädt abhängige Ressourcen
- Cacht DNS-Antworten und Zertifikate
Eine minimale Anfrage aus dem Code sieht für den Server völlig anders aus – eher wie ein Roboter als wie ein Mensch. Selbst wenn der Proxy korrekt funktioniert, blockiert die Zielseite möglicherweise speziell Ihr Skript.
Probleme mit der Proxy-Authentifizierung
Die häufigste Ursache ist die falsche Übergabe von Benutzername und Passwort. Der Browser zeigt ein Eingabefenster für die Anmeldedaten an, im Code muss dies jedoch explizit erfolgen.
Falsches URL-Format
Ein häufiger Fehler ist das Weglassen des Schemas oder die falsche Maskierung von Sonderzeichen:
# Falsch
proxy = "user:pass@proxy.example.com:8080"
# Richtig
proxy = "http://user:pass@proxy.example.com:8080"
# Wenn das Passwort Sonderzeichen enthält (@, :, /)
from urllib.parse import quote
password = quote("p@ss:word/123", safe="")
proxy = f"http://user:{password}@proxy.example.com:8080"
Authentifizierung per IP vs. Benutzername/Passwort
Einige Proxy-Anbieter verwenden eine Whitelist basierend auf der IP-Adresse. Der Browser auf Ihrem Computer funktioniert, weil Ihre IP zur Whitelist hinzugefügt wurde. Das Skript auf einem Server funktioniert jedoch nicht, da der Server eine andere IP-Adresse hat.
Überprüfen Sie im Dashboard des Anbieters, welche Authentifizierungsmethode verwendet wird und welche IPs zur Whitelist hinzugefügt sind.
Inkompatibilität der Protokolle HTTP/HTTPS/SOCKS
Der Browser erkennt den Proxypunkt oft automatisch. Im Code muss der Typ explizit angegeben werden, und ein Fehler im Protokoll führt zu einer stillschweigenden Ablehnung.
| Proxypunkt | Schema in der URL | Besonderheiten |
|---|---|---|
| HTTP Proxy | http:// |
Funktioniert für HTTP und HTTPS via CONNECT |
| HTTPS Proxy | https:// |
Verschlüsselte Verbindung zum Proxy |
| SOCKS4 | socks4:// |
Ohne Authentifizierung, nur IPv4 |
| SOCKS5 | socks5:// |
Mit Authentifizierung, UDP, IPv6 |
| SOCKS5h | socks5h:// |
DNS-Auflösung über den Proxy |
Es ist entscheidend: Wenn Sie einen SOCKS5-Proxy haben, aber http:// angeben, wird die Verbindung nicht hergestellt. Die Bibliothek versucht, über das HTTP-Protokoll mit dem SOCKS-Server zu kommunizieren.
Fehlende Header und Fingerprinting
Selbst wenn der Proxy korrekt funktioniert, kann die Zielseite die Anfrage aufgrund verdächtiger Header blockieren. Vergleichen Sie:
Anfrage aus dem Browser
GET /api/data HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Standardanfrage mit requests
GET /api/data HTTP/1.1
Host: example.com
User-Agent: python-requests/2.28.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Der Unterschied ist offensichtlich. Eine Seite mit Anti-Bot-Schutz erkennt sofort, dass die Anfrage nicht von einem Browser stammt.
Minimaler Satz von Headern zur Tarnung
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"Cache-Control": "max-age=0"
}
SSL-Zertifikate und Verifizierung
Der Browser verfügt über einen integrierten Speicher für Stammzertifikate und kann verschiedene SSL-Konfigurationen verarbeiten. Im Code können Probleme auftreten:
SSL-Fehler: CERTIFICATE_VERIFY_FAILED
Einige Proxys verwenden eigene Zertifikate zur Verkehrsinspektion. Ihr Browser hat dieses Zertifikat möglicherweise als vertrauenswürdig eingestuft, Ihr Skript jedoch nicht.
# Temporäre Lösung zum Debuggen (NICHT für die Produktion!)
import requests
response = requests.get(url, proxies=proxies, verify=False)
# Korrekte Lösung – Pfad zum Zertifikat angeben
response = requests.get(url, proxies=proxies, verify="/path/to/proxy-ca.crt")
Wichtig: Das Deaktivieren der SSL-Verifizierung (
verify=False) macht die Verbindung anfällig für MITM-Angriffe. Verwenden Sie dies nur zum Debuggen in einer sicheren Umgebung.
TLS Fingerprint
Fortgeschrittene Anti-Bot-Systeme analysieren den TLS-Fingerabdruck – die Reihenfolge und den Satz von Chiffren bei der Verbindungsherstellung. Python requests verwendet einen Standardsatz, der sich von dem des Browsers unterscheidet.
Um dies zu umgehen, verwenden Sie Bibliotheken mit einem benutzerdefinierten TLS-Fingerabdruck:
# Installation: pip install curl-cffi
from curl_cffi import requests
response = requests.get(
url,
proxies={"https": proxy},
impersonate="chrome120" # Imitiert den TLS-Fingerabdruck von Chrome 120
)
DNS-Lecks und Auflösung
Ein weiteres nicht offensichtliches Problem ist die DNS-Auflösung. Bei der Verwendung eines HTTP-Proxys kann die DNS-Anfrage direkt von Ihrer Maschine gesendet werden und den Proxy umgehen.
Wie sich dies auf die Funktion auswirkt
- Die Website sieht den tatsächlichen DNS-Resolver und nicht den Proxy
- Die Geolokalisierung wird falsch bestimmt
- Einige Websites blockieren die Nichtübereinstimmung zwischen IP und DNS-Region
Lösung für SOCKS5
Verwenden Sie das Schema socks5h:// anstelle von socks5:// – der Buchstabe "h" bedeutet, dass die DNS-Auflösung auf der Proxy-Seite erfolgt:
# DNS wird lokal aufgelöst (Leck!)
proxy = "socks5://user:pass@proxy.example.com:1080"
# DNS wird über den Proxy aufgelöst (korrekt)
proxy = "socks5h://user:pass@proxy.example.com:1080"
Funktionierende Beispiele für Python, Node.js und cURL
Python mit requests
import requests
from urllib.parse import quote
# Proxy-Daten
proxy_host = "proxy.example.com"
proxy_port = "8080"
proxy_user = "username"
proxy_pass = quote("p@ssword!", safe="") # Sonderzeichen maskieren
# Proxy-URL erstellen
proxy_url = f"http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}"
proxies = {
"http": proxy_url,
"https": proxy_url
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
}
try:
response = requests.get(
"https://httpbin.org/ip",
proxies=proxies,
headers=headers,
timeout=30
)
print(f"Status: {response.status_code}")
print(f"IP: {response.json()}")
except requests.exceptions.ProxyError as e:
print(f"Proxy-Fehler: {e}")
except requests.exceptions.ConnectTimeout:
print("Timeout beim Verbindungsaufbau zum Proxy")
Python mit aiohttp (Asynchron)
import aiohttp
import asyncio
async def fetch_with_proxy():
proxy_url = "http://user:pass@proxy.example.com:8080"
async with aiohttp.ClientSession() as session:
async with session.get(
"https://httpbin.org/ip",
proxy=proxy_url,
headers={"User-Agent": "Mozilla/5.0..."}
) as response:
return await response.json()
result = asyncio.run(fetch_with_proxy())
print(result)
Node.js mit axios
const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');
const proxyUrl = 'http://user:pass@proxy.example.com:8080';
const agent = new HttpsProxyAgent(proxyUrl);
axios.get('https://httpbin.org/ip', {
httpsAgent: agent,
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...'
}
})
.then(response => console.log(response.data))
.catch(error => console.error('Error:', error.message));
Node.js mit node-fetch und SOCKS
const fetch = require('node-fetch');
const { SocksProxyAgent } = require('socks-proxy-agent');
const agent = new SocksProxyAgent('socks5://user:pass@proxy.example.com:1080');
fetch('https://httpbin.org/ip', { agent })
.then(res => res.json())
.then(data => console.log(data));
cURL
# HTTP Proxy
curl -x "http://user:pass@proxy.example.com:8080" \
-H "User-Agent: Mozilla/5.0..." \
https://httpbin.org/ip
# SOCKS5 Proxy mit DNS über Proxy
curl --socks5-hostname "proxy.example.com:1080" \
--proxy-user "user:pass" \
https://httpbin.org/ip
# Debugging – den gesamten Verbindungsprozess anzeigen
curl -v -x "http://user:pass@proxy.example.com:8080" \
https://httpbin.org/ip
Diagnose-Checkliste
Wenn der Proxy im Code nicht funktioniert, überprüfen Sie die folgenden Punkte der Reihe nach:
- Proxy-URL-Format – Ist das Schema (http://, socks5://) vorhanden?
- Sonderzeichen im Passwort – Sind diese URL-kodiert?
- Proxypunkt – Stimmt das angegebene Protokoll mit dem tatsächlichen überein?
- Authentifizierung – Erfolgt die Authentifizierung per IP oder per Login? Ist die IP des Servers in der Whitelist?
- Header – Wurden Browser-Header wie User-Agent hinzugefügt?
- SSL – Gibt es Zertifikatsfehler?
- DNS – Wird socks5h:// verwendet, um die Auflösung über den Proxy zu erzwingen?
- Timeouts – Ist genügend Zeit für den Verbindungsaufbau eingeräumt (besonders bei Residenz-Proxys)?
Fazit
Der Unterschied zwischen Browser und Code liegt in den Details: Header, Protokolle, SSL, DNS. Der Browser verbirgt diese Komplexität, während im Code jeder Aspekt explizit konfiguriert werden muss. Beginnen Sie mit der Überprüfung des URL-Formats und der Authentifizierung und fügen Sie dann die Browser-Header hinzu – dies löst 90 % der Probleme.
Für Web-Scraping- und Automatisierungsaufgaben, bei denen Stabilität und eine geringe Sperrquote wichtig sind, eignen sich Residenz-Proxys hervorragend – mehr darüber erfahren Sie auf proxycove.com.