
Les API REST sont aujourd'hui omniprésentes : services de géolocalisation,
paiements en ligne, données météorologiques, réseaux sociaux... La capacité à
communiquer avec ces interfaces depuis Python est devenue essentielle pour tout
développeur. Qu'il s'agisse d'automatiser des processus métier, de récupérer des
données externes ou d'intégrer des services tiers dans vos applications, les API
REST constituent le pont qui relie votre code au monde extérieur. La
bibliothèque requests de Python transforme cette communication en une tâche
intuitive et élégante, permettant d'effectuer des requêtes HTTP complexes
avec seulement quelques lignes de code.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comprendre une API REST : ressources, endpoints, méthodes HTTP, codes de statut
- Installer
requestset lire vos secrets depuis un fichier.env - Appeler une API avec
GET,POST,PUT,PATCHetDELETE - Gérer les erreurs avec
raise_for_status()et un timeout systématique - Authentifier vos appels (Basic, clé API, jeton Bearer, OAuth2,
Session) - Sécuriser : ne jamais coder un secret en dur, exiger HTTPS et ne jamais désactiver la vérification TLS
Comprendre les bases d’une API REST
Section intitulée « Comprendre les bases d’une API REST »Avant d’écrire la moindre ligne de code, il est essentiel de bien comprendre comment fonctionne une API REST. Ces interfaces permettent à des programmes d’échanger des données en s'appuyant sur le protocole HTTP, celui-là même qui fait fonctionner le web.
Ressources et endpoints
Section intitulée « Ressources et endpoints »Une API REST expose des ressources (utilisateurs, machines, services…) accessibles via des endpoints (URL). Par exemple, l’URL suivante :
https://api.mon-cloud.fr/v1/serverspeut renvoyer la liste des machines virtuelles disponibles sur une plateforme.
Méthodes HTTP
Section intitulée « Méthodes HTTP »Chaque opération est liée à une méthode HTTP spécifique, qui décrit l'intention de l'appel :
- GET : lire des données
- POST : créer une ressource
- PUT : remplacer une ressource existante
- PATCH : modifier partiellement une ressource
- DELETE : supprimer une ressource
Ces méthodes sont utilisées pour décrire l’intention de l’appel.
Structure JSON
Section intitulée « Structure JSON »La majorité des API REST échangent des données au format JSON, lisible et léger. Exemple de réponse :
{ "id": 42, "name": "webserver-prod", "status": "running"}Codes de retour HTTP
Section intitulée « Codes de retour HTTP »À chaque appel, l’API renvoie un code de statut qui indique le résultat :
200 OK: requête réussie201 Created: ressource créée204 No Content: suppression réussie, sans contenu400 Bad Request: syntaxe incorrecte401 Unauthorized: clé ou jeton manquant/invalide404 Not Found: ressource introuvable500 Internal Server Error: erreur côté serveur
Authentification
Section intitulée « Authentification »Pour des raisons de sécurité, la majorité des API nécessitent une clé d’API ou un jeton Bearer :
Authorization: Bearer eyJhbGciOiJIUzI1...Ces éléments doivent être transmis dans les headers HTTP, et ne jamais être codés en dur dans les scripts.
Plus d'informations sur les API REST
Préparer son environnement Python
Section intitulée « Préparer son environnement Python »Avant de consommer des API REST en Python, il faut configurer un environnement propre, sécurisé et prêt pour l'automatisation. Voici les étapes à suivre.
Créer un environnement virtuel
Section intitulée « Créer un environnement virtuel »Créez un environnement virtuel avec venv pour isoler vos
dépendances :
python -m venv venvsource venv/bin/activateInstaller la bibliothèque requests
Section intitulée « Installer la bibliothèque requests »Le module requests est la bibliothèque la plus simple et la plus utilisée
pour faire des appels HTTP en Python. Pour l’installer :
pip install requestsCe module gère les méthodes HTTP, les entêtes, les erreurs, l’encodage JSON, etc.
Créer une structure de script claire
Section intitulée « Créer une structure de script claire »Organisez vos scripts avec une structure modulaire, séparant le point d'entrée des fonctions réutilisables :
mon_script_api/├── main.py├── api_utils.py└── .envmain.py: point d’entrée du scriptapi_utils.py: fonctions réutilisables (authentification, requêtes).env: fichier contenant les clés d’API ou les jetons d’accès
Utiliser un fichier .env pour les secrets
Section intitulée « Utiliser un fichier .env pour les secrets »Pour éviter de stocker des identifiants directement dans le code, placez-les
dans un fichier .env :
API_KEY=sk_test_abc123BASE_URL=https://api.mon-cloud.frEt lisez-les dans votre script avec la bibliothèque python-dotenv :
pip install python-dotenvDans le script :
from dotenv import load_dotenvimport os
load_dotenv()api_key = os.getenv("API_KEY")Pour éviter de commettre ce fichier dans Git, ajoutez .env à votre
.gitignore.
Utiliser la bibliothèque requests
Section intitulée « Utiliser la bibliothèque requests »La bibliothèque requests simplifie les appels HTTP en Python. Voici comment
l'utiliser pour interagir avec une API REST.
Pour apprendre à l'utiliser, nous allons utiliser JSONPlaceholder. C’est une API REST factice gratuite qui simule des endpoints courants.
Lire une ressource avec GET
Section intitulée « Lire une ressource avec GET »Pour récupérer une ressource, utilisez la méthode GET :
import requests
url = "https://jsonplaceholder.typicode.com/todos/1"response = requests.get(url)print(response.json())Résultat attendu :
{ "userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}Créer une tâche avec POST
Section intitulée « Créer une tâche avec POST »Pour créer une nouvelle ressource, utilisez la méthode POST :
payload = { "userId": 1, "title": "Créer un playbook Ansible", "completed": False}response = requests.post("https://jsonplaceholder.typicode.com/todos", json=payload)print(response.json())Même si la création est fictive, l’API renvoie un objet JSON contenant un ID simulé.
{ "userId": 1, "title": "Créer un playbook Ansible", "completed": false, "id": 201}Modifier une tâche avec PUT
Section intitulée « Modifier une tâche avec PUT »Pour remplacer une ressource existante, utilisez la méthode PUT :
update = { "userId": 1, "title": "Tâche mise à jour", "completed": True}response = requests.put("https://jsonplaceholder.typicode.com/todos/1", json=update)print(response.json())Vous devriez obtenir une réponse similaire à celle-ci :
{ "userId": 1, "id": 1, "title": "Tâche mise à jour", "completed": true}Mise à jour partielle avec PATCH
Section intitulée « Mise à jour partielle avec PATCH »Pour modifier partiellement une ressource, utilisez la méthode PATCH :
partial = {"completed": False}response = requests.patch("https://jsonplaceholder.typicode.com/todos/1", json=partial)print(response.json())La réponse contiendra uniquement les champs modifiés :
{ "userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}Supprimer une tâche avec DELETE
Section intitulée « Supprimer une tâche avec DELETE »Pour supprimer une ressource, utilisez la méthode DELETE :
response = requests.delete("https://jsonplaceholder.typicode.com/todos/1")print(f"Code de statut : {response.status_code}")En général, l’API renvoie un 204 No Content ou 200 OK sans contenu.
Gérer les erreurs et exceptions
Section intitulée « Gérer les erreurs et exceptions »Lorsque vous consommez des API, il est essentiel de gérer les erreurs pour rendre vos scripts robustes, surtout dans un environnement d’infrastructure automatisé. Cela évite que des appels échoués passent inaperçus ou génèrent des comportements inattendus.
Vérifier les codes de statut HTTP
Section intitulée « Vérifier les codes de statut HTTP »Chaque réponse d’API contient un code de statut HTTP. Utilisez-le pour détecter les erreurs avant de traiter la réponse :
response = requests.get("https://jsonplaceholder.typicode.com/todos/1")if response.status_code == 200: print("Succès :", response.json())elif response.status_code == 404: print("Ressource non trouvée.")else: print(f"Erreur : {response.status_code}")Ou utilisez directement :
if response.ok: # True si le code est dans la plage 2xx donnees = response.json()response.ok vaut True si le code de statut est dans la plage 2xx.
Lever automatiquement les erreurs
Section intitulée « Lever automatiquement les erreurs »Pour simplifier la détection, utilisez raise_for_status() :
try: response = requests.get("https://api.mon-cloud.fr/data") response.raise_for_status() print(response.json())except requests.exceptions.HTTPError as e: print(f"Erreur HTTP : {e}")Cette méthode déclenche une exception si le code HTTP n'est pas dans la plage 2xx.
Ici, le code lève une exception HTTPError si la requête échoue, ce qui
permet de capturer les erreurs réseau ou de statut HTTP sans avoir à vérifier
manuellement le code de statut.
Erreur HTTP : 410 Client Error: Gone for url: https://api.mon-cloud.fr/dataCapturer les erreurs réseau
Section intitulée « Capturer les erreurs réseau »Les problèmes de réseau ou d’URL incorrectes doivent être capturés avec
RequestException :
try: response = requests.get("https://mauvaise-url") response.raise_for_status()except requests.exceptions.ConnectionError: print("Erreur de connexion")except requests.exceptions.Timeout: print("Délai d’attente dépassé")except requests.exceptions.RequestException as e: print(f"Erreur générale : {e}")Ce code gère les erreurs de connexion, les délais d’attente et les autres exceptions liées aux requêtes.
Erreur de connexionAjouter des délais d'attente (timeout)
Section intitulée « Ajouter des délais d'attente (timeout) »Pour éviter que votre script ne reste bloqué en cas d’API lente, imposez
un timeout :
requests.get("https://jsonplaceholder.typicode.com/todos/1", timeout=5)Cela déclenche une exception après 5 secondes d'attente.
Journaux d’erreur (logging)
Section intitulée « Journaux d’erreur (logging) »Dans un script d’automatisation, loguez les erreurs dans un fichier au lieu de simplement les afficher :
import logginglogging.basicConfig(filename='api.log', level=logging.ERROR)
try: r = requests.get("https://api.mon-cloud.fr/data") r.raise_for_status()except requests.exceptions.RequestException as e: logging.error(f"Appel échoué : {e}")Plus d'informations sur la gestion des erreurs.
Travailler avec des API sécurisées
Section intitulée « Travailler avec des API sécurisées »Lorsqu’on consomme des API REST, la gestion de l’authentification est
primordiale. Elle garantit que seules les entités autorisées peuvent accéder
aux ressources. Python, via requests, permet de gérer plusieurs types
d’authentification. Voici les modèles les plus courants, du plus simple au plus
avancé.
Authentification HTTP Basic
Section intitulée « Authentification HTTP Basic »Le schéma Basic envoie un couple utilisateur:motdepasse encodé en
Base64 dans un entête HTTP :
Authorization: Basic base64(utilisateur:motdepasse)Python gère automatiquement cette conversion Base64 via le module
requests.auth :
from requests.auth import HTTPBasicAuthimport requests
auth = HTTPBasicAuth("admin", "motdepasse")response = requests.get("https://api.mon-cloud.fr/serveurs", auth=auth)Cela génère automatiquement le header :
Authorization: Basic YWRtaW46bW90ZGVwYXNzZQ==Authentification par clé API (API Key)
Section intitulée « Authentification par clé API (API Key) »De nombreuses APIs utilisent une clé d’authentification unique, transmise de deux façons :
Dans les en-têtes HTTP
Section intitulée « Dans les en-têtes HTTP »headers = { "x-api-key": "sk_test_ABC123"}response = requests.get("https://api.mon-cloud.fr/instances", headers=headers)En paramètre de requête
Section intitulée « En paramètre de requête »params = { "api_key": "sk_test_ABC123"}response = requests.get("https://api.mon-cloud.fr/instances", params=params)Ce type d’authentification est simple mais sensible à l’exposition de la clé. Elle donne un accès complet aux endpoints autorisés.
Jeton Bearer (OAuth2, JWT)
Section intitulée « Jeton Bearer (OAuth2, JWT) »La méthode Bearer consiste à transmettre un jeton d’accès temporaire dans l’en-tête HTTP :
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...En Python :
headers = { "Authorization": "Bearer VOTRE_JETON", "Accept": "application/json"}response = requests.get("https://api.mon-cloud.fr/vms", headers=headers)Ce jeton est souvent obtenu via un login initial ou une authentification OAuth2, et expire généralement après un certain temps.
OAuth2, Jeton via identifiants client
Section intitulée « OAuth2, Jeton via identifiants client »De nombreuses APIs (GitLab, Azure, etc.) imposent un échange initial pour
obtenir un jeton d’accès temporaire, en envoyant un client_id et un
client_secret :
url = "https://auth.mon-cloud.fr/oauth/token"data = { "grant_type": "client_credentials", "client_id": "votre_id", "client_secret": "votre_secret"}
response = requests.post(url, data=data)access_token = response.json()["access_token"]Puis utilisation du jeton :
headers = {"Authorization": f"Bearer {access_token}"}requests.get("https://api.mon-cloud.fr/data", headers=headers)Sessions persistantes avec requests.Session
Section intitulée « Sessions persistantes avec requests.Session »Pour éviter de dupliquer les headers d’authentification sur plusieurs appels,
réutilisez un objet Session :
session = requests.Session()session.headers.update({ "Authorization": "Bearer VOTRE_JETON", "Accept": "application/json"})
response = session.get("https://api.mon-cloud.fr/monitoring")Cela améliore la lisibilité et la maintenabilité du code dans les scripts plus longs.
Bonnes pratiques pour sécuriser l’authentification API
Section intitulée « Bonnes pratiques pour sécuriser l’authentification API »Utiliser une authentification sécurisée dans vos scripts Python ne suffit pas : il faut également adopter des bonnes pratiques pour éviter les fuites d’informations sensibles, protéger vos infrastructures, et garantir la maintenabilité de vos scripts d’automatisation.
Ne jamais coder en dur une clé ou un mot de passe
Section intitulée « Ne jamais coder en dur une clé ou un mot de passe »Évitez d’insérer vos API keys, tokens, ou mots de passe directement dans le script. Exemple à éviter absolument :
# Mauvais exempleheaders = {"Authorization": "Bearer sk_live_tres_secret"}En cas de fuite (GitHub, partage de fichier…), cela donne un accès direct à vos ressources.
Utiliser un fichier .env pour stocker les secrets
Section intitulée « Utiliser un fichier .env pour stocker les secrets »Créez un fichier .env :
API_KEY=sk_prod_xxxxxxBEARER_TOKEN=eyJhbGciOiJIUzI1...Ajoutez ensuite ce fichier à .gitignore :
.envDans votre script Python, chargez les variables avec python-dotenv :
pip install python-dotenvimport osfrom dotenv import load_dotenv
load_dotenv()api_key = os.getenv("API_KEY")headers = {"x-api-key": api_key}Chiffrer les échanges (HTTPS obligatoire)
Section intitulée « Chiffrer les échanges (HTTPS obligatoire) »Tous les appels API doivent être faits sur des URLs HTTPS. Le chiffrement TLS :
- Protège les données en transit (auth, payload)
- Évite les attaques de type man-in-the-middle
Ne jamais désactiver la vérification TLS
Section intitulée « Ne jamais désactiver la vérification TLS »Par défaut, requests vérifie le certificat TLS du serveur : c'est ce qui
garantit que vous parlez bien au vrai serveur et non à un attaquant. Désactiver
cette vérification avec verify=False rouvre grand la porte aux attaques
man-in-the-middle, même en HTTPS. À proscrire :
# À NE JAMAIS FAIRE en productionrequests.get("https://api.mon-cloud.fr/data", verify=False)Si vous devez joindre une API interne avec une autorité de certification (CA)
d'entreprise, ne désactivez pas la vérification : pointez requests vers le
certificat de la CA :
requests.get("https://api.interne/data", verify="/etc/ssl/certs/ca-entreprise.pem")Stocker les logs d’erreurs sans exposer les secrets
Section intitulée « Stocker les logs d’erreurs sans exposer les secrets »Lorsque vous tracez des appels API échoués, n’incluez jamais les clés ou tokens dans les logs :
import logging
try: response = requests.get("https://api.mon-cloud.fr/infra") response.raise_for_status()except requests.exceptions.RequestException as e: logging.error(f"Erreur API : {e}")Revoir et sécuriser les dépôts Git
Section intitulée « Revoir et sécuriser les dépôts Git »- Toujours ajouter
.envà.gitignore - Scanner votre historique Git avec
truffleHogougitleakspour détecter les fuites - Utiliser GitHub Secrets, GitLab CI/CD Variables ou Vault pour injecter les valeurs dynamiquement
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
À retenir
Section intitulée « À retenir »requests.get/post/put/patch/deletecouvrent les cinq méthodes HTTP ;response.json()décode la réponse JSON.- Vérifiez toujours le résultat :
response.raise_for_status()lève une exception sur un code d'erreur, à envelopper dans untry/except. - Un
timeoutsur chaque requête évite qu'un serveur lent ne bloque votre script indéfiniment. requests.Sessionréutilise les en-têtes d'authentification sur plusieurs appels.- Secrets : jamais en dur, chargez-les depuis un
.env(viapython-dotenv) ajouté au.gitignore. - TLS : exigez HTTPS et ne désactivez jamais
verify(verify=Falserouvre la porte au man-in-the-middle) ; pour une CA interne,verify="/chemin/ca.pem".
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »Les réponses courtes ci-dessous couvrent les questions les plus recherchées sur requests. Chaque exemple est autonome et testé sur Python 3.12.
requests puis appelez la méthode correspondant à l'action :import requests
reponse = requests.get(
"https://jsonplaceholder.typicode.com/todos/1",
timeout=5,
)
print(reponse.status_code) # 200
print(reponse.json()) # dictionnaire Python
response.json() décode le corps JSON, response.status_code donne le code HTTP. Pensez à toujours passer un timeout.# GET : lire une ressource
requests.get("https://api.exemple.com/todos/1", timeout=5)
# POST : créer une ressource (données dans le corps)
requests.post(
"https://api.exemple.com/todos",
json={"title": "Nouvelle tâche"},
timeout=5,
)
En résumé : GET consulte, POST crée, PUT remplace, PATCH modifie partiellement, DELETE supprime.raise_for_status() dans un bloc try/except :import requests
try:
r = requests.get("https://api.exemple.com/data", timeout=5)
r.raise_for_status() # lève une exception si 4xx/5xx
donnees = r.json()
except requests.exceptions.RequestException as e:
print(f"Appel échoué : {e}")
RequestException est la classe parente : elle couvre les erreurs HTTP, de connexion et de timeout, sans tester le code de statut à la main.requests vérifie le certificat TLS du serveur : c'est ce qui garantit que vous parlez au vrai serveur.verify=False désactive ce contrôle et rouvre la porte aux attaques man-in-the-middle, même en HTTPS :# À NE JAMAIS FAIRE en production
requests.get("https://api.exemple.com", verify=False)
Pour une CA interne d'entreprise, ne désactivez pas la vérification : pointez requests vers le certificat de la CA.requests.get("https://api.interne", verify="/etc/ssl/certs/ca.pem", timeout=5)
timeout (en secondes) à chaque appel :import requests
try:
r = requests.get("https://api.exemple.com/data", timeout=5)
except requests.exceptions.Timeout:
print("Délai d'attente dépassé")
Sans timeout, une requête peut rester bloquée indéfiniment si le serveur ne répond pas. C'est un réflexe indispensable dans un script d'automatisation.requestsest la bibliothèque historique, synchrone, simple et omniprésente (aujourd'hui en mode maintenance).httpxreprend la même interface mais ajoute le support asynchrone (async/await) et HTTP/2.
import httpx
reponse = httpx.get("https://api.exemple.com", timeout=5)
Pour un script simple, requests suffit ; pour de l'async ou HTTP/2, httpx est préférable.Pour aller plus loin
Section intitulée « Pour aller plus loin »- FastAPI : passer de la consommation à la création de vos propres API REST.
- Les API REST : approfondir les concepts REST, ressources, verbes et statuts.