Les en-têtes HTTP sont les métadonnées qui voyagent aux côtés de chaque requête et de chaque réponse : ils indiquent à un serveur quel client appelle, quel type de contenu le corps contient, quelles informations d'identification vérifier et quel langage ou format vous attendez en retour. Quand vous voulez envoyer des en-têtes HTTP avec cURL, tout le travail se résume à une seule option, mais les détails autour (plusieurs en-têtes, surcharger les valeurs par défaut, en supprimer un, et lire la réponse) sont là où la plupart des gens se retrouvent coincés.
Ce guide parcourt la mécanique pratique du point de vue d'un ingénieur en activité. Vous apprendrez la syntaxe -H / --header, comment envoyer un en-tête ou plusieurs, les en-têtes qui comptent le plus dans le travail réel (User-Agent, Accept, Authorization, Cookie, et compagnie), comment surcharger ou supprimer un en-tête par défaut, et comment inspecter ce que le serveur renvoie. À la fin, nous faisons le lien avec le scraping : des en-têtes réalistes font ressembler une requête à un navigateur, mais ce n'est que la moitié de l'histoire, nous montrons donc comment router cURL via un proxy résidentiel quand les en-têtes seuls ne suffisent pas.
L'option -H : syntaxe de base
cURL envoie un en-tête personnalisé avec l'option -H (ou sa forme longue --header), suivie du nom de l'en-tête, d'un deux-points et de la valeur, le tout entre guillemets pour que le shell le traite comme un seul argument.
curl -H "Header-Name: value" https://example.com
C'est tout le schéma. Les guillemets comptent : une valeur d'en-tête contient souvent des espaces, et sans guillemets le shell découperait la valeur en arguments distincts et cURL la rejetterait. Le nom de l'en-tête est insensible à la casse selon la spécification HTTP, mais c'est une bonne pratique de l'écrire sous sa forme canonique (User-Agent, pas user-agent) pour que vos commandes se lisent clairement et correspondent à ce que le serveur journalise.
Si vous préférez la forme longue verbeuse, --header se comporte de manière identique. Utilisez celle qui se lit le mieux dans les scripts ; la plupart des gens optent pour -H en ligne de commande et l'écrivent en entier dans le code versionné.
Envoyer un seul en-tête
L'en-tête unique le plus courant est User-Agent. cURL envoie son propre User-Agent par défaut (quelque chose comme curl/8.4.0), ce qui révèle instantanément à n'importe quel serveur que vous n'êtes pas un navigateur. Le surcharger tient en une option.
curl -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" https://example.com
Désormais le serveur voit une chaîne Chrome actuelle au lieu de l'identifiant cURL. Le même schéma à un en-tête couvre n'importe quel autre champ. Pour demander du JSON à une API plutôt que ce que le serveur renvoie par défaut, définissez Accept :
curl -H "Accept: application/json" https://api.example.com/data
Envoyer plusieurs en-têtes
Les vraies requêtes ne portent que rarement un seul en-tête. Pour en envoyer plusieurs, répétez -H une fois par en-tête. L'ordre est préservé, et cURL envoie chaque ligne exactement comme vous l'écrivez.
curl -H "Accept: application/json" \ -H "Accept-Language: en-US,en;q=0.9" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ https://api.example.com/data
Les barres obliques inverses vous permettent d'étaler la commande sur plusieurs lignes pour la lisibilité ; sur une seule ligne cela fonctionne pareil. Il n'y a pas de limite pratique au nombre d'options -H que vous pouvez empiler, donc une requête qui imite la poignée de main d'un navigateur peut porter une douzaine d'en-têtes sans aucun traitement particulier.
Les en-têtes qui comptent le plus
Une poignée d'en-têtes font le gros du travail dans le travail d'API et le scraping. Voici à quoi sert chacun et comment le définir.
User-Agent
Identifie le client. Définissez une vraie chaîne de navigateur, actuelle, pour que le serveur traite la requête comme du trafic ordinaire. Des User-Agents obsolètes ou manifestement synthétiques sont un déclencheur de blocage courant, alors gardez le vôtre à jour.
Accept et Accept-Language
Indiquent au serveur quels types de contenu et langues vous pouvez gérer. Un navigateur les envoie toujours ; une simple requête cURL ne le fait généralement pas, ce qui constitue en soi une empreinte. Envoyer des valeurs réalistes comble cet écart.
curl -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" \ -H "Accept-Language: en-US,en;q=0.9" \ https://example.com
Referer
Indique quelle page renvoyait vers celle que vous demandez. De nombreux sites attendent un Referer de même origine lors d'une navigation interne et considèrent son absence comme suspecte. Le définir sur le propre domaine du site (ou la page d'où vous seriez venu) rend la requête plus crédible.
curl -H "Referer: https://example.com/" https://example.com/products
Content-Type
Déclare le format du corps que vous envoyez. Il ne s'applique que lorsque vous avez un corps de requête, vous le verrez donc sur POST et PUT, pas sur un simple GET. Envoyez du JSON et le serveur doit savoir qu'il faut l'analyser comme du JSON.
Autorisation
Transporte les informations d'identification. Deux formes dominent. Un jeton Bearer (OAuth, clés d'API) va directement dans l'en-tête :
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" https://api.example.com/me
Pour l'authentification HTTP Basic, vous pouvez construire l'en-tête à la main, mais cURL offre un raccourci. L'option -u encode en base64 user:pass dans un en-tête Authorization: Basic pour vous, ce qui est moins sujet aux erreurs que de l'encoder vous-même.
# cURL builds the Basic header for you curl -u myuser:mypassword https://api.example.com/secure # Equivalent, written out by hand curl -H "Authorization: Basic bXl1c2VyOm15cGFzc3dvcmQ=" https://api.example.com/secure
Cookie
Envoie l'état de session stocké. Vous pouvez passer un cookie en ligne avec -H pour une requête ponctuelle, ou utiliser l'option -b de cURL, qui accepte aussi un fichier de cookies écrit par un précédent appel -c pour qu'une session persiste d'une requête à l'autre.
curl -H "Cookie: session_id=abc123; theme=dark" https://example.com/account
HTTP traite les noms d'en-têtes de manière insensible à la casse, donc User-Agent et user-agent atteignent le même champ. Les valeurs, en revanche, sont envoyées verbatim. Une faute de frappe dans un jeton ou un espace parasite dans un User-Agent est transmis tel quel, donc quand une requête se comporte bizarrement, vérifiez la valeur octet par octet avant d'accuser le serveur.
Surcharger un en-tête contre en ajouter un
cURL envoie quelques en-têtes automatiquement : Host, User-Agent et Accept parmi eux. Quand vous passez un -H pour un en-tête que cURL envoie déjà, votre valeur remplace la valeur par défaut plutôt que d'ajouter une seconde copie. C'est pourquoi -H "User-Agent: ..." échange proprement la chaîne cURL au lieu de produire deux lignes User-Agent.
Pour un en-tête que cURL n'envoie pas par défaut, votre -H l'ajoute simplement. Le modèle mental est donc direct : si c'est un en-tête par défaut, vous le surchargez, sinon vous l'ajoutez. Dans les deux cas, la syntaxe est la même unique option.
Supprimer un en-tête par défaut
Parfois vous voulez un en-tête entièrement disparu, pas remplacé. Pour retirer un en-tête par défaut, passez son nom suivi d'un deux-points et de rien après. cURL lit la valeur vide comme un signal d'omettre l'en-tête de la requête.
# Remove the Accept header entirely curl -H "Accept:" https://example.com # Override one default and remove another in the same request curl -H "User-Agent: Mozilla/5.0" -H "Accept:" https://example.com
Notez la différence : "Accept: value" définit l'en-tête, "Accept:" sans valeur le supprime, et un point-virgule final ("Accept;") envoie l'en-tête avec une valeur vide, ce qui est un troisième cas, plus rare. La plupart du temps vous voulez les deux premiers.
Consulter les en-têtes de réponse
Envoyer des en-têtes est la moitié de la conversation ; lire ce qui revient est l'autre moitié. cURL vous offre trois options selon que vous voulez aussi le corps.
Utilisez -I (ou --head) pour récupérer uniquement les en-têtes de réponse avec une requête HEAD, sans télécharger le corps :
curl -I https://example.com
Utilisez -i (ou --include) pour afficher les en-têtes suivis du corps complet, ce qui est pratique quand vous voulez les deux d'un coup :
curl -i https://example.com
Utilisez -D (ou --dump-header) pour écrire les en-têtes de réponse dans un fichier pendant que le corps va vers stdout. Passez -D - pour déverser les en-têtes vers stdout aux côtés du corps, ce qui est utile quand vous voulez les conserver dans un journal.
# Save response headers to a file, body to stdout curl -D headers.txt https://example.com
Un bloc d'en-têtes de réponse typique ressemble à ceci, vous indiquant le statut, le type de contenu et la politique de cache d'un coup d'œil :
HTTP/2 200 content-type: text/html; charset=UTF-8 cache-control: max-age=3600 server: nginx
Envoyer des en-têtes personnalisés sur un POST
Les en-têtes prennent toute leur importance sur les requêtes d'écriture. Un POST JSON typique vers une API a besoin au minimum d'un Content-Type pour que le serveur analyse correctement le corps, et généralement aussi d'un en-tête Authorization. L'option -d fournit le corps, et cURL bascule automatiquement en POST dès qu'il en voit un.
curl -X POST https://api.example.com/items \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -d '{"name": "widget", "qty": 12}'
Le -X POST est techniquement redondant dès que vous passez -d, mais l'écrire rend l'intention évidente dans un script. Si le serveur attend des données de formulaire au lieu de JSON, changez Content-Type en application/x-www-form-urlencoded et passez les champs de la même manière.
Si vous partez des bases des requêtes, notre présentation sur comment envoyer des requêtes GET avec cURL couvre le côté lecture de la même boîte à outils.
En-têtes et web scraping : ce qu'ils peuvent et ne peuvent pas faire
C'est là que la connaissance des en-têtes rencontre la réalité. Une requête provenant d'une installation cURL par défaut est trivialement distinguable d'un navigateur : elle envoie le User-Agent curl/x.y.z, omet Accept-Language, ne porte aucun Referer et n'apporte aucun des client hints qu'un vrai navigateur inclut. Les serveurs dotés ne serait-ce que d'une protection de base s'appuient précisément sur ces lacunes.
Définir des en-têtes réalistes comble les lacunes faciles. Un User-Agent Chrome actuel, un Accept et un Accept-Language plausibles, et un Referer de même origine font ensemble que votre requête ressemble bien davantage à du trafic de navigateur ordinaire. Pour des pages légèrement protégées, cela suffit souvent à elle seul à cesser d'être rejeté. Notre guide sur cURL pour le web scraping approfondit l'assemblage d'un jeu d'en-têtes crédible.
Mais les en-têtes ont un plafond dur. Ils décrivent la requête ; ils ne disent rien sur sa provenance. Les systèmes anti-bot pèsent aussi la réputation de l'IP, le débit des requêtes, les empreintes TLS et les signaux comportementaux. Si vous tirez cent requêtes par minute depuis une seule IP de centre de données, aucun jeu d'en-têtes ne vous sauvera : l'adresse elle-même vous trahit. Des en-têtes réalistes réduisent les blocages triviaux, mais ils ne battent pas à eux seuls de sérieuses défenses anti-bot ni une mauvaise réputation d'IP.
Router cURL via un proxy résidentiel
La moitié manquante, c'est l'IP. Quand vous routez cURL via un pool d'adresses résidentielles tournantes, vos requêtes proviennent d'IP qui se lisent comme de vrais utilisateurs pendant que vous gardez le contrôle total de chaque en-tête. cURL parle déjà nativement aux proxys via l'option -x (ou --proxy), donc en ajouter un est un seul argument par-dessus les en-têtes que vous envoyez déjà.
Le Smart AI Proxy (aussi appelé l'AI Proxy) expose la rotation résidentielle comme un unique point de terminaison prêt à l'emploi. Vous y pointez cURL avec -x, vous vous authentifiez avec votre token, et vous envoyez les en-têtes que vous voulez ; le proxy fait tourner l'IP de sortie en coulisses.
curl -x "http://[email protected]:8012" \ -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" \ -H "Accept-Language: en-US,en;q=0.9" \ -k https://example.com
L'option -x définit le proxy, les options -H portent vos en-têtes réalistes exactement comme avant, et la requête part d'une IP résidentielle de confiance. Vous conservez le contrôle total des en-têtes que cURL vous offre et gagnez la réputation d'IP que les en-têtes seuls ne peuvent pas fournir. Pour la mécanique générale du proxy de n'importe quelle requête cURL, voir comment utiliser cURL avec un proxy.
Continuez d'écrire vos propres en-têtes dans cURL et laissez le problème d'IP se résoudre tout seul. Le Smart AI Proxy fait tourner des adresses résidentielles derrière un seul point de terminaison, pour que vos User-Agent, Accept-Language et Referer soigneusement conçus partent d'une IP que les serveurs approuvent. Pointez-y cURL avec une seule option -x et gardez le contrôle total de chaque en-tête.
Si vous voulez la différence entre un proxy direct comme celui-ci et le type inverse placé devant un serveur, notre explicatif sur les proxys directs contre les proxys inverses trace la ligne clairement.
Déboguer les problèmes d'en-têtes
Quand une requête se comporte de manière inattendue, l'outil le plus rapide est -v (verbose), qui affiche les en-têtes de requête que cURL a réellement envoyés (préfixés par >) et les en-têtes de réponse qu'il a reçus (préfixés par <). Il fait remonter exactement ce qui est passé sur le fil, ce qui suffit généralement à repérer un en-tête manquant ou une faute de frappe.
curl -v -H "Authorization: Bearer YOUR_ACCESS_TOKEN" https://api.example.com/me
Trois problèmes représentent la plupart des bugs d'en-têtes. Premièrement, les guillemets manquants : une valeur avec un espace se découpe en arguments shell supplémentaires et cURL renvoie une erreur, alors mettez toujours entre guillemets toute la chaîne name: value. Deuxièmement, une surcharge non voulue : passer -H "User-Agent: ..." remplace la valeur par défaut au lieu de s'y ajouter, ce qui est voulu pour User-Agent mais une surprise si vous attendiez les deux. Troisièmement, une suppression accidentelle : un "Header:" parasite sans valeur retire entièrement l'en-tête. Exécutez avec -v et la vérité est juste là dans la ligne de requête.
Points clés
-
Une seule option fait tout.
-H "Name: value"envoie n'importe quel en-tête ; répétez-Hpour autant d'en-têtes que nécessaire, et l'ordre est préservé. -
Surcharger, ajouter ou supprimer. Un
-Hpour un en-tête par défaut le remplace, un-Hpour un nouveau l'ajoute, et"Header:"sans valeur le supprime. -
Lisez la réponse aussi.
-Irécupère uniquement les en-têtes,-iles ajoute en tête du corps, et-Dles déverse dans un fichier ou vers stdout. - Des en-têtes réalistes réduisent les blocages triviaux. Un vrai User-Agent, Accept-Language et Referer font ressembler une requête à un navigateur, mais ils ne battent pas de sérieuses défenses anti-bot.
-
Associez les en-têtes à une IP de confiance. Routez cURL via le Smart AI Proxy avec
-xpour que les requêtes partent d'adresses résidentielles tournantes tout en gardant le contrôle total des en-têtes.
Foire aux questions
Comment ajouter un en-tête HTTP personnalisé dans cURL ?
Utilisez l'option -H (ou sa forme longue --header) suivie du nom de l'en-tête, d'un deux-points et de la valeur, le tout entre guillemets : curl -H "Header-Name: value" https://example.com. Les guillemets empêchent le shell de découper en arguments distincts une valeur qui contient des espaces.
Comment envoyer plusieurs en-têtes dans une seule requête cURL ?
Répétez l'option -H une fois par en-tête. Par exemple, curl -H "Accept: application/json" -H "Authorization: Bearer TOKEN" https://api.example.com envoie les deux. Il n'y a pas de limite pratique, et cURL préserve l'ordre dans lequel vous les écrivez.
Comment définir un jeton Bearer ou une auth Basic avec cURL ?
Pour un jeton Bearer, passez-le directement : -H "Authorization: Bearer YOUR_TOKEN". Pour l'authentification HTTP Basic, l'option -u user:pass est plus simple que de construire l'en-tête à la main, car cURL encode en base64 les informations d'identification et définit l'en-tête Authorization: Basic pour vous.
Comment consulter uniquement les en-têtes de réponse avec cURL ?
Utilisez -I (ou --head) pour récupérer juste les en-têtes avec une requête HEAD et ignorer le corps. Si vous voulez les en-têtes et le corps ensemble, utilisez -i (ou --include). Pour enregistrer les en-têtes dans un fichier, utilisez -D filename.
Comment supprimer un en-tête par défaut que cURL envoie ?
Passez le nom de l'en-tête avec un deux-points et aucune valeur : curl -H "Accept:" https://example.com retire entièrement l'en-tête Accept. C'est différent de "Accept: value", qui le définit, et de "Accept;", qui l'envoie avec une valeur vide.
Des en-têtes personnalisés empêcheront-ils mon scraper de se faire bloquer ?
Des en-têtes réalistes aident pour les sites légèrement protégés en faisant ressembler votre requête à un navigateur, mais ils ne peuvent pas battre à eux seuls de sérieux systèmes anti-bot ni une mauvaise réputation d'IP. Les en-têtes décrivent la requête, pas sa provenance. Associez-les à des IP résidentielles tournantes, par exemple en routant cURL via le Smart AI Proxy avec l'option -x, pour que votre trafic parte d'adresses de confiance tout en gardant le contrôle total des en-têtes.
Crawlez n'importe quel site à grande échelle, sans combattre l'infrastructure.
Crawlbase gère les proxies, les empreintes et les CAPTCHA afin que votre équipe livre des pipelines de données au lieu de maintenir la plomberie de crawl. 1 000 requêtes gratuites, sans carte requise.
