Google est la cible grand public la plus difficile à scraper, et la raison est simple : il voit plus de trafic que n'importe qui, il dispose donc du modèle le plus riche de ce à quoi ressemble un véritable internaute. Frappez-le depuis une IP de centre de données à n'importe quel volume et vous obtenez un 429, une page « sorry/index » ou un blocage doux où les résultats s'amenuisent silencieusement. Ce guide couvre ce qui déclenche réellement les blocages de Google ainsi que la stratégie de proxy et de limitation de débit qui maintient en vie un scraper de SERP en 2026.
Google ne se fie pas à un seul signal : il en empile plusieurs et bannit lorsque le score combiné franchit un seuil :
Pour la plupart des cibles, vous pouvez vous en tirer avec des IP de centre de données sur des données publiques. Google est l'exception : sa notation de réputation d'ASN est assez agressive pour que les proxies de centre de données soient limités presque immédiatement. Les exits résidentiels — de vrais ASN de particuliers — sont ce qui permet à un scraper de SERP de tenir le volume. Réservez le centre de données pour tout le reste et dépensez le budget résidentiel là où il fait réellement la différence.
La rotation répartit la charge pour qu'aucune IP individuelle ne ressemble à un bot, mais la discipline qui vous maintient en vie, c'est le débit par exit, pas seulement la taille du pool. Mille proxies se font quand même bannir si vous les lancez tous à fond. Cadencez chaque exit comme une personne :
import time, random, itertools
from curl_cffi import requests # browser TLS fingerprint, see notes below
PROXIES = [
"socks5h://USERNAME:[email protected]:913",
"socks5h://USERNAME:[email protected]:913",
]
pool = itertools.cycle(PROXIES)
def serp(query, page=0):
proxy = next(pool)
params = {"q": query, "start": page * 10, "hl": "en"}
r = requests.get("https://www.google.com/search", params=params,
impersonate="chrome",
proxies={"http": proxy, "https": proxy}, timeout=30)
if r.status_code == 429 or "/sorry/" in r.url:
raise RuntimeError("rate-limited - back off and rotate")
return r.text
for q in queries:
html = serp(q)
parse(html)
time.sleep(random.uniform(2.0, 5.0)) # human-paced gap between queries
Le délai aléatoire fait un vrai travail : un sleep(3) fixe est lui-même une empreinte. Faites-le varier, et répartissez les requêtes entre les exits pour que chacun reste sous le seuil par IP de Google.
Les résultats localisés (classements, langue, devise) dépendent de l'emplacement de l'exit, alors choisissez des proxies dans la zone géographique que vous voulez mesurer et maintenez une session sticky (persistante) pendant une requête multi-pages pour que toutes les pages d'une même recherche viennent du même endroit. Mélanger les exits en cours de requête vous donne des résultats recousus depuis différentes régions : inutile pour le suivi de classement.
Google lit aussi votre handshake TLS. Un simple appel avec requests envoie un JA3 qui hurle Python, ce qui s'ajoute au score de l'IP. Envoyez une vraie empreinte de navigateur avec curl_cffi (utilisé ci-dessus) ou un vrai navigateur — voir Contourner le fingerprinting TLS avec curl_cffi. Si Google commence à dresser des barrières avec un mur de consentement JS, passez à un véritable moteur de navigateur comme expliqué dans le guide Turnstile — la même logique du « besoin d'un runtime JS » s'applique.
/sorry/ — cessez de frapper cet exit, faites tourner et appliquez un backoff exponentiel. Marteler une IP marquée prolonge le bannissement./sorry/ au lieu de réessayer vers un bannissement plus long.Les nouveaux utilisateurs reçoivent 500 Mo à l'inscription, plus un bonus sur la première recharge. Offre à durée limitée.