Les API GraphQL deviennent de plus en plus populaires, mais avec cela, les restrictions augmentent également : limitation de taux, blocages par IP, filtres géographiques. Si vous travaillez avec de grands volumes de données via GraphQL — en extrayant des données de plateformes e-commerce, en collectant des analyses des réseaux sociaux ou en testant des API — un proxy est indispensable. Dans cet article, nous allons examiner comment configurer correctement un proxy pour les requêtes GraphQL, mettre en œuvre la rotation IP et éviter les blocages.
Nous montrerons des exemples pratiques en Python et Node.js, examinerons les erreurs typiques et donnerons des recommandations sur le choix du type de proxy pour différentes tâches.
Pourquoi utiliser des proxies pour les requêtes GraphQL
Les API GraphQL sont souvent utilisées pour obtenir de grands volumes de données en peu de temps. Contrairement aux API REST, où les données sont réparties sur de nombreux points de terminaison, GraphQL permet de demander tout ce dont vous avez besoin en une seule requête. C'est pratique, mais cela crée des problèmes :
- Limitation de taux — la plupart des API GraphQL publiques limitent le nombre de requêtes d'une seule IP (par exemple, API GitHub : 5000 requêtes par heure, Shopify : 2 requêtes par seconde)
- Blocages IP — si vous dépassez les limites ou si une activité suspecte est détectée, votre IP peut être bloquée pendant plusieurs heures ou définitivement
- Restrictions géographiques — certaines API ne sont accessibles que depuis certains pays (par exemple, des marketplaces locaux ou des services régionaux)
- Protection contre le scraping — les serveurs surveillent les modèles de requêtes et bloquent les IP suspectes
Les proxies résolvent ces problèmes en permettant de répartir les requêtes sur de nombreuses adresses IP, d'imiter des requêtes provenant de différentes régions et de contourner les blocages. Cela est particulièrement important lors de travaux avec :
- L'extraction de données à partir de plateformes e-commerce (API GraphQL Shopify, WooCommerce)
- La collecte d'analyses des réseaux sociaux (API Graph Facebook, API Instagram)
- La surveillance des prix et de la disponibilité des produits
- Le test d'API depuis différentes localisations géographiques
- L'automatisation de la collecte de données pour l'analyse et la recherche
Quel type de proxy choisir pour travailler avec GraphQL
Le choix du type de proxy dépend de la tâche et des exigences de l'API. Examinons trois types principaux et leur utilisation pour les requêtes GraphQL :
| Type de proxy | Vitesse | Anonymat | Quand utiliser |
|---|---|---|---|
| Proxies de data center | Très élevée (10-50 ms) | Moyenne | Extraction d'API publiques, tests, vitesse élevée plus importante que l'anonymat |
| Proxies résidentiels | Moyenne (100-300 ms) | Très élevée | Travail avec des API protégées (Shopify, Facebook), contournement de filtres stricts |
| Proxies mobiles | Moyenne (150-400 ms) | Maximale | API Instagram, API TikTok, applications mobiles avec GraphQL |
Recommandations pour le choix :
- Pour les API publiques (GitHub, OpenWeather) — des proxies de data center suffisent, ils sont rapides et peu coûteux
- Pour l'e-commerce (Shopify, WooCommerce) — des proxies résidentiels, car ces plateformes filtrent activement les data centers
- Pour les réseaux sociaux (API Graph Facebook, Instagram) — des proxies mobiles ou résidentiels sont obligatoires
- Pour le scraping massif — une combinaison : data centers pour le trafic principal + résidentiels pour la rotation en cas de blocages
Configuration du proxy en Python pour GraphQL (requests, httpx, gql)
Python est l'un des langages les plus populaires pour travailler avec des API. Examinons trois façons de configurer un proxy pour les requêtes GraphQL.
Option 1 : Bibliothèque requests (client HTTP simple)
La façon la plus simple est d'utiliser la bibliothèque standard requests. Elle convient pour des requêtes GraphQL de base sans logique complexe.
import requests
import json
# Configuration du proxy
proxies = {
'http': 'http://username:password@proxy.example.com:8080',
'https': 'http://username:password@proxy.example.com:8080'
}
# Requête GraphQL
query = """
query {
products(first: 10) {
edges {
node {
id
title
priceRange {
minVariantPrice {
amount
}
}
}
}
}
}
"""
# Envoi de la requête via le proxy
url = "https://your-shop.myshopify.com/api/2024-01/graphql.json"
headers = {
'Content-Type': 'application/json',
'X-Shopify-Storefront-Access-Token': 'your_token_here',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
response = requests.post(
url,
json={'query': query},
headers=headers,
proxies=proxies,
timeout=30
)
data = response.json()
print(json.dumps(data, indent=2))
Option 2 : Bibliothèque httpx (requêtes asynchrones)
Si vous devez envoyer de nombreuses requêtes en parallèle, utilisez httpx avec prise en charge de async/await :
import httpx
import asyncio
import json
async def fetch_graphql(query, proxy_url):
url = "https://api.example.com/graphql"
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_TOKEN',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)'
}
# Configuration du proxy pour httpx
proxies = {
"http://": proxy_url,
"https://": proxy_url
}
async with httpx.AsyncClient(proxies=proxies, timeout=30.0) as client:
response = await client.post(
url,
json={'query': query},
headers=headers
)
return response.json()
# Utilisation
query = """
query {
viewer {
login
repositories(first: 5) {
nodes {
name
stargazerCount
}
}
}
}
"""
proxy = "http://user:pass@proxy.example.com:8080"
result = asyncio.run(fetch_graphql(query, proxy))
print(json.dumps(result, indent=2))
Option 3 : Bibliothèque gql (client GraphQL spécialisé)
Pour un travail avancé avec GraphQL, utilisez la bibliothèque gql — elle prend en charge la validation des schémas, le caching et un travail pratique avec les requêtes :
from gql import gql, Client
from gql.transport.requests import RequestsHTTPTransport
# Configuration du transport avec proxy
transport = RequestsHTTPTransport(
url='https://api.example.com/graphql',
headers={
'Authorization': 'Bearer YOUR_TOKEN',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64)'
},
proxies={
'http': 'http://user:pass@proxy.example.com:8080',
'https': 'http://user:pass@proxy.example.com:8080'
},
timeout=30
)
# Création du client
client = Client(transport=transport, fetch_schema_from_transport=True)
# Requête GraphQL
query = gql("""
query GetProducts($first: Int!) {
products(first: $first) {
edges {
node {
id
title
variants(first: 1) {
edges {
node {
price
}
}
}
}
}
}
}
""")
# Exécution de la requête
result = client.execute(query, variable_values={"first": 20})
print(result)
Configuration du proxy en Node.js pour GraphQL (axios, apollo-client)
Node.js est également largement utilisé pour travailler avec des API GraphQL. Examinons deux approches principales.
Option 1 : Axios avec proxy
Client HTTP simple et flexible avec prise en charge des proxies :
const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');
// Configuration du proxy
const proxyUrl = 'http://username:password@proxy.example.com:8080';
const httpsAgent = new HttpsProxyAgent(proxyUrl);
// Requête GraphQL
const query = `
query {
products(first: 10) {
edges {
node {
id
title
priceRange {
minVariantPrice {
amount
}
}
}
}
}
}
`;
// Envoi de la requête
axios.post('https://your-shop.myshopify.com/api/2024-01/graphql.json',
{ query },
{
headers: {
'Content-Type': 'application/json',
'X-Shopify-Storefront-Access-Token': 'your_token_here',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
},
httpsAgent: httpsAgent,
timeout: 30000
}
)
.then(response => {
console.log(JSON.stringify(response.data, null, 2));
})
.catch(error => {
console.error('Erreur :', error.message);
});
Option 2 : Apollo Client avec proxy
Apollo Client est le client GraphQL le plus populaire pour Node.js et le navigateur. Configuration du proxy via un fetch personnalisé :
const { ApolloClient, InMemoryCache, HttpLink, gql } = require('@apollo/client');
const fetch = require('cross-fetch');
const HttpsProxyAgent = require('https-proxy-agent');
// Agent proxy
const proxyUrl = 'http://user:pass@proxy.example.com:8080';
const agent = new HttpsProxyAgent(proxyUrl);
// Fetch personnalisé avec proxy
const customFetch = (uri, options) => {
return fetch(uri, {
...options,
agent: agent
});
};
// Création du client Apollo
const client = new ApolloClient({
link: new HttpLink({
uri: 'https://api.example.com/graphql',
fetch: customFetch,
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)'
}
}),
cache: new InMemoryCache()
});
// Requête GraphQL
const GET_REPOS = gql`
query GetRepositories($login: String!) {
user(login: $login) {
repositories(first: 5) {
nodes {
name
stargazerCount
}
}
}
}
`;
// Exécution de la requête
client.query({
query: GET_REPOS,
variables: { login: 'facebook' }
})
.then(result => {
console.log(JSON.stringify(result.data, null, 2));
})
.catch(error => {
console.error('Erreur :', error);
});
Mise en œuvre de la rotation des proxies pour contourner la limitation de taux
La rotation des proxies est une technique clé pour contourner les restrictions des API. Au lieu d'envoyer toutes les requêtes depuis une seule IP, vous les répartissez entre de nombreux proxies. Cela permet de contourner la limitation de taux et d'éviter les blocages.
Rotation simple en Python
Mise en œuvre de base de la rotation avec un changement cyclique de proxies :
import requests
import itertools
import time
# Liste de proxies
PROXY_LIST = [
'http://user:pass@proxy1.example.com:8080',
'http://user:pass@proxy2.example.com:8080',
'http://user:pass@proxy3.example.com:8080',
'http://user:pass@proxy4.example.com:8080',
]
# Création d'un itérateur infini
proxy_pool = itertools.cycle(PROXY_LIST)
def make_graphql_request(query):
"""Envoi d'une requête GraphQL avec rotation des proxies"""
proxy = next(proxy_pool)
proxies = {'http': proxy, 'https': proxy}
url = "https://api.example.com/graphql"
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_TOKEN',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
}
try:
response = requests.post(
url,
json={'query': query},
headers=headers,
proxies=proxies,
timeout=30
)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Erreur avec le proxy {proxy} : {e}")
# Passer au proxy suivant
return make_graphql_request(query)
# Exemple d'utilisation
queries = [
'query { products(first: 10) { edges { node { id title } } } }',
'query { collections(first: 5) { edges { node { id title } } } }',
'query { shop { name email } }'
]
for query in queries:
result = make_graphql_request(query)
print(result)
time.sleep(1) # Pause entre les requêtes
Rotation intelligente avec suivi des erreurs
Une version plus avancée qui suit les proxies non fonctionnels et les exclut automatiquement du pool :
import requests
import random
from collections import defaultdict
import time
class ProxyRotator:
def __init__(self, proxy_list, max_failures=3):
self.proxy_list = proxy_list.copy()
self.max_failures = max_failures
self.failures = defaultdict(int)
self.active_proxies = proxy_list.copy()
def get_proxy(self):
"""Obtenir un proxy actif aléatoire"""
if not self.active_proxies:
raise Exception("Tous les proxies sont indisponibles !")
return random.choice(self.active_proxies)
def mark_failure(self, proxy):
"""Marquer un échec"""
self.failures[proxy] += 1
if self.failures[proxy] >= self.max_failures:
print(f"Proxy {proxy} exclu du pool (limite d'erreurs dépassée)")
if proxy in self.active_proxies:
self.active_proxies.remove(proxy)
def mark_success(self, proxy):
"""Réinitialiser le compteur d'erreurs en cas de succès"""
self.failures[proxy] = 0
# Initialisation
proxies = [
'http://user:pass@proxy1.example.com:8080',
'http://user:pass@proxy2.example.com:8080',
'http://user:pass@proxy3.example.com:8080',
]
rotator = ProxyRotator(proxies)
def graphql_request_with_retry(query, max_retries=3):
"""Requête GraphQL avec tentatives automatiques"""
for attempt in range(max_retries):
proxy = rotator.get_proxy()
proxies_dict = {'http': proxy, 'https': proxy}
try:
response = requests.post(
'https://api.example.com/graphql',
json={'query': query},
headers={
'Content-Type': 'application/json',
'Authorization': 'Bearer TOKEN',
'User-Agent': 'Mozilla/5.0'
},
proxies=proxies_dict,
timeout=30
)
response.raise_for_status()
# Succès — réinitialiser le compteur d'erreurs
rotator.mark_success(proxy)
return response.json()
except Exception as e:
print(f"Tentative {attempt + 1}/{max_retries} avec {proxy} a échoué : {e}")
rotator.mark_failure(proxy)
time.sleep(2) # Pause avant de réessayer
raise Exception("Échec de la requête après toutes les tentatives")
# Utilisation
query = 'query { products(first: 10) { edges { node { id title } } } }'
result = graphql_request_with_retry(query)
print(result)
Configuration des en-têtes et User-Agent pour les requêtes GraphQL
Les en-têtes HTTP corrects sont essentiels pour le bon fonctionnement des API GraphQL via des proxies. De nombreuses API vérifient non seulement l'IP, mais aussi les en-têtes de la requête.
En-têtes obligatoires pour GraphQL
headers = {
# Type de contenu — toujours application/json pour GraphQL
'Content-Type': 'application/json',
# Autorisation (dépend de l'API)
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
# ou
'X-Shopify-Storefront-Access-Token': 'token_here',
# User-Agent — imiter un vrai navigateur
'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 — indiquer que nous acceptons JSON
'Accept': 'application/json',
# Accept-Language — langue de l'utilisateur
'Accept-Language': 'en-US,en;q=0.9',
# Accept-Encoding — prise en charge de la compression
'Accept-Encoding': 'gzip, deflate, br',
# Referer — d'où provient la requête (optionnel)
'Referer': 'https://example.com/',
# Origin — pour les requêtes CORS
'Origin': 'https://example.com'
}
Rotation du User-Agent
Pour plus d'anonymat, il est recommandé de faire tourner le User-Agent avec le proxy :
import random
USER_AGENTS = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15'
]
def get_random_headers(token):
"""Génération d'en-têtes aléatoires"""
return {
'Content-Type': 'application/json',
'Authorization': f'Bearer {token}',
'User-Agent': random.choice(USER_AGENTS),
'Accept': 'application/json',
'Accept-Language': 'en-US,en;q=0.9',
'Accept-Encoding': 'gzip, deflate, br'
}
Gestion des erreurs et tentatives répétées via un proxy
Lors de l'utilisation de proxies, des erreurs sont inévitables : délais d'attente, proxies indisponibles, blocages. Il est important de gérer correctement ces situations et de mettre en œuvre un mécanisme de tentatives répétées.
Erreurs typiques de GraphQL via un proxy
- Délais d'attente — le proxy est lent ou surchargé (augmentez le délai d'attente à 30-60 secondes)
- HTTP 407 Proxy Authentication Required — identifiant/mot de passe du proxy incorrects
- HTTP 429 Too Many Requests — limite de taux dépassée (rotation des proxies nécessaire)
- HTTP 403 Forbidden — IP du proxy bloquée (changez le type de proxy pour des résidentiels)
- Connection refused — proxy indisponible (exclure du pool)
Gestion avancée des erreurs
import requests
import time
from requests.exceptions import ProxyError, Timeout, ConnectionError
def graphql_request_robust(query, proxy, max_retries=3, backoff=2):
"""
Requête GraphQL fiable avec gestion de tous les types d'erreurs
Args:
query: Requête GraphQL
proxy: URL du proxy
max_retries: nombre maximum de tentatives
backoff: multiplicateur de délai entre les tentatives
"""
url = "https://api.example.com/graphql"
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer TOKEN',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
}
proxies = {'http': proxy, 'https': proxy}
for attempt in range(max_retries):
try:
response = requests.post(
url,
json={'query': query},
headers=headers,
proxies=proxies,
timeout=30
)
# Vérification de la limitation de taux
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
print(f"Limite de taux ! Attente de {retry_after} secondes...")
time.sleep(retry_after)
continue
# Vérification du blocage IP
if response.status_code == 403:
print(f"IP {proxy} bloquée ! Un autre proxy est nécessaire.")
raise Exception("IP bloquée")
# Vérification des erreurs d'autorisation du proxy
if response.status_code == 407:
print(f"Erreur d'autorisation du proxy {proxy}")
raise Exception("Échec de l'authentification du proxy")
response.raise_for_status()
# Vérification des erreurs GraphQL
data = response.json()
if 'errors' in data:
print(f"Erreurs GraphQL : {data['errors']}")
# Certaines erreurs peuvent être répétées, d'autres non
if is_retryable_graphql_error(data['errors']):
time.sleep(backoff * (attempt + 1))
continue
else:
raise Exception(f"Erreur GraphQL : {data['errors']}")
return data
except (ProxyError, ConnectionError) as e:
print(f"Tentative {attempt + 1}: Proxy indisponible - {e}")
time.sleep(backoff * (attempt + 1))
except Timeout as e:
print(f"Tentative {attempt + 1}: Délai d'attente - {e}")
time.sleep(backoff * (attempt + 1))
except requests.exceptions.HTTPError as e:
print(f"Tentative {attempt + 1}: Erreur HTTP - {e}")
if attempt < max_retries - 1:
time.sleep(backoff * (attempt + 1))
else:
raise
raise Exception(f"Échec de la requête après {max_retries} tentatives")
def is_retryable_graphql_error(errors):
"""Détermine si une requête peut être répétée en cas d'erreur GraphQL"""
retryable_codes = ['THROTTLED', 'INTERNAL_ERROR', 'TIMEOUT']
for error in errors:
if error.get('extensions', {}).get('code') in retryable_codes:
return True
return False
Meilleures pratiques pour travailler avec GraphQL via un proxy
Résumons et donnons des recommandations pour un travail efficace avec l'API GraphQL via des proxies :
✓ Optimisation des requêtes
- Demandez uniquement les champs nécessaires — GraphQL permet de spécifier exactement ce dont vous avez besoin
- Utilisez la pagination au lieu de demander toutes les données en une seule fois
- Regroupez les requêtes connexes en une seule (GraphQL prend en charge les requêtes multiples)
- Mettez en cache les résultats côté client pour réduire le nombre de requêtes
✓ Gestion des proxies
- Utilisez un pool d'au moins 5-10 proxies pour la rotation
- Vérifiez régulièrement la disponibilité des proxies (vérification de santé)
- Excluez automatiquement les proxies non fonctionnels du pool
- Pour les tâches critiques, gardez des proxies de secours d'un autre type
✓ Respect des limites
- Étudiez la documentation de l'API — elle indique les limites exactes
- Ajoutez des délais entre les requêtes (1-2 secondes minimum)
- Suivez les en-têtes X-RateLimit-Remaining et X-RateLimit-Reset
- Lors de la réception d'une erreur 429, augmentez le délai de manière exponentielle
✓ Sécurité et anonymat
- Utilisez toujours des proxies HTTPS pour protéger les tokens d'autorisation
- Faites tourner le User-Agent avec le proxy
- Ne stockez pas les tokens dans le code — utilisez des variables d'environnement
- Loguez uniquement les informations minimales nécessaires
Architecture recommandée pour les projets à grande échelle
Si vous travaillez avec de grands volumes de données, nous recommandons l'architecture suivante :
- File d'attente de tâches (Redis, RabbitMQ) — pour répartir les requêtes entre les travailleurs
- Pool de travailleurs — chaque travailleur utilise son propre proxy
- Gestionnaire de proxies — surveille l'état des proxies et les répartit entre les travailleurs
- Base de données — pour stocker les résultats et l'état des tâches
- Surveillance — suivi des erreurs, de la vitesse, de l'utilisation des proxies
Conclusion
Travailler avec l'API GraphQL via des proxies n'est pas simplement ajouter le paramètre proxies à la requête. Pour un fonctionnement fiable et efficace, il est nécessaire de mettre en œuvre la rotation des proxies, une gestion appropriée des erreurs, de configurer les en-têtes et de respecter les limites de l'API. Nous avons examiné des exemples pratiques en Python et Node.js que vous pouvez immédiatement utiliser dans vos projets.
Principales conclusions : utilisez des proxies résidentiels pour les API protégées (Shopify, Facebook), des data centers pour les API publiques et le scraping massif, mettez en œuvre une rotation automatique en excluant les proxies non fonctionnels, ajoutez des délais et gérez tous les types d'erreurs. Cela vous permettra de travailler de manière stable avec n'importe quelle API GraphQL sans blocages.
Si vous envisagez de travailler avec l'API GraphQL en production, nous vous recommandons d'utiliser des proxies résidentiels — ils offrent une stabilité maximale et un risque minimal de blocages. Pour les tests et le développement, des proxies de data center conviendront — ils sont plus rapides et moins chers.