Zonder KYC — geen ID, geen selfie, geen documenten. Betaal met crypto: BTC, USDT, USDC, ETH, SOL, LTC
Taal: Nederlands
Aan de slag

Docs · Python 3.9+ · requests · httpx · aiohttp

Rotating residentiële proxy's in Python: requests, httpx en aiohttp

Productiepatronen, geen one-liners: retries die Retry-After respecteren, een nieuw IP per verzoek of één IP per flow, per-host concurrency in asyncio, en de bytes die elke pagina werkelijk kost.

Laatst bijgewerkt: · 7 min leestijd

Kort antwoord

Hoe gebruik ik rotating residentiële proxy's in Python?

Geef http://USERNAME:[email protected]:7777 door als proxy voor zowel http als https in requests, als proxy= in httpx 0.26+, of als proxy= per verzoek in aiohttp. CrawlRelay residentiële proxy's roteren bij elke nieuwe verbinding en blijven sticky met -session-<id> in de gebruikersnaam. Ze kosten US$ 1,50 voor 1 GB en US$ 0,50/GB vanaf 50 GB. Betaald in crypto, zonder KYC.

Python setup in één oogopslag

requestsproxies={"http": url, "https": url}; retries via urllib3 Retry
httpxhttpx.Client(proxy=url); het oude proxies= argument is verwijderd in httpx 0.28
aiohttpsession.get(url, proxy="http://USER:PASS@host:port"), inloggegevens in de proxy URL
SOCKS5pip install "requests[socks]" of httpx[socks], daarna socks5h:// op poort 7778
Nieuw IP per verzoekSchakel keep-alive uit: Connection: close, max_keepalive_connections=0 of force_close=True
Zelfde IP voor een flow-session-<id>-ttl-<minutes> in de gebruikersnaam, tot 30 minuten
Proxy URL schemaAltijd http:// voor de HTTP-poort, ook voor HTTPS-websites

Hoe gebruik ik een proxy met requests, met retries die Retry-After respecteren?

Monteer een HTTPAdapter met urllib3's Retry op een Session. Het herhaalt verbindingsfouten en de statussen die je lijst, wacht met exponentiële backoff, en respecteert de Retry-After-header die sites sturen bij 429 en 503. Stel trust_env = False in zodat een overgebleven HTTPS_PROXY variabele je proxy niet kan overschrijven.

requests + urllib3 Retry
import os

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

USER = os.environ.get("CRAWLRELAY_USER", "USERNAME-country-us")
PASSWORD = os.environ.get("CRAWLRELAY_PASSWORD", "PASSWORD")
PROXY = "http://%s:%[email protected]:7777" % (USER, PASSWORD)

retry = Retry(
    total=4,
    connect=2,
    backoff_factor=1.0,  # waits of 0 s, 2 s, 4 s, 8 s (Retry-After wins on 429/503)
    status_forcelist=(429, 502, 503, 504),
    allowed_methods=frozenset({"GET", "HEAD"}),
    respect_retry_after_header=True,
)

session = requests.Session()
session.trust_env = False  # ignore HTTP(S)_PROXY from the environment
session.mount("http://", HTTPAdapter(max_retries=retry))
session.mount("https://", HTTPAdapter(max_retries=retry))
session.proxies = {"http": PROXY, "https": PROXY}
session.headers["User-Agent"] = "ExampleCrawler/1.0 (+https://example.com/crawler-info)"
session.headers["Connection"] = "close"  # new connection per request, so usually a new exit IP

r = session.get("https://api.ipify.org", timeout=(10, 30))
print(r.status_code, r.text)

Hoe bouw ik veilige gerichte proxy-URL's?

Genereer de gebruikersnaam in één functie en valideer deze. Een typfout in een landcode of een niet-geëncodeerd teken in het wachtwoord veroorzaakt een 407 die eruitziet als een inlogprobleem. De helper hieronder houdt de gedocumenteerde volgorde aan (USERNAME-country-{cc}-state-{state}-city-{city}-zip-{zip}-asn-{asn}-session-{id}-ttl-{minutes}), weigert onbekende sleutels en URL-encodeert beide inloggegevens.

Gebruikersnaam bouwer en proxy URL
import re
from urllib.parse import quote

ORDER = ("country", "state", "city", "zip", "asn", "session", "ttl")
VALUE = re.compile(r"^[a-z0-9_]+$")


def build_username(base, **params):
    """build_username("USERNAME", country="us", city="new_york", session="job1", ttl=30)"""
    parts = [base]
    for key in ORDER:
        value = params.pop(key, None)
        if value is None:
            continue
        value = str(value).lower()
        if not VALUE.match(value):
            raise ValueError("bad value for %s: %r" % (key, value))
        if key == "ttl" and not 1 <= int(value) <= 30:
            raise ValueError("ttl must be 1 to 30 minutes")
        parts.append("%s-%s" % (key, value))
    if params:
        raise ValueError("unknown parameters: %s" % ", ".join(sorted(params)))
    return "-".join(parts)


def proxy_url(username, password, socks=False):
    scheme, port = ("socks5h", 7778) if socks else ("http", 7777)
    return "%s://%s:%[email protected]:%d" % (
        scheme, quote(username, safe=""), quote(password, safe=""), port)


print(proxy_url(build_username("USERNAME", country="us", state="ny", city="new_york", session="job1", ttl=20), "p@ss:word"))

Hoe krijg ik een nieuw IP bij elk verzoek met httpx?

Schakel keep-alive uit. httpx poolt standaard verbindingen, en een hergebruikte verbinding behoudt zijn exit IP. Met max_keepalive_connections=0 opent elk verzoek een nieuwe verbinding naar de gateway en verlaat die meestal via een andere residentiële IP. num_bytes_downloaded geeft de ontvangen bytes op de lijn, wat het dichtst bij de verkeersafrekening ligt.

httpx: roterende client
import httpx

PROXY = "http://USERNAME-country-gb:[email protected]:7777"

# No keep-alive: every request opens a new connection, so it usually gets a new exit IP
with httpx.Client(
    proxy=PROXY,
    timeout=httpx.Timeout(30.0, connect=10.0),
    limits=httpx.Limits(max_keepalive_connections=0),
    follow_redirects=True,
) as client:
    for _ in range(3):
        r = client.get("https://api.ipify.org")
        print(r.text, r.num_bytes_downloaded, "bytes on the wire")

Hoe scrape ik gelijktijdig met asyncio zonder één site te overladen?

Beperk concurrency per host, niet alleen globaal. Een globale limiet van 50 laat alle 50 verzoeken dezelfde site raken als je URL-lijst op domein is gesorteerd. Een semaphore per hostname houdt elke site op een beleefd niveau terwijl de crawl als geheel snel blijft. Begin met 2 tot 4 per host en lees de concurrency gids voordat je verhoogt.

httpx.AsyncClient met een semaphore per host
import asyncio
from collections import defaultdict
from urllib.parse import urlsplit

import httpx

PROXY = "http://USERNAME-country-us:[email protected]:7777"
PER_HOST = 4  # parallel requests per target host
host_slots = defaultdict(lambda: asyncio.Semaphore(PER_HOST))


async def fetch(client, url):
    async with host_slots[urlsplit(url).hostname]:
        try:
            r = await client.get(url)
            return url, r.status_code, r.num_bytes_downloaded
        except httpx.HTTPError as exc:
            return url, type(exc).__name__, 0


async def main(urls):
    limits = httpx.Limits(max_connections=50, max_keepalive_connections=0)
    timeout = httpx.Timeout(30.0, connect=10.0)
    async with httpx.AsyncClient(proxy=PROXY, limits=limits, timeout=timeout) as client:
        for result in await asyncio.gather(*(fetch(client, u) for u in urls)):
            print(*result)


asyncio.run(main(["https://example.com/", "https://example.org/", "https://example.net/"]))

Hoe gebruik ik een proxy met aiohttp?

Geef de gateway door als proxy= bij elk verzoek, met de inloggegevens in de proxy URL. Dat werkt zonder waarschuwingen bij elke aiohttp 3.x release; BasicAuth en de proxy_auth= parameter zijn verouderd sinds aiohttp 3.14 en worden verwijderd in 4.0. Een TCPConnector(force_close=True) sluit elke verbinding na de respons, zodat elk verzoek meestal een nieuwe exit krijgt. Zonder dit hergebruikt aiohttp verbindingen en behoud je tijdelijk hetzelfde IP.

aiohttp met inloggegevens in de proxy URL
import asyncio

import aiohttp

# Credentials go in the proxy URL; percent-encode a password that contains @ or :
PROXY = "http://USERNAME-country-fr:[email protected]:7777"


async def main():
    # force_close=True: one connection per request, so each request usually gets a new exit IP
    connector = aiohttp.TCPConnector(limit=20, force_close=True)
    timeout = aiohttp.ClientTimeout(total=60, sock_connect=10)
    async with aiohttp.ClientSession(connector=connector, timeout=timeout) as session:
        for _ in range(3):
            async with session.get("https://api.ipify.org", proxy=PROXY) as resp:
                print(resp.status, await resp.text())


asyncio.run(main())

Hoe houd ik één IP voor een multi-step flow?

Genereer één sessie-ID per flow en zet die in de gebruikersnaam met een TTL langer dan de flow. Keep-alive is hier prima: je wilt dezelfde exit. Als het residentiële apparaat achter de sessie offline gaat, kan het IP veranderen voordat de TTL afloopt, dus maak de flow herstartbaar vanaf het laatste checkpoint.

Sticky sessie met requests
import uuid

import requests

session_id = uuid.uuid4().hex[:10]  # one ID per flow, lowercase letters and digits
user = "USERNAME-country-us-state-ca-session-%s-ttl-20" % session_id
proxy = "http://%s:[email protected]:7777" % user

with requests.Session() as s:
    s.proxies = {"http": proxy, "https": proxy}
    first = s.get("https://api.ipify.org", timeout=(10, 30)).text
    second = s.get("https://api.ipify.org", timeout=(10, 30)).text
    print(first, second, "same exit" if first == second else "exit changed")

Hoeveel verkeer gebruikt een Python scraper per pagina?

Meet het op 100 echte pagina's voordat je volume koopt. Log num_bytes_downloaded in httpx, of de lengte van de gecomprimeerde body in je eigen middleware, en vermenigvuldig met je pagina-aantal. Alleen HTML-verzoeken kosten meestal tientallen kilobytes per pagina; de bandbreedte gids geeft de cijfers en de kosten per 1.000 pagina's tegen CrawlRelay prijzen.

Drie gewoontes verminderen verkeer zonder je resultaten te veranderen:

  • Verstuur Accept-Encoding: gzip, br (httpx en requests versturen standaard gzip) zodat pagina's gecomprimeerd reizen.
  • Haal de JSON-endpoint op die een pagina laadt, wanneer de site dit documenteert of toestaat, in plaats van de volledige HTML.
  • Sla ongewijzigde pagina's over met If-None-Match of If-Modified-Since: een 304 Not Modified kost enkele honderden bytes.

Python en proxy's: vragen

requests, httpx of aiohttp: welke moet ik gebruiken voor scraping?

Gebruik requests voor eenvoudige scripts en kleine crawls. Gebruik httpx als je dezelfde API wilt in synchrone en asynchrone code, en HTTP/2 via httpx[http2]. Gebruik aiohttp voor zeer hoge gelijktijdigheid in pure asyncio. Voor een crawl met planning, deduplicatie en pipelines gebruik je Scrapy in plaats van die onderdelen zelf te schrijven.

Waarom krijg ik SSL: WRONG_VERSION_NUMBER bij mijn proxy in Python?

Je hebt waarschijnlijk https:// voor het proxyadres gezet. De gatewaypoort 7777 spreekt gewoon HTTP en opent een CONNECT-tunnel voor HTTPS-sites, dus de proxy-URL moet in zowel de http als https sleutels met http:// beginnen. Zie de foutpagina.

Hoe gebruik ik SOCKS5 proxy's in Python?

Installeer de extra (pip install "requests[socks]" of pip install "httpx[socks]"), gebruik dan socks5h://USERNAME:[email protected]:7778. De h stuurt hostnamen naar de proxy, zodat DNS-resolutie bij de uitgang gebeurt en je dezelfde regionale antwoorden krijgt als lokale bezoekers.

Waarom geeft mijn roterende proxy twee keer hetzelfde IP terug?

Je client hergebruikte een keep-alive verbinding, terwijl rotatie per nieuwe verbinding gebeurt. Verstuur Connection: close in requests, stel max_keepalive_connections=0 in httpx in, of gebruik force_close=True in aiohttp. Controleer ook dat de gebruikersnaam geen session- onderdeel heeft, dat opzettelijk één IP behoudt.

Hoe stel ik time-outs in voor proxied requests?

Stel ze expliciet in: requests heeft standaard geen timeout. Een connect-timeout van ongeveer 10 seconden en een read-timeout van 30 seconden is geschikt voor HTML-pagina's; mobiele exits en trage doelen hebben 45 tot 60 seconden nodig. Probeer een timeout eenmaal opnieuw met een nieuwe verbinding in plaats van langer te wachten. Zie read timeouts.

Kan ik deze proxy's gebruiken in Jupyter of met pandas?

Ja. Alles wat requests of httpx gebruikt, neemt dezelfde proxy-instellingen over. Voor pandas.read_html of read_csv op een URL, download eerst de inhoud met een proxied requests-aanroep en geef dan de tekst of bytes aan pandas door.

Laat je Python scraper lopen via residentiële proxy's

US$ 1,50 voor 1 GB, US$ 0,50/GB vanaf 50 GB.

Vanaf US$ 0,50/GB · zonder KYC

Aan de slag