Retour au blog

Comment configurer un proxy dans Python requests pour le scraping, l'API et l'automatisation : guide complet avec des exemples de code

Guide complet pour connecter un proxy dans la bibliothèque Python requests - de la configuration de base à la rotation des IP et au contournement des blocages lors du scraping et de l'automatisation.

📅3 avril 2026
```html

Si votre script Python reçoit une erreur 403, un CAPTCHA ou un blocage par IP — cela signifie que le site cible vous a déjà remarqué. Connecter un proxy à la bibliothèque requests résout ce problème : vous changez d'adresse IP, contournez les restrictions géographiques et répartissez la charge entre plusieurs adresses. Dans ce guide, tout est abordé, de la connexion de base à la rotation avancée avec de vrais exemples de code.

Pourquoi utiliser des proxies dans les scripts Python

La plupart des sites et des API suivent les adresses IP des requêtes entrantes. Si une adresse effectue plus de 100 requêtes par minute — elle est bloquée. C'est une protection standard contre les bots, utilisée par Wildberries, Ozon, Avito, Google, Instagram et des centaines d'autres plateformes. Un proxy permet de diriger la requête via un serveur intermédiaire avec une autre adresse IP, vous rendant invisible pour les systèmes de protection.

Voici les principales tâches où les proxies en Python sont critiques :

  • Scraping de marketplaces — collecte de prix depuis Wildberries, Ozon, Yandex.Market sans blocages par IP
  • Surveillance des concurrents — requêtes régulières aux sites des concurrents toutes les 5 à 15 minutes
  • Travail avec des API avec des limites — répartition des requêtes entre plusieurs IP pour ne pas dépasser le taux limite
  • Tests géolocalisés — vérification de l'apparence d'un site depuis différents pays et régions
  • Automatisation des formulaires et des inscriptions — création de comptes ou remplissage de formulaires depuis différentes IP
  • Surveillance SEO — récupération des positions depuis différentes régions de Russie et d'autres pays

Sans proxy, même un parser bien écrit se heurtera à un blocage après quelques heures de fonctionnement. Avec une rotation IP correctement configurée, le même script fonctionne pendant des semaines sans interruption.

Configuration de base du proxy dans requests

La bibliothèque requests prend en charge les proxies nativement — aucun paquet supplémentaire n'est nécessaire. Le proxy est transmis via un dictionnaire proxies dans les paramètres de la requête.

L'exemple le plus simple — un proxy HTTP pour une seule requête :

import requests

proxies = {
    "http": "http://123.45.67.89:8080",
    "https": "http://123.45.67.89:8080",
}

response = requests.get("https://httpbin.org/ip", proxies=proxies)
print(response.json())
# {'origin': '123.45.67.89'}
  

Notez que dans le dictionnaire proxies, vous devez spécifier les deux clés — http et https. Si vous n'en spécifiez qu'une, les requêtes via le second protocole passeront directement sans proxy. C'est une erreur fréquente chez les débutants, qui entraîne une fuite de l'IP réelle.

Pour vous assurer que le proxy fonctionne, utilisez le service httpbin.org/ip — il retourne l'adresse IP depuis laquelle la requête a été faite. Si dans la réponse vous voyez l'IP du serveur proxy, et non la vôtre — tout est correctement configuré.

Proxies HTTP, HTTPS et SOCKS5 : différences et exemples de code

Les proxies existent en différents types, et chacun est adapté à ses propres tâches. Dans le contexte de Python requests, il est important de comprendre la différence entre les trois protocoles principaux :

Type Protocole dans l'URL Vitesse Support UDP Meilleur scénario
HTTP http:// Élevée Non Scraping de sites HTTP
HTTPS https:// Élevée Non Scraping de sites sécurisés
SOCKS5 socks5:// Moyenne Oui Anonymat complet, tous les protocoles

Pour travailler avec SOCKS5 en Python, vous devez installer un paquet supplémentaire :

pip install requests[socks]
# ou séparément :
pip install PySocks
  

Après l'installation, la connexion SOCKS5 proxy ressemble à ceci :

import requests

# Proxy SOCKS5
proxies = {
    "http": "socks5://123.45.67.89:1080",
    "https": "socks5://123.45.67.89:1080",
}

response = requests.get("https://httpbin.org/ip", proxies=proxies)
print(response.json())
  

SOCKS5 est le protocole préféré pour les tâches où l'anonymat est important. Contrairement aux proxies HTTP, SOCKS5 n'ajoute pas d'en-têtes X-Forwarded-For, qui peuvent révéler votre IP réelle.

Proxy avec authentification par nom d'utilisateur et mot de passe

La plupart des services de proxy payants utilisent l'authentification par nom d'utilisateur et mot de passe. C'est une pratique standard — sans authentification, le proxy ne laissera tout simplement pas passer votre requête. Dans la bibliothèque requests, les données d'authentification sont transmises directement dans l'URL du proxy.

import requests

# Format : protocole://nom_utilisateur:mot_de_passe@hôte:port
proxy_url = "http://myuser:[email protected]:8080"

proxies = {
    "http": proxy_url,
    "https": proxy_url,
}

response = requests.get("https://httpbin.org/ip", proxies=proxies)
print(response.status_code)
print(response.json())
  

Si le mot de passe ou le nom d'utilisateur contient des caractères spéciaux (par exemple, @, #, %), ils doivent être URL-encodés. Pour cela, utilisez le module urllib.parse :

import requests
from urllib.parse import quote

username = "myuser"
password = "p@ss#word!"  # Caractères spéciaux

# URL-encoder le nom d'utilisateur et le mot de passe
encoded_user = quote(username, safe="")
encoded_pass = quote(password, safe="")

proxy_url = f"http://{encoded_user}:{encoded_pass}@123.45.67.89:8080"

proxies = {
    "http": proxy_url,
    "https": proxy_url,
}

response = requests.get("https://httpbin.org/ip", proxies=proxies)
print(response.json())
  

💡 Conseil de sécurité

Ne hardcodez jamais le nom d'utilisateur et le mot de passe directement dans le code du script. Utilisez des variables d'environnement ou un fichier .env avec la bibliothèque python-dotenv. Cela vous évitera une fuite accidentelle des informations d'identification lors de la publication du code sur GitHub.

Rotation des proxies : changement automatique d'IP pour le scraping

Un proxy — c'est toujours une adresse IP, qui peut être bloquée. La véritable protection contre les blocages est la rotation : chaque requête (ou toutes les N requêtes) part avec une nouvelle IP. Voici quelques approches pour mettre en œuvre la rotation.

Méthode 1 : Sélection aléatoire dans la liste

import requests
import random

# Liste de proxies
proxy_list = [
    "http://user:[email protected]:8080",
    "http://user:[email protected]:8080",
    "http://user:[email protected]:8080",
    "http://user:[email protected]:8080",
]

def get_random_proxy():
    proxy = random.choice(proxy_list)
    return {"http": proxy, "https": proxy}

# Scraping de 10 pages avec rotation IP
urls = [f"https://example.com/page/{i}" for i in range(1, 11)]

for url in urls:
    proxies = get_random_proxy()
    try:
        response = requests.get(url, proxies=proxies, timeout=10)
        print(f"URL : {url} | IP : {proxies['http'].split('@')[1]} | Statut : {response.status_code}")
    except requests.RequestException as e:
        print(f"Erreur : {e}")
  

Méthode 2 : Rotation cyclique avec itertools

import requests
import itertools

proxy_list = [
    "http://user:[email protected]:8080",
    "http://user:[email protected]:8080",
    "http://user:[email protected]:8080",
]

# Création d'une boucle infinie sur la liste de proxies
proxy_cycle = itertools.cycle(proxy_list)

def get_next_proxy():
    proxy = next(proxy_cycle)
    return {"http": proxy, "https": proxy}

# Chaque requête utilise le prochain proxy dans l'ordre
for i in range(9):
    proxies = get_next_proxy()
    response = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=10)
    print(f"Requête {i+1} : {response.json()['origin']}")
  

Pour des tâches industrielles avec des milliers de requêtes par heure, il est recommandé d'utiliser des proxies résidentiels avec rotation automatique intégrée — le fournisseur change lui-même l'IP pour chaque requête via un point d'accès unique, et vous n'avez pas besoin de gérer manuellement la liste des adresses.

Proxy via Session : connexions persistantes et cookies

Lorsque vous devez effectuer plusieurs requêtes dans le cadre d'une seule session (par exemple, se connecter puis faire des requêtes), utilisez l'objet requests.Session(). Il conserve les cookies, les en-têtes et les paramètres de proxy entre les requêtes — il n'est pas nécessaire de transmettre le proxy à chaque appel séparément.

import requests

# Création d'une session avec proxy
session = requests.Session()
session.proxies = {
    "http": "http://user:[email protected]:8080",
    "https": "http://user:[email protected]:8080",
}

# Ajout d'en-têtes pour imiter un navigateur
session.headers.update({
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
    "Accept-Language": "fr-FR,fr;q=0.9",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
})

# Étape 1 : Authentification
login_data = {"username": "myuser", "password": "mypass"}
session.post("https://example.com/login", data=login_data)

# Étape 2 : Requêtes déjà avec des cookies et via proxy
response = session.get("https://example.com/dashboard")
print(response.status_code)

# Étape 3 : Fermeture de la session
session.close()
  

L'utilisation de Session est également plus efficace en termes de performance : la connexion TCP est réutilisée, au lieu d'être ouverte à nouveau pour chaque requête. Lors du scraping de plus de 1000 pages, cela offre un gain de vitesse significatif.

Gestion des erreurs, délais d'attente et répétitions automatiques

Les serveurs proxy peuvent être inaccessibles, répondre lentement ou renvoyer des erreurs de connexion. Un script fiable pour le scraping doit être capable de gérer ces situations et de passer automatiquement à un autre proxy en cas d'échec.

import requests
import random
import time

proxy_list = [
    "http://user:[email protected]:8080",
    "http://user:[email protected]:8080",
    "http://user:[email protected]:8080",
]

def fetch_with_retry(url, max_retries=3, timeout=10):
    """
    Effectue une requête avec changement automatique de proxy en cas d'erreur.
    Retourne un objet Response ou None si les tentatives sont épuisées.
    """
    available_proxies = proxy_list.copy()
    random.shuffle(available_proxies)

    for attempt, proxy_url in enumerate(available_proxies[:max_retries], 1):
        proxies = {"http": proxy_url, "https": proxy_url}
        try:
            response = requests.get(
                url,
                proxies=proxies,
                timeout=timeout,
                headers={"User-Agent": "Mozilla/5.0"}
            )
            response.raise_for_status()  # Lève une exception pour les 4xx/5xx
            print(f"✓ Succès à la tentative {attempt}")
            return response

        except requests.exceptions.ProxyError:
            print(f"✗ Tentative {attempt} : proxy inaccessible — {proxy_url}")
        except requests.exceptions.Timeout:
            print(f"✗ Tentative {attempt} : délai d'attente — {proxy_url}")
        except requests.exceptions.HTTPError as e:
            print(f"✗ Tentative {attempt} : erreur HTTP {e.response.status_code}")
            if e.response.status_code == 403:
                print("  → Blocage reçu, essayons le prochain proxy...")
        except requests.exceptions.RequestException as e:
            print(f"✗ Tentative {attempt} : erreur générale — {e}")

        time.sleep(1)  # Pause entre les tentatives

    print(f"✗ Toutes les {max_retries} tentatives épuisées pour {url}")
    return None

# Utilisation
result = fetch_with_retry("https://httpbin.org/ip")
if result:
    print(result.json())
  

Notez le raise_for_status() — cette méthode lève automatiquement une exception pour les statuts HTTP 4xx et 5xx. Sans cela, le script considérera même une réponse avec le code 403 (blocage) ou 429 (limite de requêtes dépassée) comme réussie.

Proxy via des variables d'environnement : stockage sécurisé des données

La bibliothèque requests lit automatiquement les variables d'environnement HTTP_PROXY et HTTPS_PROXY. Cela permet de ne pas stocker les informations d'identification dans le code et de passer facilement d'un proxy à l'autre sans modifier le script.

Définition des variables dans le terminal (Linux/macOS) :

export HTTP_PROXY="http://user:[email protected]:8080"
export HTTPS_PROXY="http://user:[email protected]:8080"
export NO_PROXY="localhost,127.0.0.1"
  

Ou via un fichier .env avec la bibliothèque python-dotenv :

# Fichier .env (ajoutez à .gitignore !)
HTTP_PROXY=http://user:[email protected]:8080
HTTPS_PROXY=http://user:[email protected]:8080
  
# Script Python
from dotenv import load_dotenv
import requests
import os

load_dotenv()  # Chargement des variables depuis .env

# requests utilise automatiquement HTTP_PROXY et HTTPS_PROXY
response = requests.get("https://httpbin.org/ip")
print(response.json())

# Ou explicitement depuis les variables d'environnement :
proxies = {
    "http": os.getenv("HTTP_PROXY"),
    "https": os.getenv("HTTPS_PROXY"),
}
response = requests.get("https://httpbin.org/ip", proxies=proxies)
print(response.json())
  

⚠️ Important : variable NO_PROXY

La variable NO_PROXY permet d'exclure certaines adresses du proxy. Assurez-vous d'y ajouter localhost et 127.0.0.1, afin que les requêtes locales ne passent pas par le proxy.

Scénarios réels : scraping de marketplaces, travail avec des API et automatisation

Examinons trois scénarios pratiques auxquels les développeurs sont souvent confrontés.

Scénario 1 : Scraping des prix d'un marketplace

Lors de la surveillance des prix sur Wildberries ou Ozon, il est important d'imiter le comportement d'un utilisateur réel : transmettre les bons en-têtes de navigateur, ajouter des délais entre les requêtes et faire tourner les IP. Pour cette tâche, les proxies de data center conviennent bien — ils sont rapides et peu coûteux pour le traitement de grandes quantités de données.

import requests
import time
import random

HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
                  "(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Accept": "application/json, text/plain, */*",
    "Accept-Language": "fr-FR,fr;q=0.9",
    "Referer": "https://www.wildberries.ru/",
}

PROXIES = [
    {"http": "http://user:[email protected]:8080",
     "https": "http://user:[email protected]:8080"},
    {"http": "http://user:[email protected]:8080",
     "https": "http://user:[email protected]:8080"},
]

def get_product_price(article_id: int) -> dict:
    """Obtient le prix d'un produit par son identifiant sur Wildberries."""
    url = f"https://card.wb.ru/cards/v1/detail?appType=1&curr=rub&nm={article_id}"
    proxies = random.choice(PROXIES)

    try:
        resp = requests.get(url, headers=HEADERS, proxies=proxies, timeout=15)
        resp.raise_for_status()
        data = resp.json()
        product = data["data"]["products"][0]
        return {
            "id": product["id"],
            "name": product["name"],
            "price": product["salePriceU"] / 100,  # prix en kopecks
        }
    except (requests.RequestException, KeyError, IndexError) as e:
        return {"error": str(e)}

# Scraping de plusieurs articles avec délai
articles = [12345678, 87654321, 11223344]
for article in articles:
    result = get_product_price(article)
    print(result)
    time.sleep(random.uniform(1.5, 3.0))  # Délai aléatoire de 1.5 à 3 sec
  

Scénario 2 : Travail avec une API via un proxy

Certaines API limitent le nombre de requêtes depuis une seule IP (limitation de taux). La répartition des requêtes entre plusieurs proxies permet de contourner cette limitation :

import requests
import itertools
from typing import Optional

class ProxyAPIClient:
    """Client pour travailler avec l'API via rotation de proxy."""

    def __init__(self, api_key: str, proxy_list: list):
        self.api_key = api_key
        self.proxy_cycle = itertools.cycle(proxy_list)
        self.session = requests.Session()
        self.session.headers.update({
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        })

    def _get_proxy(self) -> dict:
        proxy = next(self.proxy_cycle)
        return {"http": proxy, "https": proxy}

    def get(self, url: str, **kwargs) -> Optional[dict]:
        proxies = self._get_proxy()
        try:
            resp = self.session.get(url, proxies=proxies, timeout=10, **kwargs)
            resp.raise_for_status()
            return resp.json()
        except requests.RequestException as e:
            print(f"Requête API échouée : {e}")
            return None

# Utilisation
proxy_list = [
    "http://user:[email protected]:8080",
    "http://user:[email protected]:8080",
]

client = ProxyAPIClient(api_key="your_api_key", proxy_list=proxy_list)
data = client.get("https://api.example.com/products")
  

Scénario 3 : Tests géolocalisés

Les spécialistes du marketing et les experts SEO vérifient souvent comment un site apparaît depuis différentes régions. Avec des proxies des emplacements souhaités, ce processus peut être automatisé :

import requests

# Proxies de différentes régions
regional_proxies = {
    "Moscou":        "http://user:[email protected]:8080",
    "Saint-Pétersbourg": "http://user:[email protected]:8080",
    "Novossibirsk":   "http://user:[email protected]:8080",
    "États-Unis":     "http://user:[email protected]:8080",
}

url = "https://example.com/prices"

for region, proxy_url in regional_proxies.items():
    proxies = {"http": proxy_url, "https": proxy_url}
    try:
        resp = requests.get(url, proxies=proxies, timeout=15)
        print(f"[{region}] Statut : {resp.status_code} | "
              f"Taille : {len(resp.content)} octets")
    except requests.RequestException as e:
        print(f"[{region}] Erreur : {e}")
  

Quel type de proxy choisir pour votre tâche

Le choix du type de proxy influence directement le succès de votre projet. Un proxy de data center peu coûteux peut bien fonctionner pour certaines tâches et échouer complètement pour d'autres. Voici un guide pratique pour le choix :

Tâche Type de proxy Pourquoi
Scraping de marketplaces (Wildberries, Ozon) Résidentiels Ont l'apparence d'utilisateurs normaux, sont moins souvent bloqués
Scraping de données ouvertes, d'actualités Data centers Rapides, peu coûteux, suffisamment anonymes
Travail avec l'API Facebook, Instagram Mobiles Les réseaux sociaux font davantage confiance aux IP mobiles
Tests géolocalisés Résidentiels avec géotargeting Géolocalisation précise, IP réelles de la région souhaitée
Scraping à fort volume (10k+ requêtes/heure) Data centers (pool) Vitesse et coût pour de grands volumes
Authentification et travail avec des comptes Résidentiels ou mobiles Moins de déclencheurs pour les systèmes anti-fraude

Pour les tâches où la fiabilité maximale et le risque minimal de blocage lors du travail avec des sites sécurisés sont importants, les développeurs choisissent le plus souvent des proxies mobiles — ils utilisent des adresses IP de véritables opérateurs mobiles (MTS, Beeline, Megafon), qui sont très rarement ajoutées aux listes de blocage.

Liste de vérification des proxies avant utilisation

  • ✅ Vérifiez l'IP via httpbin.org/ip — votre adresse réelle est-elle visible ?
  • ✅ Vérifiez la vitesse — le temps de réponse ne doit pas dépasser 2-3 secondes
  • ✅ Assurez-vous que le proxy n'est pas dans les listes de blocage via blocklist.de ou ipqualityscore.com
  • ✅ Vérifiez la géolocalisation via ipinfo.io — correspond-elle à la région attendue ?
  • ✅ Testez sur le site cible avec une seule requête avant de lancer le script complet
  • ✅ Assurez-vous que le trafic HTTPS passe également par le proxy (les deux clés dans le dictionnaire)

Conclusion

Configurer un proxy dans Python requests n'est pas difficile, mais cela nécessite une attention aux détails. Les principaux principes à retenir : indiquez toujours les deux clés (http et https) dans le dictionnaire proxy, utilisez Session pour les scénarios multi-étapes, gérez toujours les erreurs et les délais d'attente, et stockez les informations d'identification dans des variables d'environnement, pas dans le code.

Pour le scraping industriel avec des milliers de requêtes par jour, une liste manuelle de proxies n'est pas suffisante — une rotation est nécessaire. Si vous scrapez des marketplaces sécurisées comme Wildberries ou Ozon, travaillez avec des réseaux sociaux ou testez la géolocalisation, nous vous recommandons d'essayer des proxies résidentiels — ils offrent un haut niveau de confiance de la part des systèmes anti-bots et prennent en charge la rotation automatique des IP via un point d'accès unique, ce qui simplifie considérablement le code de votre script.

```