La commande curl que les utilisateurs Linux utilisent quotidiennement est bien plus qu’un outil de téléchargement — c’est un client HTTP complet capable de tester des REST APIs, d’automatiser des workflows, de déboguer des problèmes réseau et de transférer des données via des dizaines de protocoles. Que vous déboguiez un webhook défaillant, scripiez une intégration API ou inspectiez des certificats TLS, maîtriser curl est l’une des compétences les plus rentables qu’un sysadmin ou développeur puisse acquérir. Ce guide parcourt chaque cas d’usage pratique, des simples GET aux tests REST API CRUD complets, avec des exemples concrets tout au long.
Prérequis
- Un système Linux avec
curlinstallé (curl --versionpour confirmer ; installez viasudo apt install curlousudo dnf install curl) - Une familiarité de base avec le terminal et les concepts HTTP (méthodes de requête, en-têtes, codes de statut)
- Un endpoint API à tester — les exemples utilisent
https://jsonplaceholder.typicode.com, une API mock publique gratuite - Optionnel :
jqinstallé pour formater les réponses JSON (sudo apt install jq)
Requêtes HTTP : GET, POST, PUT, DELETE
curl utilise GET par défaut, donc la commande la plus simple est juste une URL :
curl https://jsonplaceholder.typicode.com/posts/1
Ajoutez -s (silencieux) pour supprimer l’indicateur de progression dans les scripts, et redirigez vers jq pour une sortie lisible :
curl -s https://jsonplaceholder.typicode.com/posts/1 | jq .
POST — création d’une ressource :
curl -s -X POST \
-H "Content-Type: application/json" \
-d '{"title":"My Post","body":"Hello world","userId":1}' \
https://jsonplaceholder.typicode.com/posts | jq .
Le drapeau -X POST définit la méthode. -H ajoute un en-tête. -d envoie le corps de la requête. Pour les soumissions de formulaires au lieu de JSON, omettez l’en-tête Content-Type ou utilisez -d "champ=valeur&autre=donnee".
PUT — mise à jour d’une ressource :
curl -s -X PUT \
-H "Content-Type: application/json" \
-d '{"title":"Updated Title","body":"New body","userId":1}' \
https://jsonplaceholder.typicode.com/posts/1 | jq .
PATCH — mise à jour partielle :
curl -s -X PATCH \
-H "Content-Type: application/json" \
-d '{"title":"Just the title changed"}' \
https://jsonplaceholder.typicode.com/posts/1 | jq .
DELETE — suppression d’une ressource :
curl -s -X DELETE https://jsonplaceholder.typicode.com/posts/1
echo "HTTP status: $?"
Pour capturer explicitement le code de statut HTTP :
curl -s -o /dev/null -w "%{http_code}" -X DELETE \
https://jsonplaceholder.typicode.com/posts/1
Le drapeau -w (write-out) avec %{http_code} affiche uniquement le code de statut numérique — idéal pour vérifier le succès ou l’échec dans des scripts shell.
Authentification : En-têtes, Jetons Bearer et Basic Auth
La plupart des APIs de production requièrent une authentification. curl gère tous les schémas courants.
Jeton Bearer (OAuth 2.0 / JWT) :
curl -s -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
https://api.example.com/protected-resource | jq .
HTTP Basic Auth — deux formes équivalentes :
# Forme 1 : drapeau -u (curl ajoute automatiquement l'en-tête Authorization)
curl -s -u myuser:mysecretpass https://api.example.com/data
# Forme 2 : en-tête explicite (utile pour les scripts avec des variables)
curl -s -H "Authorization: Basic $(echo -n myuser:mysecretpass | base64)" \
https://api.example.com/data
Clé API comme paramètre de requête :
curl -s "https://api.example.com/data?api_key=YOUR_KEY_HERE" | jq .
Clé API comme en-tête personnalisé (courant avec des services comme OpenAI ou Stripe) :
curl -s -H "X-API-Key: YOUR_KEY_HERE" https://api.example.com/endpoint | jq .
Stocker les identifiants dans un fichier netrc pour garder les secrets hors de l’historique shell :
# ~/.netrc
machine api.example.com
login myuser
password mysecretpass
curl -s --netrc https://api.example.com/data
Téléchargement et Upload de Fichiers
Téléchargement basique — sauvegarde avec le nom d’origine :
curl -O https://releases.ubuntu.com/24.04/ubuntu-24.04-desktop-amd64.iso
Téléchargement vers un chemin spécifique :
curl -o /tmp/ubuntu.iso https://releases.ubuntu.com/24.04/ubuntu-24.04-desktop-amd64.iso
Suivre les redirections (de nombreuses URLs de téléchargement redirigent) :
curl -L -O https://github.com/cli/cli/releases/latest/download/gh_linux_amd64.tar.gz
Reprendre un téléchargement interrompu :
curl -C - -O https://example.com/large-file.tar.gz
Téléchargement avec barre de progression (utile dans les terminaux interactifs) :
curl --progress-bar -O https://example.com/large-file.tar.gz
Upload d’un fichier avec multipart/form-data (simulation d’une entrée fichier navigateur) :
curl -s -X POST \
-F "file=@/path/to/document.pdf" \
-F "description=My document" \
https://api.example.com/upload | jq .
Upload binaire brut avec PUT :
curl -s -X PUT \
-H "Content-Type: application/octet-stream" \
--data-binary @/path/to/image.png \
https://api.example.com/files/image.png
Débogage Verbeux avec -v et —trace
Le drapeau -v est votre meilleur outil de débogage. Il affiche la poignée de main TLS, les en-têtes de requête, les en-têtes de réponse et la ligne de statut :
curl -v https://jsonplaceholder.typicode.com/posts/1
Exemple de sortie (tronquée) :
* Connected to jsonplaceholder.typicode.com (104.21.x.x) port 443
* TLSv1.3, TLS handshake
> GET /posts/1 HTTP/2
> Host: jsonplaceholder.typicode.com
> User-Agent: curl/8.5.0
> Accept: */*
>
< HTTP/2 200
< content-type: application/json; charset=utf-8
< cache-control: max-age=43200
<
{ ... JSON body ... }
Les lignes commençant par > sont envoyées par curl ; < sont reçues du serveur. C’est indispensable pour vérifier que vos en-têtes sont bien envoyés.
Pour encore plus de détails, utilisez --trace pour afficher les octets bruts :
curl --trace /tmp/curl-trace.txt https://api.example.com/endpoint
Vérifier uniquement les en-têtes sans télécharger le corps :
curl -I https://example.com
-I envoie une requête HEAD. Pour envoyer HEAD tout en spécifiant une méthode personnalisée :
curl -s -X HEAD -I https://example.com
Inspecter les informations du certificat TLS :
curl -v --connect-to :: https://example.com 2>&1 | grep -A5 "Server certificate"
Ou avec --cert-status sur les builds supportés.
curl vs wget : Choisir le Bon Outil
curl et wget téléchargent tous deux des fichiers, mais ils servent des objectifs principaux différents :
| Fonctionnalité | curl | wget |
|---|---|---|
| Cas d’usage principal | Appels API, débogage HTTP, scripting | Téléchargements récursifs, mirroring de sites |
| Support REST API | Complet (GET/POST/PUT/DELETE/PATCH) | GET uniquement par défaut |
| Corps de requête JSON | -d '{"key":"val"}' | Non supporté nativement |
| En-têtes personnalisés | -H "Header: Value" | --header="Header: Value" |
| Suivre les redirections | Drapeau -L requis | Suit par défaut |
| Reprendre les téléchargements | -C - | Drapeau -c |
| Téléchargement récursif | Non supporté | Drapeau --recursive |
| Sortie vers stdout | Par défaut | Requiert -O - |
| Scripting / piping | Excellent (stdout par défaut) | Moins naturel |
| Protocoles supportés | 30+ (FTP, SFTP, SMTP, IMAP…) | HTTP, HTTPS, FTP |
| Affichage de progression | -# ou --progress-bar | Affiché par défaut |
Règle générale : Utilisez curl pour le travail API, le débogage et les pipelines de scripting. Utilisez wget lorsque vous devez copier ou télécharger récursivement un site web, ou lorsque vous reprenez des téléchargements de façon plus simple.
Scénario Réel : Tester une REST API de Bout en Bout
Vous avez un serveur de production qui exécute un nouveau microservice de gestion des utilisateurs. Avant le déploiement, vous souhaitez valider le cycle de vie CRUD complet depuis la ligne de commande, en capturant les codes de statut pour l’intégration CI/CD.
#!/bin/bash
set -euo pipefail
BASE="https://api.example.com/v1"
TOKEN="eyJhbGciOiJIUzI1NiIs..."
echo "=== Testing User Management API ==="
# 1. Health check
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$BASE/health")
echo "Health check: $STATUS"
[[ "$STATUS" == "200" ]] || { echo "FAIL: API not healthy"; exit 1; }
# 2. Create a new user
RESPONSE=$(curl -s -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"username":"testuser","email":"test@example.com","role":"viewer"}' \
"$BASE/users")
USER_ID=$(echo "$RESPONSE" | jq -r '.id')
echo "Created user ID: $USER_ID"
# 3. Retrieve the user
curl -s -H "Authorization: Bearer $TOKEN" \
"$BASE/users/$USER_ID" | jq '.username'
# 4. Update the user role
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
-X PATCH \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"role":"editor"}' \
"$BASE/users/$USER_ID")
echo "PATCH status: $STATUS"
[[ "$STATUS" == "200" ]] || echo "WARNING: expected 200, got $STATUS"
# 5. List all users and count
COUNT=$(curl -s -H "Authorization: Bearer $TOKEN" \
"$BASE/users" | jq 'length')
echo "Total users: $COUNT"
# 6. Delete test user
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
-X DELETE \
-H "Authorization: Bearer $TOKEN" \
"$BASE/users/$USER_ID")
echo "DELETE status: $STATUS"
[[ "$STATUS" == "204" ]] || echo "WARNING: expected 204, got $STATUS"
echo "=== All tests passed ==="
Ce script valide l’ensemble du contrat API et se termine avec un code non-zéro en cas d’échec — prêt à être intégré dans un pipeline CI/CD.
Pièges et Cas Particuliers
Erreurs de certificat SSL sur des serveurs internes/dev : Utilisez -k ou --insecure pour ignorer la vérification, mais uniquement en développement :
curl -k https://internal-dev-server.local/api
Guillemets simples vs doubles dans les shells : À l’intérieur des guillemets doubles, $ et les backticks sont développés. Utilisez des guillemets simples autour des corps JSON pour éviter les surprises :
# Sûr : les guillemets simples empêchent l'expansion des variables dans le JSON
curl -d '{"userId":1}' https://api.example.com/items
# Risqué : $HOME est développé à l'intérieur des guillemets doubles
curl -d "{\"userId\":$USER_ID}" https://api.example.com/items # OK si $USER_ID est intentionnel
Envoyer un @ littéral dans les données POST : curl traite -d @nomfichier comme “lire le corps depuis un fichier”. Pour envoyer un @ littéral, utilisez --data-raw :
curl --data-raw '{"email":"user@example.com"}' https://api.example.com/subscribe
Limitation de débit et nouvelles tentatives : Ajoutez --retry et --retry-delay pour des scripts résilients :
curl --retry 5 --retry-delay 2 --retry-all-errors \
-s https://api.example.com/endpoint | jq .
Contrôle des délais d’attente : Évitez que les scripts restent bloqués indéfiniment :
curl --connect-timeout 10 --max-time 30 https://api.example.com/slow-endpoint
--connect-timeout limite la phase de connexion ; --max-time plafonne le temps total de transfert.
Cookies : Envoyez et persistez les cookies pour les APIs basées sur des sessions :
# Sauvegarder les cookies dans un fichier après la connexion
curl -s -c /tmp/cookies.txt -X POST \
-d "username=admin&password=secret" \
https://example.com/login
# Réutiliser les cookies sauvegardés pour les requêtes authentifiées
curl -s -b /tmp/cookies.txt https://example.com/dashboard
Résolution de Problèmes
« Could not resolve host » : Échec DNS. Vérifiez /etc/resolv.conf ou testez avec curl --dns-servers 8.8.8.8 https://example.com.
« SSL: no alternative certificate subject name matches » : Le certificat du serveur ne correspond pas au nom d’hôte. Utilisez -v pour voir ce que dit le certificat ; le nom d’hôte dans votre URL est peut-être incorrect.
« Empty reply from server » : Le serveur a fermé la connexion sans envoyer d’en-têtes. Essayez -v pour voir si la poignée de main TLS a réussi ; peut indiquer une incompatibilité de protocole (le drapeau --http1.1 peut aider).
Le corps de la réponse est vide mais le statut est 200 : Certains endpoints retournent 204 No Content en cas de succès (surtout DELETE). Utilisez -v pour confirmer la ligne de statut.
Grande réponse tronquée dans le terminal : Redirigez vers less ou dans un fichier :
curl -s https://api.example.com/large-dataset | jq . | less
curl -s https://api.example.com/large-dataset > /tmp/response.json
Vérifier quelle version de curl vous avez et quels protocoles elle supporte :
curl --version
Cherchez Protocols: dans la sortie — cela indique la disponibilité de FTP, SFTP, HTTP/2, HTTP/3 selon votre build.
Résumé
curlest le client HTTP Linux incontournable pour les tests REST API, les transferts de fichiers et le débogage réseau- Utilisez
-Xpour définir la méthode HTTP (POST, PUT, PATCH, DELETE),-Hpour les en-têtes,-dpour le corps de la requête - Authentification :
-H "Authorization: Bearer TOKEN"pour l’auth par jeton,-u user:passpour Basic Auth - Téléchargez des fichiers avec
-O(nom d’origine) ou-o nomfichier; utilisez-Lpour suivre les redirections - Le mode verbeux
-vaffiche les en-têtes de requête/réponse complets et les détails TLS — indispensable pour le débogage -w "%{http_code}"extrait le code de statut pour le scripting et la validation CI/CD- Utilisez
--retry,--connect-timeoutet--max-timepour rendre les scripts résilients en production - Préférez curl à wget pour le travail API et le scripting ; utilisez wget pour les téléchargements récursifs de sites
- Utilisez toujours
--data-rawquand les données du corps contiennent des caractères@littéraux pour éviter la confusion avec la lecture de fichiers - Redirigez vers
jqpour une sortie JSON formatée :curl -s https://api.example.com/data | jq .