Récupérer des données sur Internet, en quelques lignes
La plupart des vrais programmes Python finissent par avoir besoin de parler à quelque chose sur le réseau — une API REST, un service météo, un endpoint GitHub, un téléchargement. La bibliothèque standard peut le faire (via urllib), mais l'outil de facto dans le monde Python est une bibliothèque tierce appelée requests. L'API est tellement plus sympa que l'unique pip install vaut le coup.
pip install requests
Si tu ne travailles pas déjà dans un environnement virtuel, configures-en un d'abord — ça garde cette installation limitée à ton projet.
Une première requête GET
Trois lignes : appeler get, vérifier le code de statut, regarder le corps. response.text est le corps de la réponse comme chaîne. Tronqué ici parce que le JSON complet est long.
Codes de statut à reconnaître au niveau antisèche :
- 200 — OK, tout a marché.
- 201 — Créé (réponse POST courante).
- 301 / 302 — redirections ;
requestsles suit automatiquement par défaut. - 400 — mauvaise requête ; quelque chose dans ce que tu as envoyé était faux.
- 401 / 403 — non authentifié / non autorisé.
- 404 — la ressource n'existe pas.
- 429 — rate limit ; ralentis.
- 500 — erreur serveur.
Parser une réponse JSON
Quand l'endpoint renvoie du JSON, appelle .json() sur la réponse — il parse le corps et te donne un dict (ou une liste) :
Sous le capot, .json() est pareil que json.loads(response.text) — juste un raccourci pour le cas courant.
Envoyer des paramètres de query
Ne colle pas manuellement ?key=value&... sur l'URL. Passe un dict à params= :
requests gère l'encodage d'URL pour toi — espaces, caractères spéciaux, Unicode, tout marche en sécurité.
L'URL réelle qui est partie est disponible sur response.url, pratique pour déboguer.
Requêtes POST avec corps JSON
Pour envoyer des données — créer des ressources, soumettre des formulaires, appeler des endpoints qui mutent — utilise requests.post :
import requests
payload = {
"title": "Docs update",
"body": "Added HTTP requests page.",
"labels": ["docs"],
}
response = requests.post(
"https://api.example.com/issues",
json=payload,
headers={"Authorization": "Bearer YOUR_TOKEN"},
)
print(response.status_code)
print(response.json())
L'argument json= fait deux choses : il sérialise payload en JSON et met Content-Type: application/json. Tu pourrais faire les deux à la main avec data=json.dumps(payload) et un en-tête explicite, mais json= est le raccourci idiomatique.
Pour des données encodées en formulaire (le genre qu'un formulaire HTML classique envoie), utilise data= à la place :
requests.post("https://example.com/login", data={"user": "rosa", "password": "..."})
En-têtes
Passe n'importe quels en-têtes personnalisés comme un dict :
import requests
response = requests.get(
"https://api.example.com/profile",
headers={
"Authorization": "Bearer abc123",
"User-Agent": "my-tool/1.0",
},
)
La plupart des API veulent un en-tête Authorization pour l'authentification. Le schéma exact (Bearer, Basic, Token) est dans leur documentation.
Les timeouts ne sont pas optionnels
Par défaut, requests attendra pour toujours une réponse. Dans un vrai programme, ça transforme un serveur instable en script bloqué. Passe toujours un timeout :
import requests
try:
response = requests.get("https://api.example.com/slow", timeout=5)
except requests.Timeout:
print("Server took too long.")
Le nombre est en secondes. timeout=5 veut dire « abandonne si on n'a pas de réponse en 5 secondes ». Tu peux passer un tuple (connect_timeout, read_timeout) pour plus de contrôle.
Gestion des erreurs
Deux sortes de problèmes peuvent arriver :
- Erreurs au niveau HTTP (4xx, 5xx) — le serveur a répondu, mais la réponse est une erreur.
response.status_codete le dit. - Problèmes au niveau réseau — timeouts, échecs DNS, hôtes inaccessibles. Ceux-ci lèvent des exceptions.
Le motif idiomatique combine les deux :
raise_for_status() est un no-op pour les réponses 2xx et lève une exception sinon. RequestException est la classe de base pour chaque erreur que requests lève — un seul catch pour « tout ce qui a pu mal tourner en parlant à cet endpoint ».
Télécharger un fichier
Pour de gros téléchargements binaires, streame la réponse pour qu'elle ne traîne pas en mémoire :
import requests
url = "https://example.com/large.zip"
with requests.get(url, stream=True, timeout=30) as r:
r.raise_for_status()
with open("large.zip", "wb") as f:
for chunk in r.iter_content(chunk_size=8192):
f.write(chunk)
stream=True dit à requests de ne pas pré-charger le corps. iter_content(chunk_size=...) produit le corps un morceau à la fois, que tu écris directement sur le disque.
Sessions : réutiliser les connexions et les défauts
Si tu vas faire plusieurs requêtes vers le même service, utilise une Session. Elle réutilise la connexion TCP sous-jacente (plus rapide) et te laisse définir les défauts une seule fois :
import requests
session = requests.Session()
session.headers.update({"Authorization": "Bearer abc123"})
# Chaque requête à travers cette session porte l'en-tête.
a = session.get("https://api.example.com/users/1")
b = session.get("https://api.example.com/users/2")
c = session.post("https://api.example.com/users", json={"name": "Rosa"})
Pour des scripts qui frappent la même API des dizaines de fois, une session est une accélération significative.
Un exemple réaliste : petit client GitHub
Récupérer la dernière release d'un repo :
import requests
def latest_release(owner, repo):
url = f"https://api.github.com/repos/{owner}/{repo}/releases/latest"
response = requests.get(url, timeout=10)
response.raise_for_status()
data = response.json()
return {
"tag": data["tag_name"],
"name": data["name"],
"published": data["published_at"],
"url": data["html_url"],
}
release = latest_release("python", "cpython")
print(release)
Moins de quinze lignes : construire l'URL, la requêter, vérifier les erreurs, extraire les champs qui t'intéressent. C'est la forme de la plupart des clients d'API que tu écriras.
Et urllib ?
L'urllib.request de la bibliothèque standard peut faire tout ce que requests peut — en plus de lignes et avec une moins bonne ergonomie. Si tu ne peux absolument pas ajouter de dépendance, il est là :
import json
import urllib.request
with urllib.request.urlopen("https://api.github.com/repos/python/cpython") as r:
data = json.loads(r.read().decode("utf-8"))
print(data["name"])
Pour tout au-delà d'un script rapide, requests (ou httpx si tu as besoin d'async) vaut l'installation.
Quelques habitudes
- Mets toujours un timeout. Pas d'exceptions.
- Utilise
raise_for_status()dans les scripts qui attendent un succès — ça convertit une mauvaise réponse en exception bruyante. - Passe des dicts à
params=etjson=, pas des chaînes construites à la main. - Enveloppe les appels apparentés dans une
Sessionquand tu frappes la même API plusieurs fois. - Log
response.status_codeetresponse.textquand tu débogues — le corps te dit généralement exactement ce que le serveur n'a pas aimé.
Ensuite : dates et heures
Avec requests dans ta boîte à outils, tu peux parler à n'importe quelle API web moderne, télécharger des fichiers et construire de petites intégrations entre services. Combiné avec les pages JSON et CSV avant celle-ci, tu as maintenant la boucle complète « récupérer des données, les lire, faire quelque chose avec, les réécrire » — la forme d'un énorme nombre de vrais scripts Python. La plupart de ces données ont un timestamp dessus, cependant, et la prochaine page couvre comment Python représente les dates, heures et pièges de fuseaux horaires à éviter.
Questions fréquentes
Comment faire une requête HTTP en Python ?
Installe la bibliothèque requests avec pip install requests, puis appelle requests.get(url) pour un GET ou requests.post(url, json=...) pour un POST. L'objet réponse a .status_code, .text, .json() et .headers. Exemple : r = requests.get('https://api.example.com/users/1').
Faut-il utiliser requests ou urllib ?
requests pour tout ce que tu écrirais à la main — son API est spectaculairement plus sympa. urllib est intégré et convient quand ajouter une dépendance est impossible, mais il demande plus de code pour des choses comme les corps JSON et les sessions. En production, la plupart des équipes utilisent aussi httpx (une bibliothèque compatible requests avec support async).
Comment envoyer du JSON dans une requête POST en Python ?
Passe json={'key': 'value'} à requests.post(...). requests sérialise le dict en JSON et met Content-Type: application/json pour toi. Ne passe pas à la fois data= et json= — choisis-en un.
Comment gérer les erreurs avec la bibliothèque requests ?
Vérifie response.status_code (200 veut dire succès), ou appelle response.raise_for_status() pour lever une exception sur 4xx/5xx. Les problèmes au niveau réseau (timeouts, échecs DNS) lèvent des sous-classes de requests.RequestException — attrape ça pour couvrir les deux.