Rotazione Proxy in Crawlee per Python: Guida Pratica per Sviluppatori

Scopri come configurare la rotazione proxy in Crawlee per Python con ProxyConfiguration, SessionPool e proxy residenziali ProxyHat. Esempi di codice pronti all'uso e pattern di produzione.

Proxy Rotation in Crawlee for Python: A Developer's Guide to Residential Proxies
In questo articolo

La rotazione proxy in Crawlee per Python è una delle competenze più richieste da chi costruisce crawler di produzione. Se hai mai visto il tuo scraper bloccato dopo 50 richieste da un firewall WAF come Cloudflare o DataDome, sai quanto sia fragile un setup senza gestione intelligente degli IP. Crawlee — il framework open-source di Apify — offre strumenti nativi per affrontare il problema: ProxyConfiguration, SessionPool e un sistema di autoscaling che insieme permettono di distribuire il traffico su dozzine di IP residenziali mantenendo cookie e fingerprint coerenti. In questa guida esploriamo ogni punto di estensione del framework, con codice runnable che usa i gateway ProxyHat.

Nota legale: il web scraping di dati pubblici è generalmente lecito, ma l'accesso non autorizzato a sistemi protetti può violare legali come il Computer Fraud and Abuse Act (CFAA) negli USA o il GDPR in Europa. Rispetta sempre i robots.txt, i termini di servizio e i limiti di frequenza. Preferisci API ufficiali quando disponibili.

Rotazione proxy in Crawlee per Python: il quadro generale

Crawlee per Python (crawlee.dev/python) è il successore spirituale dell'Apify SDK, riscritto come framework standalone con un'architettura modulare. Due crawler principali gestiscono il grosso del lavoro:

  • BeautifulSoupCrawler — HTTP puro con parsing via BeautifulSoup o lxml. Veloce, leggero, ideale per siti statici.
  • PlaywrightCrawler — browser headless via Playwright. Necessario per SPA, contenuti renderizzati lato client o sfide JavaScript anti-bot.

Entrambi i crawler condividono la stessa infrastruttura: una code di richieste unificata (RequestQueue o RequestList), un pool di sessioni (SessionPool) che lega cookie, fingerprint e IP proxy, e un autoscaled pool che regola la concorrenza in base alle prestazioni. La rotazione proxy non è un hack esterno: si integra a livello di configurazione del crawler, e il framework la propaga automaticamente a ogni richiesta.

BeautifulSoupCrawler vs PlaywrightCrawler: quando scegliere

Il BeautifulSoupCrawler effettua richieste HTTP dirette — tipicamente 200-500ms per pagina su una connessione proxy residenziale. Il PlaywrightCrawler avvia un'istanza Chromium completa, con overhead di 2-5 secondi per pagina. La regola è semplice: se il contenuto è nel HTML iniziale, usa BeautifulSoup. Se il sito richiede esecuzione JavaScript o supera sfide anti-bot dinamiche, passa a Playwright. Molti team mantengono entrambi: BeautifulSoup per il 90% del volume, Playwright per i casi problematici.

SessionPool: il cuore della gestione sessioni in Crawlee

Il crawlee session pool è il componente che distingue Crawlee da un semplice wrapper HTTP. Ogni Session nel pool mantiene:

  • Cookie accumulati durante la navigazione
  • Un ID univoco usato per pinning dell'IP proxy
  • Stato (attiva, bloccata, ritirata)
  • Contatori di errori e successo

Quando il crawler assegna una sessione a una richiesta, usa l'ID della sessione per ottenere un proxy coerente da ProxyConfiguration. Questo significa che lo stesso IP residenziale naviga attraverso più pagine dello stesso dominio, mantenendo i cookie validi — esattamente come un utente reale. Se la sessione viene bloccata (session.retire()), il pool genera una nuova sessione con un nuovo IP.

ProxyConfiguration: l'approccio idiomatico in Crawlee python proxy

La classe ProxyConfiguration è il punto di estensione centrale per la gestione dei proxy. Si costruisce una volta e si passa al crawler:

from crawlee.proxy_configuration import ProxyConfiguration

# Rotazione round-robin tra endpoint ProxyHat
proxy_configuration = ProxyConfiguration(
    proxy_urls=[
        'http://user-country-US:pass@gate.proxyhat.com:8080',
        'http://user-country-DE:pass@gate.proxyhat.com:8080',
        'http://user-country-GB:pass@gate.proxyhat.com:8080',
    ]
)

# new_url(session_id=...) pinna un IP a una sessione specifica
proxy_url = await proxy_configuration.new_url(session_id='abc123')

Il metodo new_url(session_id=...) è la chiave della rotazione session-bound. Quando passi un session_id, ProxyConfiguration restituisce deterministicamente lo stesso URL proxy per quello stesso ID. Senza session_id, ruota round-robin tra gli URL configurati. Questo è esattamente ciò che serve per i proxy residenziali ProxyHat: l'ID di sessione nel username ProxyHat (es. user-country-US-session-abc123) mantiene lo stesso IP per tutta la durata della sessione Crawlee.

Rotazione round-robin vs session-bound: quale usare

Round-robin (senza session_id) va bene per richieste stateless: API pubbliche, endpoint REST, pagine che non richiedono login. Ogni richiesta ottiene un IP diverso, massimizzando la distribuzione.

Session-bound (con session_id) è indispensabile per: siti con login, carrelli e-commerce, navigazione multi-pagina dove i cookie devono persistere, e qualsiasi target che profila il comportamento dell'IP nel tempo. Senza session-bound, i cookie raccolti su un IP verrebbero inviati da un IP diverso alla richiesta successiva — un segnale immediato di bot.

Proxy residenziali vs datacenter: Cloudflare, DataDome e fallback a livelli

I sistemi anti-bot moderni come Cloudflare Bot Management e DataDome non si limitano a controllare gli header HTTP. Analizzano la reputazione dell'IP, il ASN di provenienza, la coerenza tra IP dichiarato e fingerprint del browser, e pattern comportamentali. Un IP datacenter con ASN di AWS o DigitalOcean è un segnale immediato: nessun utente reale naviga da un IP di un datacenter.

I proxy residenziali usano IP assegnati a dispositivi consumer reali (ISP domestici), rendendo il traffico indistinguibile da quello umano. Il costo è maggiore — tipicamente $3-15 per GB contro $0.5-2 per GB dei datacenter — ma il tasso di successo su target protetti passa dal 30-50% al 90%+.

Caratteristica Proxy Residenziali Proxy Datacenter Proxy Mobile
Overhead di latenza 50-200ms <50ms 200-500ms
Resistenza anti-bot Alta Bassa Molto alta
Persistenza sessione IP Fino a 72 ore N/A (rotazione per richiesta) 10-30 minuti
Costo indicativo per GB $3-15 $0.5-2 $10-30
Concorrenza raccomandata 50-100 sessioni 100-500 10-30

Strategia di fallback a livelli (tiered proxies)

Un pattern di produzione efficace usa proxy a livelli: inizia con datacenter per minimizzare i costi, e passa a residenziali solo quando rilevi blocchi. In Crawlee, questo si implementa combinando più ProxyConfiguration o gestendo il fallback nel request_handler:

from crawlee.proxy_configuration import ProxyConfiguration

# Tier 1: datacenter per traffico ad alto volume, basso rischio
dc_proxies = [
    'http://dc-user:pass@gate.proxyhat.com:8080',
]

# Tier 2: residenziali per target protetti
res_proxies = [
    f'http://user-country-US-session-{i}:pass@gate.proxyhat.com:8080'
    for i in range(20)
]

# Crawlee ruota tra tutti gli URL; ordina per priorità
tiered_config = ProxyConfiguration(
    proxy_urls=res_proxies + dc_proxies,
)

Per un controllo più fine, puoi implementare un middleware personalizzato che monitora il tasso di successo per configurazione e cambia dinamicamente. L'approccio più semplice in Crawlee è gestire il fallback nel request_handler: se una richiesta con proxy datacenter riceve 403, ritira la sessione e lascia che il pool ne crei una nuova — che potrebbe pescare un URL residenziale.

Esempio runnable: BeautifulSoupCrawler con ProxyConfiguration e ProxyHat

Ecco un esempio completo che usa crawlee proxyconfiguration con endpoint ProxyHat geo-localizzati e sessioni pin-nate. Il codice genera username per-sessione nel formato ProxyHat (user-country-US-session-{id}), permettendo al SessionPool di mantenere lo stesso IP residenziale per tutta la durata di una sessione.

import random
import string
from crawlee.beautifulsoup_crawler import (
    BeautifulSoupCrawler,
    BeautifulSoupCrawlingContext,
)
from crawlee.proxy_configuration import ProxyConfiguration

GATEWAY = 'gate.proxyhat.com'
PORT = 8080
BASE_USER = 'your_proxyhat_username'
PASSWORD = 'your_proxyhat_password'


def gen_session_id() -> str:
    """Genera un ID sessione alfanumerico di 12 caratteri."""
    return ''.join(random.choices(string.ascii_lowercase + string.digits, k=12))


def build_proxy_url(session_id: str | None = None) -> str:
    """Costruisce un URL proxy ProxyHat con geo-targeting US e sessione pin-nata."""
    sid = session_id or gen_session_id()
    username = f'{BASE_USER}-country-US-session-{sid}'
    return f'http://{username}:{PASSWORD}@{GATEWAY}:{PORT}'


# Pre-genera 10 URL proxy con sessioni distinte
proxy_urls = [build_proxy_url(gen_session_id()) for _ in range(10)]

proxy_configuration = ProxyConfiguration(proxy_urls=proxy_urls)

crawler = BeautifulSoupCrawler(
    proxy_configuration=proxy_configuration,
    max_request_retries=3,
    max_concurrency=10,
)


@crawler.router.default_handler
async def handle_page(context: BeautifulSoupCrawlingContext) -> None:
    title_tag = context.soup.find('title')
    title = title_tag.text.strip() if title_tag else 'N/A'

    session_id = context.session.id if context.session else 'no-session'
    context.log.info(
        f'URL: {context.request.url} | '
        f'Session: {session_id} | '
        f'Title: {title}'
    )

    # Enqueue link interni per crawling continuativo
    await context.enqueue_links()


await crawler.run(['https://example.com'])

Generazione di username per-sessione con il formato ProxyHat

Il formato del username ProxyHat è potente perché permette di codificare geo-targeting e sessione direttamente nelle credenziali proxy. La sintassi è:

# Geo-targeting per paese
http://user-country-US:pass@gate.proxyhat.com:8080

# Geo-targeting per città
http://user-country-DE-city-berlin:pass@gate.proxyhat.com:8080

# Sessione pin-nata (IP stabile)
http://user-session-abc123:pass@gate.proxyhat.com:8080

# Combinato: paese + sessione
http://user-country-US-session-abc123:pass@gate.proxyhat.com:8080

Quando il SessionPool di Crawlee crea una nuova sessione con ID xyz789, e il ProxyConfiguration chiama new_url(session_id='xyz789'), l'URL risultante include session-xyz789 nel username. ProxyHat assegna allora lo stesso IP residenziale a tutte le richieste che usano quel session ID — tipicamente per fino a 72 ore consecutive.

Consulta la documentazione ufficiale ProxyHat per i dettagli sulla persistenza delle sessioni e i parametri disponibili. Per le location supportate, visita la pagina delle posizioni ProxyHat.

Pattern di produzione: session.retire(), retry e concorrenza nel crawlee session pool

Configurare i proxy è solo l'inizio. Un crawler di produzione deve gestire blocchi, timeout, concorrenza e retry in modo elegante. Crawlee offre hook specifici per ognuno di questi aspetti.

Gestione dei blocchi con session.retire()

Quando una richiesta riceve 403, 429 o un contenuto che indica un CAPTCHA, la risposta corretta non è solo ritentare — è ritirare la sessione. session.retire() marca la sessione come compromessa, libera l'IP associato e fa sì che il pool crei una sessione fresca con un nuovo proxy:

from crawlee.beautifulsoup_crawler import BeautifulSoupCrawlingContext


@crawler.router.default_handler
async def handler(context: BeautifulSoupCrawlingContext) -> None:
    status = context.http_response.status_code

    if status in (403, 429):
        context.log.warning(
            f'Blocco {status} su {context.request.url} — '
            f'ritiro la sessione'
        )
        if context.session:
            context.session.retire()
        # Non processare la pagina; il retry userà una nuova sessione
        return

    soup = context.soup
    # ... estrai i dati
    await context.enqueue_links()

max_request_retries e gestione degli errori

Il parametro max_request_retries=3 sul crawler definisce quante volte ritentare una richiesta fallita prima di scartarla. Crawlee incrementa un contatore di retry per ogni richiesta e usa un backoff esponenziale tra i tentativi. Se una richiesta fallisce 3 volte consecutive, viene spostata in una code di fallimenti (RequestQueue.failed) e il crawler continua con le altre.

Per logica di retry personalizzata, puoi sovrascrivere error_handler nel crawler:

async def on_error(context, error):
    context.log.error(
        f'Errore su {context.request.url}: {type(error).__name__}: {error}'
    )
    # Logica custom: notifica, metriche, fallback a PlaywrightCrawler

crawler = BeautifulSoupCrawler(
    proxy_configuration=proxy_configuration,
    max_request_retries=3,
    error_handler=on_error,
)

Concorrenza e autoscaling

Crawlee include un autoscaled pool che regola dinamicamente la concorrenza in base al tasso di successo. Se le richieste falliscono frequentemente, il pool riduce i worker; se tutto va liscio, scala fino a max_concurrency. Per i proxy residenziali ProxyHat, una configurazione ragionevole è:

  • max_concurrency=10-50 per BeautifulSoupCrawler su target moderati
  • max_concurrency=5-10 per PlaywrightCrawler (ogni worker usa un browser)
  • max_concurrency=100+ per API pubbliche con proxy datacenter

Scaling con container: headless fleet

Per volumi che superano le capacità di un singolo processo, il pattern standard è containerizzare il crawler e eseguire multiple istanze. Ogni container esegue un'istanza indipendente di Crawlee con il proprio SessionPool e ProxyConfiguration. La code di richieste può essere condivisa via storage distribuito (Redis, o il RequestQueue gestito di Apify). Con 10 container a 50 sessioni concorrenti ciascuno, si raggiungono 500 sessioni attive — sufficienti per la maggior parte dei casi d'uso di web scraping e SERP tracking.

Per il deployment containerizzato, un'immagine Docker tipica include Python 3.11+, Crawlee, Playwright con dipendenze browser, e le variabili d'ambiente per le credenziali ProxyHat. Il gateway gate.proxyhat.com:8080 supporta 100+ sessioni concorrenti per account, con un uptime dichiarato del 99.9%.

Quando NON usare il browser crawling, e considerazioni etiche

Il PlaywrightCrawler è potente ma costoso: ogni pagina consuma 200-500MB di RAM e 2-5 secondi di tempo. Prima di raggiungerlo, considera:

  1. Il contenuto è nel HTML iniziale? Usa BeautifulSoupCrawler. Molte SPA espongono i dati in chiamate API JSON separate — intercetta quelle invece di renderizzare la pagina.
  2. Esiste un'API ufficiale? Molte piattaforme (Reddit, Twitter/X, Amazon) offrono API con rate limit generosi. Un'API ufficiale è sempre più affidabile e legalmente sicura del scraping.
  3. Il sito blocca solo per comportamento, non per JavaScript? Headers HTTP corretti (User-Agent realistici, Accept-Language, Referer) con BeautifulSoupCrawler spesso bastano.

Dal punto di vista etico e legale, rispetta sempre il RFC 9309 sul protocollo robots.txt — è lo standard IETF che definisce come i crawler devono interpretare le direttive di esclusione. Crawlee non applica automaticamente i robots.txt: devi implementare il controllo nel tuo handler o usare un middleware. Implementa anche rate limiting rispettoso: 1 richiesta ogni 2-5 secondi per dominio è una buona pratica per siti senza ToS espliciti.

Key Takeaways

  • ProxyConfiguration è il punto di estensione idiomatico per la rotazione proxy in Crawlee. Usa new_url(session_id=...) per pinning IP per-sessione, senza session_id per round-robin.
  • SessionPool lega cookie, fingerprint e IP proxy. Quando ritiri una sessione con session.retire(), il pool crea una nuova sessione con un nuovo IP — non devi gestire la rotazione manualmente.
  • I proxy residenziali battono i datacenter sui target protetti (Cloudflare, DataDome). Usa proxy a livelli: datacenter per traffico ad alto volume, residenziali per fallback sui blocchi.
  • Il formato username ProxyHat (user-country-US-session-abc123) codifica geo-targeting e sessione direttamente nelle credenziali — si integra nativamente con il session_id di Crawlee.
  • Autoscaling e containerizzazione permettono di scalare da 10 a 500+ sessioni concorrenti. Configura max_concurrency in base al tipo di proxy e crawler.
  • Etica prima di tutto: rispetta robots.txt, rate limit e ToS. Preferisci API ufficiali quando disponibili.

Configura ProxyHat con Crawlee

ProxyHat offre proxy residenziali, datacenter e mobile con geo-targeting per oltre 90 paesi. Il gateway gate.proxyhat.com:8080 è compatibile nativamente con ProxyConfiguration di Crawlee — basta inserire l'URL nel parametro proxy_urls. Consulta il prezzario ProxyHat per i piani disponibili, o visita la documentazione per i dettagli tecnici completi.

Domande frequenti

Cos'è la rotazione proxy in Crawlee per Python?

La rotazione proxy in Crawlee per Python è la gestione automatica degli IP proxy durante il web scraping, implementata tramite la classe ProxyConfiguration. Crawlee distribuisce le richieste su più URL proxy, pinna gli IP alle sessioni tramite new_url(session_id=...) e ritira automaticamente le sessioni bloccate. Il SessionPool lega cookie, fingerprint e IP proxy in modo che ogni sessione mantenga un'identità coerente, esattamente come un utente reale.

Perché la rotazione proxy in Crawlee per Python è importante per gli utenti di proxy?

Senza rotazione proxy, un crawler esaurisce rapidamente il limite di richieste per IP imposto dai siti target, ricevendo blocchi 403 o 429 dopo poche decine di richieste. La rotazione proxy distribuisce il traffico su multipli IP, riducendo il rischio di blocco dal 70% al 10% su target non protetti e dal 50% al 5% su target con anti-bot come Cloudflare. Inoltre, il pinning session-bound mantiene i cookie validi attraverso più pagine, evitando di inviare cookie raccolti su un IP da un IP diverso.

Quale tipo di proxy funziona meglio per la rotazione proxy in Crawlee per Python?

I proxy residenziali sono la scelta migliore per target protetti da anti-bot come Cloudflare o DataDome, perché usano IP assegnati a ISP domestici reali e sono indistinguibili dal traffico umano. I proxy datacenter sono più economici e veloci (latenza sotto 50ms) ma vengono bloccati facilmente dai WAF moderni. Una strategia ottimale usa proxy a livelli: datacenter per traffico ad alto volume su target non protetti, residenziali come fallback quando si rilevano blocchi 403 o 429.

Come evitare i blocchi implementando la rotazione proxy in Crawlee per Python?

Per evitare i blocchi: usa session.retire() quando ricevi 403 o 429 per liberare l'IP compromesso e generarne uno nuovo; configura max_request_retries=3 per ritentare con sessioni fresche; imposta max_concurrency tra 10 e 50 per proxy residenziali; usa geo-targeting per matchare la location del target; implementa header HTTP realistici (User-Agent, Accept-Language, Referer); e rispetta rate limit di 1 richiesta ogni 2-5 secondi per dominio. Combina proxy residenziali con session-bound rotation per massimizzare il tasso di successo.

Verifica la tua configurazione proxy in pochi secondi

Verificatore di proxy gratuito — conferma che i tuoi IP siano veloci, anonimi e non bloccati.

Controlla i proxy gratis
← Torna al Blog