Se stai costruendo crawler di produzione con Crawlee per Python, prima o poi ti imbatterai in blocchi IP, challenge JavaScript e rate limiting. La rotazione proxy in Crawlee per Python non è un accessorio opzionale: è la differenza tra un crawler che raccoglie 10.000 pagine senza intoppi e uno che muore dopo 200 richieste con un 403. In questa guida vediamo come integrare proxy residenziali ProxyHat nel modo idiomatico — attraverso ProxyConfiguration, SessionPool e middleware nativi del framework — senza hack o workaround fragili.
Avviso legale: raccogli solo dati pubblicamente accessibili, rispetta
robots.txt, i limiti di frequenza e i Termini di Servizio. Il Computer Fraud and Abuse Act (CFAA) negli Stati Uniti e il GDPR in Europa possono applicarsi all'accesso non autorizzato o al trattamento di dati personali. Preferisci sempre API ufficiali quando disponibili.
Architettura di Crawlee per Python e ruolo della rotazione proxy
Crawlee per Python offre due motori principali: BeautifulSoupCrawler per richieste HTTP veloci e parsing HTML, e PlaywrightCrawler per rendering headless completo. Entrambi pescano da una coda di richieste unificata (RequestQueue o RequestList), condividendo la stessa infrastruttura di gestione sessioni, proxy e retry. L'autoscaling è integrato: il pool di worker si espande o si contrae in base alla CPU e alla memoria disponibili, fino a un limite configurabile.
Il cuore della gestione IP è il SessionPool. Ogni Session lega insieme cookie, fingerprint del browser (nel caso di Playwright) e un proxy URL. Quando una sessione viene ritirata (session.retire()), Crawlee scarta cookie e IP associati, creando una nuova identità pulita. Questo è il motivo per cui la crawlee session pool e la crawlee proxyconfiguration devono essere pensate insieme: una senza l'altra non basta.
Perché il SessionPool lega IP e cookie
I sistemi anti-bot come Cloudflare Bot Management e DataDome non guardano solo l'IP: correlano IP, header TLS, comportamento di navigazione e pattern di richieste. Se ruoti l'IP ma mantieni i cookie di una sessione bloccata, il nuovo IP eredita la reputazione compromessa. Crawlee risolve questo problema associando ogni sessione a un proxy unico, in modo che il ritiro di una sessione pulisca simultaneamente cookie e IP.
ProxyConfiguration: l'approccio idiomatico in Crawlee
La classe ProxyConfiguration è il punto di integrazione ufficiale per i proxy in Crawlee. Accetta una lista di URL proxy o una funzione generatrice, e fornisce il metodo new_url(session_id=...) che restituisce un URL proxy legato a una specifica sessione. Questo è fondamentale per i proxy residenziali: permette di pinmare un IP residenziale per sessione invece di ruotare ad ogni richiesta.
Due strategie principali:
- Round-robin: ogni richiesta ottiene un IP diverso. Utile per scraping massivo su target tolleranti, ma rompe la continuità delle sessioni (carrelli, login, paginazione autenticata).
- Session-bound (sticky): ogni
Sessionottiene un IP residenziale stabile tramitesession_id. L'IP cambia solo quando la sessione viene ritirata. Ideale per siti che richiedono coerenza IP-cookie.
Con ProxyHat, la rotazione si implementa direttamente nel username: il flag -session-abc123 pinma l'IP per quella sessione, mentre -country-US geolocalizza il traffico. Vediamo il codice.
Configurazione base di ProxyConfiguration con ProxyHat
Ecco un esempio minimale di crawlee python proxy con ProxyHat, usando il gateway HTTP su gate.proxyhat.com:8080:
from crawlee.proxy_configuration import ProxyConfiguration
# Genera URL proxy con IP residenziale statunitense
# e sessione pinmata per coerenza IP-cookie
proxy_config = ProxyConfiguration(
proxy_urls=[
'http://user-country-US-session-abc123:pass@gate.proxyhat.com:8080',
'http://user-country-US-session-def456:pass@gate.proxyhat.com:8080',
'http://user-country-US-session-ghi789:pass@gate.proxyhat.com:8080',
]
)
# new_url(session_id='abc123') restituisce sempre lo stesso URL proxy
# per quella session_id, garantendo IP stabile</pre></code>
<p>Quando passi <code>session_id='abc123'</code> a <code>new_url()</code>, Crawlee seleziona deterministicamente l'URL proxy corrispondente. Se invece ometti <code>session_id</code>, Crawlee fa round-robin tra gli URL disponibili. Per un controllo più fine, puoi passare una funzione custom a <code>ProxyConfiguration</code>.</p>
<h2>Esempio eseguibile: BeautifulSoupCrawler con proxy residenziali</h2>
<p>Vediamo un esempio completo di <strong>crawlee proxy rotation</strong> con <code>BeautifulSoupCrawler</code>, <code>ProxyConfiguration</code> e sessioni pinmate su IP residenziali ProxyHat:</p>
<pre><code>import asyncio
from crawlee.beautifulsoup_crawler import BeautifulSoupCrawler
from crawlee.proxy_configuration import ProxyConfiguration
from crawlee.sessions import SessionPool
def make_proxy_url(session_id: str) -> str:
"""Genera un URL proxy ProxyHat con IP residenziale US e sessione pinmata."""
return f'http://user-country-US-session-{session_id}:pass@gate.proxyhat.com:8080'
async def main():
# Configurazione proxy con generatore dinamico di URL per sessione
proxy_config = ProxyConfiguration(
proxy_urls=[make_proxy_url(f'sess-{i}') for i in range(20)]
)
crawler = BeautifulSoupCrawler(
proxy_configuration=proxy_config,
max_request_retries=3,
max_requests_per_crawl=500,
request_handler_timeout=60,
)
@crawler.router.default_handler
async def handler(request, session, soup):
title = soup.select_one('title')
print(f'[{session.id}] {request.url} -> {title.text if title else "N/A"}')
# Salva i dati estratti
await crawler.push_data({
'url': request.url,
'title': title.text if title else '',
})
await crawler.run(['https://example.com/page-1', 'https://example.com/page-2'])
if __name__ == '__main__':
asyncio.run(main())
In questo esempio, Crawlee assegna automaticamente una sessione ad ogni richiesta. Il SessionPool interno crea fino a 20 sessioni (una per ogni URL proxy), e ogni sessione mantiene il proprio IP residenziale stabile grazie al flag -session-sess-N nel username ProxyHat. Quando una sessione viene ritirata, il successivo new_url() per quella sessione genererà un nuovo endpoint.
Generazione dinamica di username per sessione
Per scalare a centinaia di sessioni, puoi generare gli URL proxy dinamicamente invece di hardcodarli. Ecco un pattern più avanzato che usa una funzione custom:
import hashlib
def proxy_url_generator():
"""Genera URL proxy unici per ogni sessione, con geo-targeting US."""
counter = 0
while True:
session_id = hashlib.md5(f'sess-{counter}'.encode()).hexdigest()[:12]
yield f'http://user-country-US-session-{session_id}:pass@gate.proxyhat.com:8080'
counter += 1
# Usa il generatore con ProxyConfiguration
proxy_config = ProxyConfiguration(
proxy_urls=list(proxy_url_generator())[:50] # 50 sessioni uniche
)
Questo pattern ti permette di generare 100 sessioni concorrenti o più, ciascuna con un IP residenziale distinto. La latenza tipica dei proxy residenziali ProxyHat si aggira tra 200–800 ms per richiesta, rispetto ai 50–150 ms dei datacenter — ma il trade-off vale la pena quando i target bloccano i range IP datacenter.
Perché i proxy residenziali battono i datacenter su Cloudflare e DataDome
I proxy datacenter offrono velocità e costi inferiori, ma i loro range IP appartengono a ASN noti (AWS, DigitalOcean, Hetzner). I sistemi anti-bot come Cloudflare Bot Management e DataDome mantengono database di ASN datacenter e assegnano automaticamente un punteggio di rischio elevato a queste richieste. Il risultato: challenge JavaScript, CAPTCHA o blocchi 403 immediati.
I proxy residenziali usano IP assegnati a ISP reali (Comcast, AT&T, Vodafone), con reputazione di traffico umano. Una richiesta da un IP residenziale statunitense con header coerenti e sessione stabile è statisticamente indistinguibile da un utente reale. Il tasso di successo tipico su target protetti passa dal 30–50% con datacenter al 85–95% con residenziali ben gestiti.
| Caratteristica | Proxy Datacenter | Proxy Residenziali |
|---|---|---|
| Latenza tipica | 50–150 ms | 200–800 ms |
| Costo per GB | $0.5–2 | $3–15 |
| Tasso di successo su Cloudflare | 30–50% | 85–95% |
| Rischio di blocco ASN | Alto | Basso |
| Coerenza sessione | Limitata | Ottima con sticky session |
Proxy a livelli (tiered fallback)
In produzione, una strategia efficace è il tiered proxy fallback: inizia con datacenter per target non protetti, passa a residenziali al primo segnale di blocco, e usa mobile proxy come ultima risorsa per i target più aggressivi. Crawlee supporta questo pattern tramite il ritiro dinamico delle sessioni e la rigenerazione dell'URL proxy.
from crawlee.sessions import Session
@crawler.router.default_handler
async def handler(request, session, soup, response):
# Rileva blocco: status 403, 429, o challenge page
if response.status_code in (403, 429):
print(f'Blocco rilevato su {request.url} — ritiro sessione {session.id}')
session.retire() # Scarta IP + cookie + fingerprint
raise ValueError(f'Blocked: {response.status_code}')
# Verifica presenza di challenge Cloudflare/DataDome nel HTML
if soup.select_one('#cf-challenge-running, #datadome-challenge'):
session.retire()
raise ValueError('Anti-bot challenge detected')
# Estrazione normale
title = soup.select_one('title')
await crawler.push_data({
'url': request.url,
'title': title.text if title else '',
})
Quando session.retire() viene chiamato, Crawlee marca la sessione come "retired" e non la riutilizza. La richiesta viene rimessa in coda e al prossimo tentativo riceve una nuova sessione con un nuovo IP residenziale. Con max_request_retries=3, Crawlee prova fino a 3 volte con sessioni diverse prima di dichiarare fallita la richiesta.
Pattern di produzione: concorrenza, retry e gestione errori
Concorrenza tramite autoscaled pool
Crawlee gestisce la concorrenza automaticamente attraverso l'AutoscaledPool. I parametri chiave sono max_concurrency (numero massimo di richieste parallele) e min_concurrency. Per proxy residenziali, ti consigliamo di partire con max_concurrency=10–20 e aumentare gradualmente monitorando il tasso di successo.
crawler = BeautifulSoupCrawler(
proxy_configuration=proxy_config,
max_request_retries=3,
max_requests_per_crawl=10000,
max_request_retries=3,
autoscaled_pool_options={
'max_concurrency': 15,
'min_concurrency': 5,
},
request_handler_timeout=60,
)
Gestione errori nel request_handler
Oltre al rilevamento di blocchi, il request_handler deve gestire timeout di rete, connessioni fallite e parsing error. Crawlee distingue tra errori retryable (network timeout, 503) e non retryable (404, parsing fallito). Sollevare un'eccezione nel handler mette automaticamente la richiesta in retry, a meno che tu non usi request.no_retry = True.
@crawler.router.default_handler
async def handler(request, session, soup, response):
try:
data = extract_data(soup)
if not data:
# Dato mancante: non ritentare, è un problema di contenuto
request.no_retry = True
return
await crawler.push_data(data)
except Exception as e:
# Errore generico: ritira sessione e ritenta
session.retire()
raise
Monitoraggio e metriche
In produzione, monitora almeno queste metriche:
- Tasso di successo per sessione (successi / tentativi totali).
- Latenza P50 e P95 per capire se i proxy sono il collo di bottiglia.
- Numero di sessioni attive vs ritirate per rilevare ban IP sistematici.
- Richieste al minuto per restare sotto i limiti di frequenza del target.
Se vedi più del 20% di sessioni ritirate in 5 minuti, il target sta bloccando aggressivamente. Riduci la concorrenza, aumenta il ritardo tra le richieste, o passa a proxy con geo-targeting più specifico (città invece di paese).
Quando NON usare il browser crawling
Il PlaywrightCrawler è potente ma costoso: ogni pagina richiede avvio del browser, rendering JavaScript, e consumo di memoria 10–50x superiore rispetto a BeautifulSoupCrawler. Usalo solo quando:
- Il contenuto è generato dinamicamente via JavaScript (SPA, React, Vue).
- Il target richiede interazione (click, scroll, compilazione form).
- I sistemi anti-bot richiedono un fingerprint browser completo.
Per la maggior parte dei casi di web scraping e SERP tracking, BeautifulSoupCrawler con proxy residenziali è sufficiente e 5–10x più veloce. Se il target serve il HTML completo nella risposta HTTP, il browser è sprecato.
Considerazioni etiche e legali
Prima di avviare qualsiasi crawler, verifica:
robots.txt: Crawlee può rispettare automaticamenterobots.txttramite configurazione. Non disabilitarlo senza motivo.- Termini di Servizio: molti siti proibiscono esplicitamente lo scraping. Leggi i ToS.
- Rate limiting: mantieni una frequenza ragionevole. 1–5 richieste al secondo per dominio è una buona regola empirica.
- Dati personali: il GDPR richiede base giuridica per il trattamento di dati personali. Se raccogli dati personali di utenti UE, consulta un legale.
- API ufficiali: se il target offre un'API, usala. È più stabile, più veloce e legalmente più sicura.
Configurazione ProxyHat in Crawlee
ProxyHat offre proxy residenziali, mobile e datacenter con geo-targeting a livello di paese e città. L'integrazione con Crawlee avviene interamente tramite ProxyConfiguration, senza SDK aggiuntivi. I parametri di connessione sono:
- Gateway HTTP:
gate.proxyhat.com:8080 - Gateway SOCKS5:
gate.proxyhat.com:1080 - Geo-targeting:
user-country-USouser-country-DE-city-berlin - Sessione pinmata:
user-session-abc123
Consulta la documentazione ufficiale ProxyHat per i dettagli completi sui parametri disponibili. Per i prezzi e i piani, visita la pagina prezzi di ProxyHat.
Key Takeaways
- SessionPool e ProxyConfiguration vanno pensati insieme: ogni sessione lega IP, cookie e fingerprint. Ritirare una sessione pulisce tutto simultaneamente.
- Usa
new_url(session_id=...)per IP stabili: i proxy residenziali con sessioni pinmate battono il round-robin su target protetti.- Residenziali > datacenter su Cloudflare/DataDome: il tasso di successo passa dal 30–50% all'85–95%.
- Chiama
session.retire()sui blocchi: non ritentare con la stessa sessione. Crawlee rimetterà la richiesta in coda con una sessione nuova.- Parti con BeautifulSoupCrawler: usa PlaywrightCrawler solo quando il rendering JS è indispensabile. Il costo in memoria è 10–50x superiore.
- Rispetta robots.txt, ToS e rate limit: il CFAA e il GDPR si applicano allo scraping. Preferisci API ufficiali quando disponibili.
FAQ
Cos'è la rotazione proxy in Crawlee per Python?
La rotazione proxy in Crawlee per Python è la gestione automatica degli IP proxy attraverso la classe ProxyConfiguration e il SessionPool. Crawlee assegna un proxy URL a ogni sessione, permettendo sia round-robin (IP diverso per richiesta) sia sticky session (IP stabile per sessione tramite new_url(session_id=...)). Il ritiro di una sessione scarta automaticamente IP e cookie associati.
Perché la rotazione proxy in Crawlee per Python è importante?
È importante perché i sistemi anti-bot come Cloudflare e DataDome correlano IP, cookie e fingerprint per rilevare bot. Senza rotazione, un singolo IP viene bloccato dopo poche richieste. Con proxy residenziali e sessioni pinmate, ogni sessione mantiene un'identità coerente che appare come traffico umano, aumentando il tasso di successo dal 30–50% al 85–95%.
Quale tipo di proxy funziona meglio per la rotazione in Crawlee?
I proxy residenziali funzionano meglio per target protetti da anti-bot, perché usano IP di ISP reali con reputazione di traffico umano. I proxy datacenter sono più veloci e economici ma vengono bloccati facilmente dai sistemi anti-bot che riconoscono gli ASN datacenter. Una strategia tiered (datacenter → residenziali → mobile) offre il miglior compromesso tra costo e affidabilità.
Come evitare i blocchi nella rotazione proxy con Crawlee?
Per evitare i blocchi: usa session.retire() quando rilevi status 403/429 o challenge anti-bot, mantieni max_request_retries=3 per ritentare con sessioni nuove, limita la concorrenza a 10–20 richieste parallele con proxy residenziali, rispetta i rate limit del target (1–5 req/s per dominio), e usa geo-targeting specifico (città invece di paese) quando possibile.






