Scraping avancé : rate limits, sessions, nouvelles tentatives et rotation sans surcharger les sites
Publié le · 7 min de lecture
Un scraper qui fonctionne sur dix pages se grippe souvent sur dix mille : arrivent les 429, les captchas, les pages vides qui répondent 200. Le problème n'est presque jamais l'IP, mais la façon dont les requêtes arrivent au site. Cet article reprend les bases de [Web scraping avec des proxys](/blog/web-scraping-avec-proxys) et va un peu plus loin : comment bâtir une collecte de données qui tient dans la durée et reste légère pour les sites qu'elle visite.
Lire les signaux du site
Un site communique ses limites de plusieurs façons, et un scraper robuste les reconnaît toutes :
- 429 Too Many Requests : vous avez dépassé le rythme accepté. Il arrive souvent avec l'en-tête Retry-After, qui indique combien de temps attendre : un nombre de secondes ou une date. Voir aussi erreur 429.
- 503 Service Unavailable : le serveur est surchargé ou en maintenance. Retry-After peut aussi être présent.
- 403 Forbidden : l'accès est refusé. Répéter la même requête ne sert généralement à rien : vérifiez les en-têtes, la session et le rythme.
- En-têtes de quota : certaines API et certains sites indiquent les requêtes restantes avec des en-têtes comme X-RateLimit-Remaining. S'ils sont là, utilisez-les pour ralentir avant la limite.
- Blocages silencieux : la réponse est 200, mais contient un captcha, une page de consentement ou une liste vide. On ne les repère qu'en contrôlant le contenu.
Concurrence par domaine, pas requêtes par seconde
La charge ressentie par un site dépend du nombre de requêtes que vous avez ouvertes vers lui au même moment, pas du total sur une heure. C'est pourquoi le premier paramètre à régler est la concurrence par domaine : combien de requêtes parallèles vont vers le même site.
- Commencez bas : une ou deux requêtes parallèles par domaine, avec des pauses variables entre elles.
- Adaptez le rythme aux temps de réponse : si les pages répondent plus lentement, le serveur est chargé et mieux vaut ralentir.
- Respectez robots.txt : les règles d'accès sont standardisées (RFC 9309). La directive Crawl-delay ne fait pas partie du standard et Google l'ignore, mais lorsqu'un site l'indique, c'est un signal clair du rythme qu'il accepte volontiers.
- Étalez dans le temps : mieux vaut un passage lent et régulier la nuit qu'une rafale à l'heure de pointe du site.
Dans Scrapy, ce comportement s'obtient avec l'extension AutoThrottle (AUTOTHROTTLE_ENABLED), qui adapte le délai à la latence du site, avec CONCURRENT_REQUESTS_PER_DOMAIN, DOWNLOAD_DELAY et ROBOTSTXT_OBEY.
Sessions : quand garder la même IP
Pour un site, une session est un ensemble cohérent : la même IP, les mêmes cookies, le même user agent et la même langue. Si l'un d'eux change en cours de route, la session semble être passée à quelqu'un d'autre.
- Gardez la même IP quand le site utilise une connexion, un panier, des filtres enregistrés ou une pagination par jeton : c'est une session sticky.
- Changez d'IP entre deux sessions, pas pendant : fermez la session, faites tourner l'IP, repartez avec des cookies neufs.
- Un proxy par flux : si vous collectez des données sur plusieurs sites en parallèle, donnez à chaque flux son propre proxy, pour qu'une rotation n'interrompe pas les autres.
Le raisonnement complet sur le moment de faire tourner l'IP, ou pas, se trouve dans Rotation d'IP.
Bien gérer les nouvelles tentatives : backoff, jitter et plafond
- Ne relancez que ce qui a du sens : timeouts, erreurs réseau, 429, 502, 503 et 504. Un 404 ou un 403 le resteront.
- Respectez Retry-After lorsqu'il est présent : c'est le site qui vous dit combien attendre.
- Sinon, backoff exponentiel avec jitter : des attentes croissantes (5, 10, 20, 40 secondes) avec une part aléatoire, pour que plusieurs processus ne relancent pas tous au même instant.
- Fixez un plafond : un nombre maximal de tentatives et une attente maximale. Au-delà, enregistrez l'URL et passez à la suite.
- Pause par domaine : si les erreurs sur un site dépassent un seuil (par exemple 10 % des cent dernières requêtes), arrêtez tout le travail sur ce site pendant quelques minutes au lieu d'insister.
Une rotation réfléchie
Avec ProxyHub, vous changez d'IP via le lien de rotation, l'API ou la rotation automatique. Le lien et l'API répondent une fois le changement terminé, avec la nouvelle IP, et un proxy peut changer d'IP au maximum une fois toutes les 60 secondes.
- Faites tourner l'IP entre deux passages, pas à chaque requête : chaque nouvelle session part d'une nouvelle IP.
- Pour de gros volumes, utilisez plusieurs proxys en parallèle : chacun a son IP dédiée, et pendant que l'un change, les autres continuent.
- Après une limite, ralentissez avant de changer d'IP : si un site vous limite, attendez le temps indiqué et repartez plus lentement. Changer d'IP et continuer au même rythme mène au même résultat.
Moins de charge pour le site, moins de travail pour vous
- Requêtes conditionnelles : enregistrez ETag et Last-Modified et envoyez If-None-Match ou If-Modified-Since. Si la page n'a pas changé, le serveur répond 304, sans corps.
- Sitemap : pour découvrir les pages, utilisez le sitemap du site au lieu de suivre tous les liens.
- Compression : acceptez gzip ou br dans l'en-tête Accept-Encoding.
- Seulement l'utile : dans les navigateurs automatisés, bloquez images, polices et vidéos. Les données viennent souvent d'un appel JSON que vous pouvez lire directement.
- Collecte incrémentale : ne récupérez que les pages nouvelles ou modifiées, pas tout le site à chaque passage.
Avec Playwright, bloquer les ressources lourdes tient en une ligne :
page.route("**/*.{png,jpg,jpeg,gif,webp,woff,woff2,mp4}", lambda route: route.abort())La configuration du proxy dans Playwright est expliquée dans le guide Playwright.
Exemple en Python : Retry-After, backoff et rotation
Un squelette qui respecte Retry-After, utilise un backoff avec jitter et ne change d'IP qu'après une limite répétée, en tenant compte des 60 secondes entre deux changements :
import random, time, requests
from email.utils import parsedate_to_datetime
PROXY = "http://IDENTIFIANT:MOT_DE_PASSE@HOTE:PORT"
ROTATE = "LIEN_DE_ROTATION"
EXPECTED = 'class="price"' # élément que la page doit contenir
session = requests.Session()
session.proxies = {"http": PROXY, "https": PROXY}
last_rotation = 0.0
def retry_after(r):
v = r.headers.get("Retry-After", "")
if v.isdigit():
return int(v)
try:
return max(0, parsedate_to_datetime(v).timestamp() - time.time())
except (TypeError, ValueError):
return None
def rotate():
global last_rotation
if time.time() - last_rotation >= 60: # un changement par minute et par proxy
requests.get(ROTATE, timeout=30) # répond avec la nouvelle IP
last_rotation = time.time()
session.cookies.clear() # nouvelle session, nouveaux cookies
def fetch(url, tries=5):
for attempt in range(tries):
try:
r = session.get(url, timeout=30)
except (requests.ConnectionError, requests.Timeout):
time.sleep(min(60, 2 ** attempt) + random.random())
continue
if r.status_code == 200 and EXPECTED in r.text:
return r.text
if r.status_code == 200: # blocage silencieux (captcha, page vide)
wait = min(120, 10 * 2 ** attempt)
elif r.status_code in (429, 502, 503, 504):
wait = retry_after(r) or min(120, 5 * 2 ** attempt)
else:
r.raise_for_status() # 403, 404… : inutile de relancer
return r.text
if attempt >= 1:
rotate() # limite répétée : nouvelle session
time.sleep(wait + random.uniform(0, 3)) # jitter
raise RuntimeError(f"Trop de tentatives: {url}")Le même schéma fonctionne en Node.js et dans les outils no-code : la bibliothèque et la syntaxe changent, pas les règles. Si votre travail tourne en automatique, vous trouverez d'autres conseils sur la page Proxys pour automatisations et bots.
Questions fréquentes
Combien de requêtes par seconde puis-je faire ?
Aucun chiffre ne vaut pour tous les sites. Commencez avec une ou deux requêtes parallèles par domaine et des pauses de quelques secondes, puis augmentez seulement tant que les erreurs et les temps de réponse restent stables. Si le site indique Retry-After ou Crawl-delay, suivez ces valeurs.
Dois-je changer d'IP à chaque requête ?
Non : changer d'IP en pleine session casse les connexions, les paniers et la pagination, sans réduire la charge sur le site. Changez d'IP entre deux sessions ; avec ProxyHub, chaque proxy peut le faire une fois toutes les 60 secondes, et pour de gros volumes mieux vaut utiliser plusieurs proxys en parallèle.
Comment savoir si le site me limite même quand il répond 200 ?
Contrôlez le contenu : si l'élément recherché manque, si un captcha apparaît ou si la page est bien plus courte que d'habitude, traitez-la comme une erreur. Enregistrez ces cas à part : c'est le premier signe que votre rythme est trop élevé.
Essayez un proxy mobile 5G
Smartphone dédié, trafic illimité, vraies IP d'opérateurs. Actif en quelques secondes.
Voir les offresOu choisissez le pays :
