Une petite précision sur l'auteur de cet article. Nous sommes Geonode et nous vendons des proxys ; c'est pourquoi nous recommandons le plus souvent d'utiliser curl pour diagnostiquer un problème. En toute honnêteté, pour un débutant : curl n'est pas un outil de proxy et vous n'avez pas besoin d'un proxy pour l'apprendre. Tout ce qui suit fonctionne avec des points de terminaison publics depuis votre propre connexion, gratuitement. Les proxys n’entrent en jeu que bien plus tard, lorsque vous effectuez suffisamment de requêtes pour que la cible commence à vous limiter le débit, ou lorsque vous avez besoin de voir à quoi ressemble une page depuis un autre pays. Aucun de ces cas ne concerne les débutants. Commencez par apprendre à utiliser l’outil.
Qu'est-ce que curl et à quoi sert-il ?
curl est un programme en ligne de commande permettant de transférer des données à l'aide d'URL. Son manuel le décrit comme prenant en charge « DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS et WSS » — bien qu’en pratique, presque tout le monde l’utilise pour HTTP et HTTPS.
À quoi cela sert-il ?
- Appeler une API depuis un terminal ou un script
- Vérifier si une URL fonctionne et ce qu’elle renvoie
- Voir exactement ce qu’un serveur renvoie, en-têtes compris
- Télécharger des fichiers
- Déboguer : reproduire une requête en dehors de votre application pour déterminer si le problème provient de votre code ou du serveur
Ce qu’il n’est pas : un navigateur. Il n’exécute pas de JavaScript, il n’affiche rien et il ne maintient pas de session, sauf si vous le lui demandez. Une page qui semble complète dans un navigateur peut renvoyer un squelette presque vide à curl, ce qui est normal et ne constitue pas un dysfonctionnement.
Vos premières requêtes
curl https://example.com
Cette commande effectue une requête GET et affiche le corps de la réponse sur votre terminal. Si le résultat est un long bloc de code HTML, cela signifie que curl fonctionne correctement.
Quatre variantes immédiatement utiles :
Afficher les en-têtes ainsi que le corps avec -i
, documenté à l'adresse -i, --show-headers
: « Afficher les en-têtes de réponse dans la sortie. »
curl -i https://example.com
Enregistrer dans un fichier avec -o
(nom de votre choix) ou -O
(nom du serveur distant) :
curl -o page.html https://example.com
curl -O https://example.com/file.zip
Suivre les redirections avec -L
: « Suivre les redirections HTTP et répéter les requêtes avec la méthode initialement spécifiée. » Sans cette option, curl s’arrête à la première redirection et affiche la page de redirection plutôt que la page de destination.
curl -L https://example.com
Ne rien afficher mais signaler quand même les erreurs avec -sS
. -s
masque la barre de progression, -S
conserve les messages d’erreur. Ensemble, ces deux options constituent ce qu’il vous faut dans n’importe quel script.
curl -sS https://example.com
Si vous ne devez retenir qu’une seule ligne de cet article, que ce soit celle-ci :
curl -sSL https://example.com
Lire la réponse
Les débutants ont souvent tendance à se concentrer sur le corps de la réponse alors que la réponse se trouve dans les en-têtes.
curl -i https://example.com
HTTP/2 200
content-type: text/html; charset=UTF-8
content-length: 1256
La première ligne indique le statut. 200
signifie que l'opération a réussi. 301
et 302
correspondent à des redirections — il faut ajouter -L
. 401
et 403
signifient que vous n'y êtes pas autorisé. 404
signifie que la ressource n'existe pas. 429
signifie que votre requête est trop rapide. 500
et les valeurs supérieures indiquent que le serveur rencontre un problème.
content-type
Cela vous indique ce que vous avez réellement reçu et dissipe beaucoup de confusion. Si vous avez appelé une API en vous attendant à recevoir du JSON et que vous voyez « text/html
», cela signifie que vous avez obtenu une page d’erreur ou une redirection vers la page de connexion, et que l’erreur d’analyse que vous êtes sur le point de rencontrer est un symptôme plutôt que la cause.
Pour obtenir les en-têtes sans le corps :
curl -sS -o /dev/null -D - https://example.com
Cela effectue une requête GET normale, ignore le corps et affiche les en-têtes. C’est plus fiable que -I
, qui envoie une requête HEAD
et peut se comporter différemment — une distinction abordée dans notre guide sur les requêtes HEAD avec curl.
Pour obtenir un résumé plutôt que les en-têtes bruts, -w
affiche certaines valeurs sélectionnées :
curl -sS -o /dev/null -w 'status=%{response_code} time=%{time_total}s\n' https://example.com
Pour en savoir plus sur la lecture correcte des en-têtes, consultez l'article sur l'affichage des en-têtes de réponse avec curl.
Envoi de données
L'autre partie du travail.
Une requête POST avec des données de formulaire :
curl -d "name=Ada&role=engineer" https://api.example.com/users
L'utilisation de -d implique une requête POST et définit le type de contenu Content-Type: application/x-www-form-urlencoded.
Une requête POST avec du JSON — et c'est là l'erreur la plus courante chez les débutants, car -d à lui seul ne définit pas un type de contenu JSON :
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"name":"Ada","role":"engineer"}'
Si vous omettez cet en-tête, de nombreuses API renvoient l’erreur « 415 Unsupported Media Type », ce qui prête à confusion tant que vous ne savez pas qu’elle fait référence à votre Content-Type plutôt qu’à vos données. Nous avons abordé cette erreur spécifique dans l’article Qu’est-ce qu’un code d’état 415 ?.
Données provenant d’un fichier, en utilisant @ pour signifier « lire ce fichier » :
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d @payload.json
Une requête GET avec des paramètres de requête constitués de paires clé-valeur, en utilisant -G :
curl -G https://api.example.com/search -d "q=proxy" -d "limit=10"
Autres méthodes avec -X. À n'utiliser que pour les méthodes ne disposant pas d'option dédiée — PUT, DELETE, PATCH. Notez l'avertissement du manuel indiquant que -X « ne modifie que le mot utilisé dans la requête HTTP, sans altérer le comportement de curl », ce qui explique pourquoi -X HEAD ne fonctionne pas et pourquoi -I existe.
En-têtes, authentification et cookies
En-têtes personnalisés avec -H
, reproductible :
curl -H "Authorization: Bearer eyJhbG..." \
-H "Accept: application/json" \
https://api.example.com/me
Authentification de base avec -u
:
curl -u username:password https://api.example.com/private
Omettez le mot de passe et curl vous le demandera, ce qui évite qu'il ne figure dans l'historique de votre shell :
curl -u username https://api.example.com/private
Un agent utilisateur avec -A
, car curl s’identifie par défaut comme « curl » et certains serveurs réagissent différemment :
curl -A "Mozilla/5.0 (compatible; MyBot/1.0; +https://example.com/bot)" https://example.com
Si vous développez un client automatisé, un agent utilisateur honnête comportant une URL de contact relève à la fois des bonnes manières et constitue un avantage pratique — l’automatisation anonyme est bloquée bien plus facilement que l’automatisation identifiée.
Les cookies. curl ne les conserve pas d’une exécution à l’autre, sauf si vous le demandez :
curl -c cookies.txt -d "user=ada&pass=secret" https://example.com/login
curl -b cookies.txt https://example.com/dashboard
-c
écrit un fichier de cookies, -b
en lit un. C’est ainsi que vous gérez tout ce qui nécessite une session.
Les options à retenir
Tout ce qui précède se résume à un petit ensemble d'options.
| Option | Fonction |
|---|---|
-i | Afficher les en-têtes de réponse avec le corps |
-o file / -O | Enregistrer dans un fichier nommé / sous le nom du serveur distant |
-L | Suivre les redirections |
-sS | Mode silencieux, mais signaler quand même les erreurs |
-H | Ajouter un en-tête |
-d | Envoyer des données (implique une requête POST) |
-u | Authentification de base |
-v | Afficher l'échange complet |
--fail | Traiter les erreurs HTTP comme des échecs |
-m / --connect-timeout | Limites de temps |
Les deux dernières options sont celles que les débutants ont tendance à ignorer et qu'ils regrettent par la suite.
--fail est important car, par défaut, curl considère un 404 comme un transfert réussi : il télécharge la page d’erreur et renvoie un code de sortie 0. Dans un script, cela signifie que vous enregistrez une page d’erreur HTML sous le nom installer.dmg et que vous continuez. --fail fait en sorte que les erreurs HTTP génèrent un code de sortie différent de zéro et aucune sortie.
Les délais d’expiration sont importants car curl n’impose aucune limite de temps globale par défaut. Une requête bloquée bloque votre script indéfiniment. L’option --connect-timeout 5 -m 30 permet de limiter ce délai. Vous trouverez plus d’informations à ce sujet dans la configuration d’un délai d’expiration avec curl.
La ligne à inclure dans chaque script : `
curl --fail --silent --show-error --location --connect-timeout 5 --max-time 30 "$URL"
Un exemple pratique de A à Z
Assembler les différents éléments autour d’une tâche concrète : appeler une API publique, vérifier que cela a fonctionné et gérer les cas d’échec.
Première étape — voir ce que renvoie le point de terminaison. Commencez par les en-têtes, pas par le corps :
curl -sS -o /dev/null -D - https://api.github.com/repos/curl/curl
Vous obtenez une ligne d’état et des en-têtes. Si l’état est « 200
» et que « content-type
» indique « JSON », vous communiquez bien avec la bonne ressource.
Étape 2 — examinez le corps de la requête, mis en forme. Le JSON brut sur une seule ligne est illisible ; passez-le donc par jq
:
curl -sS https://api.github.com/repos/curl/curl | jq '{name, stargazers_count, language}'
Si jq
n’est pas installé, python3 -m json.tool
effectue le formatage sans dépendance supplémentaire.
Étape 3 — Vérifiez ce que vous avez envoyé. Si quelque chose ne fonctionne pas comme prévu, examinez la requête plutôt que de faire des suppositions :
curl -v https://api.github.com/repos/curl/curl 2>&1 | grep '^>'
Étape 4 — Rendez-la sûre pour un script. Ajoutez une gestion des échecs et des délais, et récupérez le statut séparément du corps de la requête :
#!/usr/bin/env bash
set -euo pipefail
URL="https://api.github.com/repos/curl/curl"
BODY=$(mktemp)
STATUS=$(curl --silent --show-error --location \
--connect-timeout 5 --max-time 30 \
--write-out '%{response_code}' --output "$BODY" \
"$URL")
case "$STATUS" in
200) jq -r '.stargazers_count' < "$BODY" ;;
404) echo "not found" >&2; exit 1 ;;
429) echo "rate limited, retry after: $(date)" >&2; exit 1 ;;
*) echo "unexpected status $STATUS" >&2; head -c 200 "$BODY" >&2; exit 1 ;;
esac
rm -f "$BODY"
Trois éléments de cette approche méritent d’être intégrés à tout ce que vous écrivez. --write-out '%{response_code}'
avec --output
sépare le statut du corps de la requête, ce qui vous permet de créer des branches en fonction de celui-ci. Afficher les 200 premiers caractères du corps en cas de statut inattendu transforme un mystère en une erreur lisible. Et --connect-timeout
avec --max-time
garantit que le script se termine même si la connexion réseau est interrompue.
Étape n° 5 — respectez la limite de débit. Les API publiques indiquent leurs limites dans les en-têtes. Les consulter ne coûte rien et permet d’éviter la cause la plus courante de blocage :
curl -sS -o /dev/null -D - https://api.github.com/repos/curl/curl | grep -i ratelimit
Erreurs courantes des débutants
Oublier -L. Vous obtenez une réponse courte contenant un message de redirection et en concluez que l’URL est incorrecte. Ce n’est pas le cas.
Oublier --fail dans les scripts. Une requête de type 404 se transforme en une page d’erreur enregistrée et un code de sortie égal à zéro. Une erreur silencieuse, mais coûteuse à long terme.
Utilisation de -d avec du JSON sans définir Content-Type. Cela génère 415 ou une erreur d’analyse déroutante côté serveur.
Les guillemets dans le shell. Les guillemets simples conservent tout à la lettre ; les guillemets doubles permettent au shell d’expanser $ et les guillemets inversés. Pour un corps JSON contenant des guillemets doubles, encadrez-le de guillemets simples. Si vos données contiennent également des guillemets simples, placez-les dans un fichier et utilisez -d @file.json.
Partir du principe que curl voit ce que voit un navigateur. curl n’exécute pas de JavaScript. Une réponse quasi vide provenant d’une page qui semble complète dans un navigateur signifie que le contenu est rendu côté client, et que curl se comporte correctement.
Ignorer le code d’état. Un corps indiquant « error » avec un statut 200 et un corps indiquant « error » avec un statut 500 correspondent à des problèmes différents. Lisez les deux.
Indiquer les identifiants dans la ligne de commande. Ils sont enregistrés dans l’historique du shell et sont visibles dans la liste des processus par les autres utilisateurs de la machine. Utilisez -u user et laissez curl vous demander les informations, ou lisez-les à partir d’une variable d’environnement.
Désactiver la vérification des certificats pour faire fonctionner quelque chose. -k supprime un avertissement qui vous indiquait quelque chose. Cherchez d’abord à savoir de quoi il s’agit.
Prochaines étapes
Une fois que vous maîtrisez les bases, voici les étapes suivantes qui s’imposent naturellement :
Téléchargements corrects — reprise des transferts interrompus, téléchargements parallèles, limitation du débit. Abordé dans Télécharger un fichier avec curl.
Délais d’expiration et tentatives de réessai, ce qui permet aux scripts de ne plus être fragiles. Voir la configuration d’un délai d’expiration avec curl.
Lecture des en-têtes en tant que données, avec %{header_json} qui vous fournit une sortie JSON au lieu de texte à analyser.
curl par rapport à wget, car ils se recoupent et excellent dans des domaines différents — curl vs wget explique quand utiliser l’un ou l’autre.
Les proxys, lorsque vous en avez réellement besoin : -x http://host:port achemine une requête via un proxy. Vraiment utile pour les vérifications géographiques et pour répartir le trafic ; vraiment inutile pour l’apprentissage ou pour une utilisation modérée.
Le manuel. man curl est un document volumineux qui fait autorité. Lire la section consacrée à un indicateur que vous utilisez déjà est un moyen fiable de découvrir l’option que vous recherchiez réellement.
Questions fréquentes
À quoi sert curl ?
Au transfert de données via des URL depuis une ligne de commande ou un script : appel d’API, vérification des réponses renvoyées par un serveur, téléchargement de fichiers et reproduction d’une requête en dehors d’une application pour isoler un problème. Il prend en charge de nombreux protocoles, mais est principalement utilisé pour HTTP et HTTPS.
Comment effectuer une requête GET avec curl ?
curl https://example.com. La méthode GET est la méthode par défaut, aucun indicateur n’est donc nécessaire. Ajoutez -L pour suivre les redirections et -i pour afficher les en-têtes de réponse en plus du corps de la réponse.
Comment envoyer du JSON avec curl ?
curl -X POST -H "Content-Type: application/json" -d '{"key":"value"}' URL. L’en-tête est essentiel : -d seul envoie un type de contenu « form-encoded », et les API qui attendent du JSON le rejetteront généralement avec un code d’erreur 415.
Pourquoi curl ne renvoie-t-il rien ?
Plusieurs possibilités : le corps de la réponse est réellement vide, vous avez suivi une redirection que vous n’aviez pas prévue (ajoutez -L), le contenu est généré par du JavaScript que curl n’exécute pas, ou la requête a échoué et vous n’avez pas vu l’erreur à cause de -s sans -S. Exécutez la commande avec -i pour voir le code d’état.
Quelle est la différence entre -o et -O dans curl ?
-o filename enregistre le fichier sous le nom de votre choix. -O enregistre le fichier sous le nom de fichier figurant dans l’URL, en ignorant le chemin d’accès. Utilisez -o lorsque l’URL ne contient pas de nom de fichier utile ou lorsque vous avez besoin d’un nom spécifique.
Comment puis-je voir la requête envoyée par curl ?
Tapez « curl -v URL » et recherchez les lignes commençant par « > ». Les informations détaillées sont envoyées vers stderr ; ajoutez donc « 2>&1 » avant le redirection. C’est le moyen le plus rapide de vérifier qu’un en-tête que vous avez configuré a bien été transmis.
Curl suit-il les redirections par défaut ?
Non. Ajoutez -L. C’est la raison la plus courante pour laquelle la commande curl d’un débutant renvoie une réponse courte et inattendue : vous voyez la redirection, et non la destination.
Ai-je besoin d’un proxy pour utiliser curl ?
Non. curl fonctionne parfaitement avec les points de terminaison publics depuis votre propre connexion. Les proxys ne deviennent pertinents que lorsque vous effectuez suffisamment de requêtes pour être soumis à une limitation de débit, ou lorsque vous avez besoin de voir ce qu’un site propose dans un autre pays. Aucune de ces deux raisons ne justifie un achat pendant la phase d’apprentissage.
En conclusion
curl propose un nombre impressionnant d’options, mais son noyau utile est très restreint. -i pour afficher les en-têtes, -L pour suivre les redirections, -o pour enregistrer, -H pour ajouter des en-têtes, -d pour envoyer des données, -u pour l’authentification, -v pour voir ce qui s’est passé, et --fail avec un délai d’expiration pour toute tâche exécutée en arrière-plan. C’est là tout ce dont la plupart des utilisateurs ont besoin.
Les deux habitudes qui comptent plus que n’importe quel indicateur : lisez le code d’état et l’Content-Type avant de lire le corps du message, car ils identifient généralement le problème sans détour ; et utilisez -v pour vérifier ce que vous avez réellement envoyé plutôt que ce que vous aviez l’intention d’envoyer, car c’est dans la différence entre ces deux éléments que se cache une part surprenante de bogues.
Tout ce qui va au-delà relève du manuel, qui est volumineux, fait autorité et mérite d’être consulté chaque fois que vous vous retrouvez à écrire une solution de contournement. L’option que vous recherchez existe généralement.
