Menu
Français

Requêtes HTTP Python : utiliser la bibliothèque requests (GET, POST, JSON)

Comment faire des requêtes HTTP en Python avec la bibliothèque requests — GET, POST, paramètres de query, en-têtes, corps JSON, et gestion des erreurs.

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

main.py
Output
Click Run to see the output here.

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 ; requests les 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) :

main.py
Output
Click Run to see the output here.

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= :

main.py
Output
Click Run to see the output here.

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 :

  1. Erreurs au niveau HTTP (4xx, 5xx) — le serveur a répondu, mais la réponse est une erreur. response.status_code te le dit.
  2. Problèmes au niveau réseau — timeouts, échecs DNS, hôtes inaccessibles. Ceux-ci lèvent des exceptions.

Le motif idiomatique combine les deux :

main.py
Output
Click Run to see the output here.

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= et json=, pas des chaînes construites à la main.
  • Enveloppe les appels apparentés dans une Session quand tu frappes la même API plusieurs fois.
  • Log response.status_code et response.text quand 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.

Apprendre à coder avec Coddy

COMMENCER