Situation classique : le script de surveillance des prix sur Wildberries ou Ozon fonctionne parfaitement sur un ordinateur portable à domicile, mais après avoir été transféré sur un VPS, il commence à recevoir des erreurs 403, des CAPTCHA ou un bannissement instantané par IP. Le développeur change les en-têtes, ajoute des délais — mais le résultat ne change pas. Le problème réside presque toujours non pas dans le code du parser en tant que tel, mais dans l'environnement à partir duquel il effectue des requêtes. Nous examinons 7 raisons concrètes et ce qu'il faut changer pour que le parser fonctionne de manière stable sur le serveur.
Pourquoi tout fonctionne localement, mais sur le serveur — bannissement
Lorsque vous lancez le parser depuis votre ordinateur personnel, le site voit une requête provenant d'une adresse IP résidentielle normale de votre fournisseur, dans une région familière, avec un environnement de navigateur réel, si vous utilisez Selenium ou Playwright avec un vrai profil. Dès que le même script est transféré sur un VPS en Allemagne, aux Pays-Bas ou aux États-Unis, la situation change complètement : l'IP appartient à un centre de données, l'empreinte TLS peut différer en raison d'une version différente des bibliothèques, le fuseau horaire du serveur ne correspond pas à la géolocalisation de l'IP, et la fréquence des requêtes augmente brusquement, car le serveur fonctionne 24/7 sans interruption.
Les systèmes anti-bot de Wildberries, Ozon, Avito et de la plupart des grandes marketplaces ne se contentent plus de vérifier uniquement le User-Agent. Ils analysent un ensemble de dizaines de signaux : type d'IP, vitesse et régularité des requêtes, comportement sur la page, correspondance des en-têtes et des paramètres TLS, présence de cookies et historique de session. La machine locale passe par ces vérifications par hasard sur la plupart des points, tandis que le serveur échoue presque à tous. Ci-dessous, une analyse détaillée de chaque raison.
Raison 1 : IP de centre de données au lieu d'un IP résidentiel
C'est la raison n°1 dans 80% des cas. Les adresses IP des VPS et des serveurs cloud (AWS, DigitalOcean, Hetzner, hébergements VDS classiques) se trouvent dans les bases de données des centres de données — les ASN de ces fournisseurs sont publiquement connus et utilisés par les systèmes anti-bot pour filtrer instantanément le trafic. Les marketplaces utilisent ces listes en priorité, car 95% du parsing automatisé provient précisément des IP de serveurs.
La solution consiste à utiliser des IP qui ne diffèrent visuellement pas de celles d'un utilisateur ordinaire d'internet. Pour le parsing de Wildberries, Ozon et Avito, les proxies résidentiels sont les plus adaptés : ce sont de vraies adresses IP de fournisseurs domestiques, attribuées à des abonnés ordinaires. Les systèmes anti-bot voient une telle requête comme du trafic d'un utilisateur vivant, et non d'un serveur dans un centre de données, ce qui élimine une grande partie des blocages immédiatement.
Raison 2 : Pas de rotation des IP et limite de fréquence des requêtes
Sur la machine locale, vous effectuez 20 à 50 requêtes manuellement pendant les tests, et le site ne le remarque pas. Sur le serveur, le script est exécuté par cron toutes les 5 minutes et traite des milliers de fiches produits consécutivement à partir d'une seule IP. Un tel modèle est un signal direct pour le système anti-bot : un vrai humain ne peut pas ouvrir 3000 pages de catalogue en une heure sans une seule pause.
Il est nécessaire d'introduire une rotation des IP sur le pool de proxies et de limiter le nombre de requêtes à une adresse dans un certain laps de temps. Règle pratique : pas plus de 30 à 60 requêtes par minute à partir d'une seule IP pour les fiches produits, avec un changement automatique d'adresse après chaque lot de requêtes. Exemple de configuration de rotation en Python via un pool de proxies :
import requests
proxies_pool = [
"http://user:[email protected]:9000",
"http://user:[email protected]:9001",
"http://user:[email protected]:9002",
]
def get_page(url, session_id):
proxy = proxies_pool[session_id % len(proxies_pool)]
resp = requests.get(
url,
proxies={"http": proxy, "https": proxy},
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"},
timeout=10
)
return resp.text
Lors de la collecte d'un grand volume de fiches produits par jour, il est plus pratique d'utiliser des proxies avec rotation automatique des IP par requête ou par minuteur — cela élimine la nécessité de maintenir manuellement une liste d'adresses.
Raison 3 : En-têtes et User-Agent ne ressemblent pas à un navigateur
De nombreux parsers utilisant requests ou aiohttp envoient des requêtes avec un ensemble minimal d'en-têtes ou avec le User-Agent standard de la bibliothèque, qui révèle immédiatement le script (par exemple python-requests/2.31.0). Sur la machine locale, via le navigateur, l'ensemble des en-têtes est complet : Accept, Accept-Language, Accept-Encoding, Sec-Ch-Ua, Referer et d'autres — leur ensemble semble naturel.
Il est nécessaire de copier l'ensemble complet des en-têtes d'un véritable navigateur, y compris l'ordre dans lequel ils sont envoyés — certains systèmes anti-bot vérifient même cela. De plus, il est important de faire tourner le User-Agent en synchronisation avec la version de l'empreinte TLS (voir le point suivant), sinon la non-conformité entre l'en-tête du navigateur et le véritable client TLS deviendra un nouveau signal de bot.
Raison 4 : L'empreinte TLS/JA3 révèle le script
C'est une raison moins connue, mais extrêmement fréquente de bannissements, notamment sur le serveur. Les bibliothèques requests, urllib, aiohttp utilisent leur propre implémentation du handshake TLS, qui diffère de l'implémentation dans Chrome ou Firefox. Les systèmes anti-bot calculent l'empreinte JA3/JA4 de la connexion TLS — et elle est complètement différente pour le script Python de celle d'un véritable navigateur, même si les en-têtes sont parfaitement copiés.
La solution consiste à utiliser des bibliothèques qui émuleraient l'empreinte TLS d'un navigateur (par exemple curl_cffi, tls-client en Python, ou un véritable navigateur headless basé sur Chromium via Playwright/Puppeteer). La deuxième option consiste à ne pas travailler via un client HTTP pur, mais via un moteur de navigateur géré en combinaison avec un outil anti-détection, où TLS et les en-têtes sont formés par un véritable noyau de navigateur, et non par une émulation de bibliothèque.
Raison 5 : Fuseau horaire, locale et serveurs DNS
Si le script émule un navigateur via Selenium ou Playwright, le système anti-bot peut vérifier le fuseau horaire système, la langue de l'interface, le résolveur DNS et même la fuite WebRTC de l'IP réelle du serveur. Un VPS dans un centre de données à Francfort avec un fuseau horaire système UTC et un fournisseur DNS de l'hébergeur, tout en utilisant un proxy avec une IP de Moscou, crée une incohérence géodonnée évidente — c'est l'un des signaux les plus fiables pour la détection.
Tous les paramètres de l'environnement — fuseau horaire, langue du navigateur, DNS, géolocalisation par WebRTC — doivent correspondre à la région de l'adresse IP utilisée pour la requête. C'est précisément pour résoudre ce problème que des navigateurs anti-détection ont été créés : Dolphin Anty, AdsPower, Multilogin, Octo Browser et GoLogin permettent de configurer un « profil de navigateur » distinct pour chaque proxy, où le fuseau horaire, la locale, la résolution d'écran et WebRTC sont automatiquement ajustés à la géolocalisation de l'IP.
Raison 6 : Le modèle des requêtes est trop « robotisé »
Un humain parcourt le catalogue avec des pauses variées, clique sur des produits aléatoires, revient parfois en arrière, fait défiler la page de manière irrégulière. Le script serveur effectue généralement des requêtes à intervalles réguliers (par exemple, strictement toutes les 2 secondes) et ne s'adresse qu'aux URL nécessaires sans « bruit » autour — sans charger d'images, de scripts, sans visiter la page d'accueil avant la fiche produit.
Ce qu'il faut changer : ajouter des délais aléatoires (pas des 2 secondes fixes, mais un aléatoire de 1,5 à 6 secondes), visiter périodiquement des pages intermédiaires (catégorie → fiche produit, et non une requête directe à l'API), émuler le défilement et les mouvements de la souris lors du travail via un navigateur headless. Cela augmente le temps de collecte des données, mais réduit considérablement le nombre de bannissements.
Raison 7 : Les sessions et les cookies ne sont pas conservés entre les requêtes
Souvent, le parser sur le serveur crée une nouvelle session requests pour chaque requête — sans cookies, sans jeton d'autorisation enregistré, sans historique de visites. Les marketplaces comme Wildberries et Ozon délivrent des cookies temporaires et des jetons lors de la première visite, et les requêtes suivantes sans eux semblent suspectes, comme si chaque requête était faite par un nouvel visiteur anonyme.
Schéma correct : une session (requests.Session() ou contexte de navigateur) — pour une IP du pool de proxies, avec conservation des cookies tout au long de la série de requêtes à cette IP. Lors du changement de proxy, il faut commencer une nouvelle session avec des cookies vierges, en imitant un nouvel utilisateur, et non continuer à utiliser d'anciens cookies avec une nouvelle IP — cela crée également une incohérence et déclenche un blocage.
Checklist : que changer dans l'ordre
Si le parser est régulièrement banni sur le serveur, mais fonctionne localement, vérifiez les modifications dans cet ordre — cela vous permettra de trouver plus rapidement la raison :
| Étape | À vérifier | À changer |
|---|---|---|
| 1 | Type d'IP du serveur | Passer à des proxies résidentiels au lieu de l'IP directe de l'hébergement |
| 2 | Fréquence des requêtes | Introduire une rotation des IP et une limite de requêtes par adresse |
| 3 | En-têtes de requête | Copier l'ensemble complet des en-têtes d'un véritable navigateur |
| 4 | Empreinte TLS | Utiliser curl_cffi / navigateur headless au lieu de requests pur |
| 5 | Fuseau horaire et locale | Configurer un profil dans Dolphin Anty / AdsPower pour la région de l'IP |
| 6 | Modèle de comportement | Randomiser les délais, ajouter des pages intermédiaires |
| 7 | Sessions et cookies | Lier une session à une IP pour tout le cycle de requêtes |
Pour le parsing à haute fréquence des catalogues Wildberries et Ozon, où la vitesse de navigation à travers des milliers de pages est importante, il est souvent judicieux de combiner deux types de proxies : des proxies de centre de données pour les requêtes techniques de brouillon (vérification de disponibilité, codes d'état) et des proxies résidentiels — pour la collecte finale de données à partir des fiches, où il est important de se camoufler en tant qu'utilisateur réel. Pour les applications mobiles des marketplaces et d'Avito, il est parfois plus efficace d'utiliser des proxies mobiles, car ils sont moins souvent inclus dans les listes de blocage automatique par ASN.
Conclusion
Le bannissement du parser sur le serveur alors que la version locale fonctionne est presque toujours lié non pas à la logique du script, mais à l'environnement : type d'IP, empreinte TLS, en-têtes, fuseau horaire, modèle de requêtes et gestion des sessions. En vérifiant chacune des 7 raisons dans l'ordre — de la plus fréquente (IP de centre de données) à la plus discrète (non-conformité entre le fuseau horaire et la région de l'IP) — il est possible de restaurer le fonctionnement stable du parser sans modifier la logique commerciale principale de la collecte de données.
Si vous collectez des prix et des stocks sur Wildberries, Ozon ou Avito à grande échelle, commencez par remplacer l'IP : essayez des proxies résidentiels au lieu de l'adresse standard du VPS — dans la plupart des cas, cela élimine jusqu'à 70% des blocages avant même que vous ne commenciez à configurer les en-têtes et les empreintes TLS.