Quasiment tous les projets data en Python finissent par interroger une API que ce soit pour récupérer des données depuis un SaaS, envoyer un événement à un webhook, déclencher un déploiement, exporter un dataset etc.... La librairie requests est l'outil standard pour ça, et elle couvre tous les cas d'usage avec une syntaxe simple.

Dans ce guide, on couvre 21 patterns concrets pour manipuler les APIs HTTP en Python : les méthodes (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS), les headers personnalisés, l'authentification (Basic Auth, OAuth 2), les sessions, le streaming de gros fichiers, le rate limiting et la gestion d'erreurs propre.

Si tu travailles déjà avec des fichiers, voir aussi Manipuler les fichiers en Python.

💡
Pratiquer sans installer Python : DataCertification.fr propose un Python Lab interactif avec 300+ exercices guidés sur la manipulation de données, pandas et NumPy. Idéal pour apprendre Python. Accéder au Python Lab.

En un coup d'œil : quel pattern pour quel besoin ?

Besoin Fonction / Pattern
Lire des données depuis une API requests.get()
Envoyer des données à une API requests.post(..., json=data)
Mettre à jour une ressource entière requests.put()
Mettre à jour une partie d'une ressource requests.patch()
Supprimer une ressource requests.delete()
Récupérer uniquement les en-têtes requests.head()
Connaître les méthodes supportées requests.options()
Envoyer des headers personnalisés headers={...}
Authentification Bearer / OAuth headers={'Authorization': 'Bearer ...'}
Authentification Basic auth=HTTPBasicAuth(...)
Limiter la durée d'une requête timeout=5
Réutiliser la même connexion requests.Session()
Télécharger un gros fichier stream=True + iter_content()
Uploader un fichier files={...}
Gérer un rate limit Boucle + sleep() sur code 429
Gérer les erreurs proprement try / except RequestException

1. Les 7 méthodes HTTP de base

Faire une requête GET

GET sert à récupérer des données depuis une API.

import requests

response = requests.get('https://api.example.com/get')
data = response.json()
print(data)

response.json() parse automatiquement la réponse JSON en dictionnaire Python.

Faire une requête POST

POST sert à envoyer des données à une API (créer une ressource, soumettre un formulaire, déclencher une action).

import requests

data_to_send = {'key1': 'value1', 'key2': 'value2'}
response = requests.post('https://api.example.com/submit', json=data_to_send)
data = response.json()
print(data)

L'argument json= sérialise automatiquement le dictionnaire et ajoute le header Content-Type: application/json.

Faire une requête PUT

PUT sert à remplacer entièrement une ressource existante.

import requests

data_to_update = {'key1': 'newvalue'}
response = requests.put('https://api.example.com/update/123', json=data_to_update)
print(response.status_code)  # 200, 201 ou 204 indiquent le succès

Faire une requête PATCH

PATCH sert à modifier partiellement une ressource (changer un champ sans toucher au reste).

import requests

data_to_patch = {'key1': 'updatedValue'}
response = requests.patch('https://api.example.com/update/456', json=data_to_patch)
print(response.json())

La différence avec PUT : PUT remplace toute la ressource, PATCH ne modifie que les champs envoyés.

Faire une requête DELETE

DELETE sert à supprimer une ressource.

import requests

response = requests.delete('https://api.example.com/delete/123')
print(response.status_code)  # 200 ou 204 indiquent le succès

Faire une requête HEAD

HEAD récupère uniquement les en-têtes d'une ressource, sans le contenu. Pratique pour vérifier l'existence d'un fichier ou sa taille avant de le télécharger.

import requests

response = requests.head('https://api.example.com/data')
print(response.headers)

Faire une requête OPTIONS

OPTIONS permet de connaître les méthodes HTTP supportées par un endpoint.

import requests

response = requests.options('https://api.example.com/data')
print(response.headers.get('allow'))  # ex : GET, POST, OPTIONS

2. Personnaliser les requêtes

Envoyer des headers personnalisés

Les headers sont souvent obligatoires pour les APIs modernes (clé d'API, type de contenu attendu, authentification).

import requests

headers = {
    'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
    'Accept': 'application/json'
}
response = requests.get('https://api.example.com/secure-data', headers=headers)
data = response.json()
print(data)

Définir un timeout

Sans timeout, une requête peut bloquer ton script indéfiniment si le serveur ne répond pas. À éviter en production.

import requests

try:
    response = requests.get('https://api.example.com/data', timeout=5)  # 5 secondes
    data = response.json()
    print(data)
except requests.exceptions.Timeout:
    print("La requête a dépassé le délai")

Tu peux aussi définir un timeout différent pour la connexion et pour la réponse : timeout=(3, 10) (3 secondes pour se connecter, 10 secondes pour recevoir la réponse).

Définir un User-Agent personnalisé

Certaines APIs filtrent les requêtes selon l'User-Agent (anti-scraping basique).

import requests

headers = {
    'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_5_1 like Mac OS X) AppleWebKit/605.1.15'
}
response = requests.get('https://api.example.com/data', headers=headers)
print(response.json())

Faire une requête conditionnelle (If-Modified-Since)

Utile pour économiser de la bande passante : tu demandes la ressource uniquement si elle a changé depuis une date donnée.

import requests

headers = {
    'If-Modified-Since': 'Sat, 29 Oct 2025 19:43:31 GMT'
}
response = requests.get('https://api.example.com/data', headers=headers)
if response.status_code == 304:
    print('Pas de changement')
else:
    print(response.json())

Passer par un proxy

Pour les environnements d'entreprise où toutes les requêtes sortantes doivent passer par un proxy.

import requests

proxies = {
    'http': 'http://10.10.1.10:3128',
    'https': 'http://10.10.1.11:1080'
}
response = requests.get('https://api.example.com/data', proxies=proxies)
print(response.text)

Désactiver la vérification SSL

À utiliser uniquement en dev ou sur des APIs internes avec des certificats auto-signés. Jamais en production.

import requests

response = requests.get('https://api.example.com/secure', verify=False)
print(response.text)

3. Authentification

Authentification Basic

Username et password envoyés à chaque requête, encodés en base64. Standard mais peu sécurisé sans HTTPS.

import requests
from requests.auth import HTTPBasicAuth

response = requests.get(
    'https://api.example.com/auth-required',
    auth=HTTPBasicAuth('username', 'password')
)
print(response.json())

Authentification OAuth 2.0 (Bearer Token)

Le pattern le plus courant aujourd'hui. Tu obtiens un token via une première requête, puis tu l'envoies dans le header Authorization pour les requêtes suivantes.

import requests

headers = {
    'Authorization': 'Bearer YOUR_ACCESS_TOKEN'
}
response = requests.get('https://api.example.com/oauth-data', headers=headers)
print(response.json())

Réutiliser une session avec requests.Session()

Au lieu de réécrire les mêmes headers à chaque requête, crée une session qui les conserve automatiquement. Bonus : la session réutilise la même connexion TCP, ce qui accélère les requêtes successives sur le même serveur.

import requests

with requests.Session() as session:
    session.headers.update({'Authorization': 'Bearer YOUR_ACCESS_TOKEN'})
    session.cookies.set('session_cookie', 'id_session_1234567890')
    
    response_one = session.get('https://api.example.com/data1')
    response_two = session.get('https://api.example.com/data2')
    print(response_one.json())
    print(response_two.json())

Le with ferme proprement la session à la fin, libérant les connexions.


4. Gérer les fichiers et gros volumes

Télécharger un gros fichier en streaming

Si tu télécharges un fichier de plusieurs Go, ne charge pas tout en mémoire. Utilise stream=True et lis par chunks.

import requests

response = requests.get('https://api.example.com/large-file', stream=True)

with open('large_file', 'wb') as f:
    for chunk in response.iter_content(chunk_size=8192):
        f.write(chunk)

Le chunk de 8192 octets est un bon équilibre entre nombre d'itérations et consommation mémoire.

Uploader un fichier

Pour envoyer un fichier (CSV, image, document) à une API, utilise le paramètre files qui encode automatiquement en multipart/form-data.

import requests

files = {'file': open('report.csv', 'rb')}
response = requests.post('https://api.example.com/upload', files=files)
print(response.status_code)

Pense à ouvrir le fichier en mode binaire ('rb') pour éviter les erreurs d'encodage.

Gérer le rate limiting d'une API

La plupart des APIs limitent le nombre de requêtes par minute. Quand tu dépasses, tu reçois un code 429. Le bon réflexe est d'attendre avant de retenter.

import requests
import time

def rate_limited_get(url):
    response = requests.get(url)
    if response.status_code == 429:
        time.sleep(10)  # Attendre 10 secondes avant de réessayer
        return rate_limited_get(url)
    return response

response = rate_limited_get('https://api.example.com/data')
print(response.json())

Pour une stratégie plus robuste, lis le header Retry-After de la réponse 429 qui te dit exactement combien de temps attendre.


5. Réponses et gestion d'erreurs

Accéder aux headers de la réponse

Pour récupérer un header précis de la réponse (type de contenu, longueur, dernière modification).

import requests

response = requests.get('https://api.example.com/data')
content_type = response.headers.get('Content-Type')
print(content_type)

Parser une réponse JSON proprement

Toujours vérifier le code de statut avant de parser, et attraper l'exception si le JSON est mal formé.

import requests

response = requests.get('https://api.example.com/data')
if response.status_code == 200:
    try:
        data = response.json()
        print(data)
    except ValueError:
        print("La réponse n'est pas au format JSON")
else:
    print(f"Erreur lors de la récupération, code : {response.status_code}")

Gérer toutes les erreurs avec try / except

Pour un code production, attrape les différents types d'exceptions séparément et utilise raise_for_status() qui lève automatiquement une HTTPError sur les codes 4xx et 5xx.

import requests

try:
    response = requests.get('https://api.example.com/data', timeout=5)
    response.raise_for_status()
    data = response.json()
    print(data)
except requests.exceptions.HTTPError as errh:
    print("Erreur HTTP :", errh)
except requests.exceptions.ConnectionError as errc:
    print("Erreur de connexion :", errc)
except requests.exceptions.Timeout as errt:
    print("Timeout :", errt)
except requests.exceptions.RequestException as err:
    print("Autre erreur :", err)

C'est le pattern à généraliser dans tout code Python qui appelle des APIs en production.


Aller plus loin : pratiquer Python

Manipuler les APIs HTTP, c'est la base pour tout pipeline data moderne (ETL avec sources cloud, intégrations SaaS, webhooks, exports). Sur DataCertification.fr, le Python Lab propose 300+ exercices interactifs sur la manipulation de données, pandas, NumPy et la POO. Tout tourne directement dans le navigateur (Pyodide), avec correction automatique.

👉 Pratiquer Python sur DataCertification.fr

Tu veux que je t'accompagne sur un projet data (intégration d'APIs, pipelines Python, Snowflake, dbt) ?

👉 Réserver un appel de 30 minutes

Questions

Comment faire une requête GET en Python ?

Utilise la librairie requests avec response = requests.get('https://api.example.com/get'). Pour récupérer le contenu en JSON, utilise response.json() qui parse automatiquement la réponse en dictionnaire Python.

Quelle différence entre GET, POST, PUT, PATCH et DELETE ?

GET récupère des données. POST crée une nouvelle ressource ou envoie des données. PUT update une ressource existante. PATCH modifie partiellement une ressource (seulement les champs envoyés). DELETE supprime une ressource. Ces verbes HTTP sont la base des APIs REST.

Comment envoyer des headers personnalisés avec requests ?

Crée un dictionnaire avec tes headers et passe-le via le paramètre headers. Exemple : headers = {'Authorization': 'Bearer TOKEN', 'Accept': 'application/json'}, puis requests.get(url, headers=headers). Les headers sont souvent obligatoires pour l'authentification.

Comment gérer l'authentification OAuth 2.0 en Python ?

Le pattern le plus courant est le Bearer Token : tu obtiens un access_token via une première requête (généralement POST sur /oauth/token), puis tu l'envoies dans le header Authorization de toutes tes requêtes. Exemple : headers = {'Authorization': 'Bearer YOUR_ACCESS_TOKEN'}. Pour les flows OAuth plus complexes (Authorization Code, Refresh Token), utilise la librairie requests-oauthlib.

Comment définir un timeout sur une requête HTTP ?

Ajoute le paramètre timeout=N (en secondes) à ton appel : requests.get(url, timeout=5). Tu peux aussi définir un timeout séparé pour la connexion et la réponse avec timeout=(3, 10). Sans timeout, ta requête peut bloquer indéfiniment si le serveur ne répond pas. C'est obligatoire en production. Attrape requests.exceptions.Timeout pour gérer le dépassement.

Comment uploader un fichier via une API en Python ?

Utilise le paramètre files= qui encode automatiquement le fichier en multipart/form-data. Exemple : files = {'file': open('report.csv', 'rb')}, puis requests.post(url, files=files). Ouvre toujours le fichier en mode binaire ('rb') pour éviter les erreurs d'encodage. Pour les fichiers volumineux, ferme explicitement le file handler après l'envoi.

Comment gérer les erreurs HTTP avec requests ?

Utilise un bloc try / except avec les exceptions spécifiques de requests : HTTPError (codes 4xx/5xx), ConnectionError (problème réseau), Timeout (dépassement de délai), RequestException (toute autre erreur). Combine avec response.raise_for_status() qui lève automatiquement une HTTPError pour les codes d'erreur.

À quoi sert requests.Session() ?

requests.Session() crée une session qui réutilise la même connexion TCP pour plusieurs requêtes vers le même serveur, ce qui accélère significativement les appels successifs. Elle conserve aussi les headers et les cookies automatiquement entre les requêtes. À utiliser dès que tu fais plus d'une requête vers la même API. Utilise un context manager (with) pour fermer proprement la session.

Comment gérer le rate limiting d'une API ?

Détecte le code de statut 429 (Too Many Requests) dans ta réponse, puis attends avec time.sleep() avant de relancer. Lis le header Retry-After de la réponse 429 qui indique combien de secondes attendre. Pour une stratégie robuste, ajoute un backoff exponentiel : 2s, 4s, 8s, etc. La librairie tenacity simplifie cette logique avec des décorateurs prêts à l'emploi.