httpx : interroge n'importe quelle API en Python, sans prise de tête

httpx : interroge n'importe quelle API en Python, sans prise de tête

De quoi avez-vous besoin

Version de Python

3.x

Packages

  • {"nom": "httpx", "version": "0.27+"}

Difficulté

Intermédiaire

Derrière chaque chatbot, chaque agent IA, chaque dashboard, il y a une réalité moins glamour : des requêtes HTTP. Pour parler à une API REST, il faut un client propre. Pendant quinze ans, la bibliothèque Requests a été la réponse évidente. Mais le monde a bougé : asyncio, HTTP/2, timeouts stricts, connexions réutilisées. C'est exactement ce que propose httpx, avec une syntaxe quasi identique à Requests. Tu ne repars pas de zéro, tu montes en gamme.

Aujourd'hui, on interroge une vraie API publique (sans clé, sans inscription) puis on termine en branchant un modèle de langage. Tout le code tourne tel quel sur ta machine.

Étape 1 : installer httpx

Un environnement virtuel, un pip install, et c'est réglé. Pas de dépendance exotique, httpx s'installe en une seconde.

bash
python -m venv venv
source venv/bin/activate   # sous Windows : venv\Scripts\activate
pip install httpx

Étape 2 : ton premier GET

On commence par le grand classique : récupérer une ressource. Ici on tape dans JSONPlaceholder, une fausse API de démo gratuite et fiable, parfaite pour tester sans clé ni inscription.

python
import httpx

r = httpx.get("https://jsonplaceholder.typicode.com/posts/1")
print(r.status_code)    # 200
print(r.json()["title"])

Deux lignes suffisent. r.json() convertit la réponse JSON en dictionnaire Python. Si l'API renvoie du texte brut, utilise r.text ; pour du binaire comme une image, c'est r.content.

Étape 3 : paramètres, en-têtes et timeouts

Une vraie requête, c'est rarement une simple URL. On ajoute des paramètres de requête, des en-têtes et, surtout, un timeout. Sans timeout, ton script peut rester bloqué une éternité sur une API qui rame.

python
r = httpx.get(
    "https://jsonplaceholder.typicode.com/comments",
    params={"postId": 1},
    headers={"User-Agent": "mon-script/1.0"},
    timeout=10.0,
)
comments = r.json()
print(len(comments), "commentaires")   # 5

Le paramètre params gère l'encodage de l'URL à ta place. Le timeout de dix secondes vaut pour l'ensemble de la requête, pas seulement la connexion.

Étape 4 : envoyer des données avec POST

Pour créer une ressource, on passe au POST avec un corps JSON. httpx s'occupe de sérialiser ton dictionnaire et de poser le bon en-tête Content-Type.

python
payload = {
    "title": "Mon article",
    "body": "Contenu du post",
    "userId": 1,
}
r = httpx.post("https://jsonplaceholder.typicode.com/posts", json=payload)
print(r.status_code)     # 201 Created
print(r.json()["id"])    # 101

Étape 5 : gérer les erreurs sans crasher

Une API peut être lente, indisponible, ou renvoyer une 404. Ton script doit survivre. httpx lève des exceptions précises selon le type de problème, à toi de les attraper.

python
try:
    r = httpx.get("https://jsonplaceholder.typicode.com/posts/99999", timeout=5.0)
    r.raise_for_status()          # lève une exception si le code est >= 400
    data = r.json()
except httpx.TimeoutException:
    print("L'API ne répond pas : timeout.")
except httpx.HTTPStatusError as e:
    print(f"Erreur HTTP {e.response.status_code}")
except httpx.RequestError as e:
    print(f"Problème réseau : {e}")

raise_for_status() transforme un code d'erreur HTTP en exception. Les deux autres except attrapent les soucis de transport, comme un serveur injoignable ou une connexion coupée.

Étape 6 : un client réutilisable

Enchaîner des dizaines de httpx.get() rouvre une connexion à chaque fois. httpx.Client garde le canal ouvert et centralise tes réglages : adresse de base, timeout, en-têtes communs.

python
with httpx.Client(
    base_url="https://jsonplaceholder.typicode.com",
    timeout=10.0,
) as client:
    user = client.get("/users/1").json()
    posts = client.get("/posts", params={"userId": user["id"]}).json()
    print(user["name"], "a écrit", len(posts), "posts")

Le with ferme proprement la connexion. base_url évite de répéter l'adresse complète à chaque appel : tu ne passes plus que le chemin.

Étape 7 : bonus, passer en asynchrone

Si tu interroges plusieurs APIs en parallèle, l'async divise le temps d'attente. httpx.AsyncClient se marie naturellement avec asyncio.

python
import asyncio

async def main():
    async with httpx.AsyncClient(timeout=10.0) as client:
        urls = [f"https://jsonplaceholder.typicode.com/posts/{i}" for i in range(1, 6)]
        reponses = await asyncio.gather(*(client.get(u) for u in urls))
        for r in reponses:
            print(r.json()["title"])

asyncio.run(main())

Étape 8 : interroger une API d'IA

Tout ce qu'on vient d'apprendre s'applique directement aux modèles. Voici l'appel minimal à l'API d'OpenAI, sans SDK, juste avec httpx.

python
client = httpx.Client(
    base_url="https://api.openai.com/v1",
    headers={"Authorization": "Bearer VOTRE_CLE"},
    timeout=30.0,
)
r = client.post("/chat/completions", json={
    "model": "gpt-4o-mini",
    "messages": [{"role": "user", "content": "Explique le théorème de Pythagore en une phrase."}],
})
print(r.json()["choices"][0]["message"]["content"])

Remplace VOTRE_CLE par ta clé. Le même schéma fonctionne avec Mistral, Anthropic ou n'importe quel fournisseur compatible OpenAI : tu changes l'URL, les en-têtes et le corps, pas ta logique.

Conclusion

httpx ne réinvente pas la roue : il reprend la simplicité de Requests et y ajoute ce qu'il faut pour le Python moderne. Timeouts partout, connexions réutilisées, async natif. Une fois ce réflexe pris, interroger une API ne te fera plus jamais peur. Prochaine étape logique : emballer tes appels dans une commande propre avec Typer, ou valider les réponses avec Pydantic. Le trio httpx + Pydantic + Typer, c'est la base d'un outil Python sérieux.