Notre point de vue, en toute franchise : nous sommes Geonode et nous vendons des proxys ; il faut donc savoir que, lorsqu'on télécharge des fichiers via un proxy, le coût repose entièrement sur la bande passante et les fichiers sont volumineux. Acheminer un téléchargement de 4 Go via un forfait résidentiel facturé à 0,79 $/Go revient à environ 3,16 $ pour un seul fichier, contre 0,56 $ via le trafic d'un centre de données facturé à 0,14 $/Go. Si votre téléchargement n’a pas besoin de donner l’impression de provenir d’une connexion grand public — ce qui est le cas de la plupart des téléchargements —, utiliser la bande passante résidentielle revient à jeter son argent par les fenêtres. Les prix sont tirés de notre page de tarifs, consultée en septembre 2026. Mieux encore : si vous pouvez télécharger directement, faites-le, et vous ne paierez rien.
Cela étant dit, voici comment procéder correctement.
Les trois façons de nommer le fichier de sortie
Par défaut, curl écrit sur la sortie standard, ce qui explique pourquoi une commande naïve comme ``curl https://example.com/file.zip`
` remplit votre terminal de données binaires. Trois options permettent de modifier ce comportement.
**-o filename
** écrit dans un fichier dont vous choisissez le nom :
curl -o archive.zip https://example.com/download?id=1234
. Utilisez cette option lorsque vous savez comment vous souhaitez nommer le fichier, et en particulier lorsque l'URL ne contient pas de nom de fichier utile.
**-O
** utilise le nom du fichier distant. Le manuel de curl le décrit ainsi : « Écrit la sortie dans un fichier portant le même nom que le fichier distant. Seule la partie « nom de fichier » du fichier distant est utilisée ; le chemin d’accès est supprimé. »
curl -O https://example.com/files/report.pdf
# saves as report.pdf
Notez la mise en garde contenue dans cette phrase. Le chemin d’accès est ignoré ; par conséquent, deux fichiers portant le même nom de base mais situés dans des répertoires différents s’écraseront mutuellement. Et si l’URL se termine par une barre oblique ou ne comporte pas de composante « nom de fichier », la commande -O
échouera.
**-J
** récupère plutôt le nom à partir de l’en-tête Content-Disposition
du serveur. Il est documenté comme indiquant à -O
« d’utiliser le nom de fichier Content-Disposition spécifié par le serveur au lieu d’en extraire un de l’URL ». Utile pour les points de terminaison de téléchargement où l’URL est un identifiant opaque.
Cette option fait également l’objet de l’avertissement le plus catégorique du manuel, qu’il convient de citer ici :
AVERTISSEMENT : Le nom de fichier spécifié dans l’en-tête Content-Disposition n’est ni validé ni nettoyé. Il peut contenir des séquences de traversée de chemin (..). N’enregistrez pas la sortie dans un emplacement non fiable ou sans avertissement préalable lorsque cette option est activée.
En d’autres termes, l’option ``-OJ`
permet à un serveur distant de choisir un chemin d’accès sur votre système de fichiers. Si la source est sous votre contrôle, cela ne pose pas de problème. Dans un script récupérant des données à partir d’URL arbitraires, cela constitue une vulnérabilité. Si vous avez besoin de noms fournis par un serveur provenant de sources non fiables, récupérez les en-têtes, nettoyez le nom vous-même, puis utilisez l’option ``-o
`.
Redirections : pourquoi l'option « -L » est presque toujours nécessaire
Par défaut, curl ne suit pas les redirections. La documentation relative à l'option « -L » indique : « Suivre les redirections HTTP et répéter les requêtes avec la méthode initialement spécifiée. »
C'est la raison la plus courante pour laquelle un téléchargement génère un petit fichier contenant du code HTML au lieu du contenu souhaité. Les URL de téléchargement redirigent constamment — vers des CDN, des URL signées, des miroirs ou des points de terminaison régionaux. Sans l’option -L, vous enregistrez la page de redirection.
curl -L -O https://example.com/latest.tar.gz
Deux points à noter à ce sujet.
L’ordre est important avec l’option -o. Lorsqu’il suit des redirections comportant plusieurs URL, curl fait correspondre les arguments de -o aux URL en fonction de leur position. Avec une seule URL, cela ne pose pas de problème, mais cela peut surprendre les utilisateurs qui écrivent des commandes comportant plusieurs URL.
Limitez le nombre de redirections. L’option --max-redirs limite le nombre de redirections que curl suivra. La valeur par défaut est généreuse, et une boucle de redirections sans limite n’est pas un scénario d’échec souhaitable dans une tâche cron.
L'échec silencieux : enregistrer les pages d'erreur sous forme de fichiers
C'est le point le plus important de cet article.
Par défaut, curl considère une réponse d'erreur HTTP comme un transfert réussi. Une erreur 404 comporte un corps ; curl télécharge ce corps ; curl se termine avec un code de sortie 0. Vous disposez désormais d’un fichier nommé installer.dmg
contenant une page HTML indiquant « Not Found », et votre script a continué comme si tout fonctionnait normalement.
L’option --fail
permet de corriger cela. Extrait du manuel : « Renvoie un code d’erreur 22 pour les réponses HTTP dont le code d’état est égal ou supérieur à 400, sans corps de réponse. »
curl --fail -L -O https://example.com/installer.dmg
Désormais, une erreur 404 génère le code de sortie 22 et aucun fichier n’est créé. Votre script peut vérifier cela.
Deux améliorations :
**--fail-with-body
** fait la même chose mais conserve le corps de la réponse, ce qui est utile lorsque les API renvoient des messages d’erreur JSON pertinents que vous souhaitez consigner.
**--fail
n’est pas parfait.** Il ne détecte pas les serveurs renvoyant un code 200 avec une page d’erreur, ce que certains font. Pour tout élément important, vérifiez le résultat : assurez-vous que la taille du fichier est plausible, vérifiez la somme de contrôle si elle est publiée, ou vérifiez les octets magiques :
curl --fail -L -o pkg.tar.gz "$URL" || exit 1
file pkg.tar.gz | grep -q gzip || { echo "not a gzip archive"; exit 1; }
La ligne de téléchargement canonique, pour les scripts, est donc :
curl --fail --silent --show-error --location -o output.bin "$URL"
-sS
supprime la jauge de progression tout en conservant les messages d’erreur, ce qui est souhaitable dans le cadre d’une automatisation. Pour une utilisation interactive, -#
vous offre une simple barre de progression plutôt que la jauge par défaut.
Reprise des téléchargements interrompus
Les fichiers volumineux et les connexions instables rendent cette fonctionnalité indispensable. L'option `
`-C -`` est décrite comme suit : « Reprend un transfert précédent à partir de l'offset en octets indiqué. Utilisez « -C - » pour demander à curl de déterminer automatiquement où et comment reprendre le transfert. »
curl -C - -L -O https://example.com/large-file.iso
curl vérifie la taille du fichier local et ne demande que la partie manquante à l’aide d’un en-tête « Range ». Associé à des tentatives de réessai, cela permet de mener à bien les téléchargements longs :
curl --fail -L -C - --retry 5 --retry-delay 5 -O https://example.com/large-file.iso
Trois mises en garde.
Le serveur doit prendre en charge les requêtes par plage. Si ce n’est pas le cas, curl ne peut pas reprendre le téléchargement et devra soit recommencer depuis le début, soit échouer. Vérifiez la présence de « Accept-Ranges: bytes » dans les en-têtes de réponse.
Reprendre un fichier corrompu ne fait que prolonger la corruption de ce fichier. -C - se fie aux octets locaux. Si le fichier partiel a été tronqué en cours d’écriture ou si la source a changé, le résultat est erroné sans que cela soit signalé. Vérifiez à l’aide d’une somme de contrôle lorsque la source en publie une.
Une source modifiée invalide la reprise. Si le fichier a été remplacé entre deux tentatives, vous obtenez un mélange des deux versions sans message d’erreur.
Téléchargement de nombreux fichiers en parallèle
Depuis la version 7.66 de curl, l’option ``-Z`
effectue des « transferts en parallèle plutôt que de manière séquentielle », l’option ``--parallel-max
` permettant de définir le « nombre maximal de transferts à effectuer en parallèle ».
curl -Z --parallel-max 8 --fail -L \
-O https://example.com/a.zip \
-O https://example.com/b.zip \
-O https://example.com/c.zip
À partir d’un fichier contenant des URL :
xargs -a urls.txt curl -Z --parallel-max 8 --fail -L --remote-name-all
--remote-name-all
applique le comportement de l’option ``-O`
` à chaque URL, ce qui évite d’avoir à répéter cette option.
Choisissez le parallélisme de manière réfléchie. Au-delà d’un certain seuil, « plus » ne signifie pas « mieux » : les serveurs limitent le débit, votre propre connexion est saturée et, au-delà du plateau, vous générez des erreurs au lieu d’un débit utile. Huit est un chiffre de départ raisonnable pour un serveur bien provisionné ; face à un petit hébergeur, quatre ou moins est plus respectueux et souvent plus rapide dans l’ensemble. Le comportement observé ici correspond à la courbe de débit que nous avons décrite dans concurrence vs parallélisme : elle augmente, atteint un plateau, puis diminue.
Répertoires, horodatages et limites de débit
Trois options qui permettent d’éviter d’avoir à écrire les scripts de wrapper que l’on utilise couramment.
**--output-dir
** — « Spécifie le répertoire dans lequel enregistrer les fichiers. Cette option fonctionne avec les options --remote-name ou --output. » Plus besoin d’utiliser cd
avant et après.
**--create-dirs
** — avec l’-o
, « curl crée la hiérarchie de répertoires locaux nécessaire. Les répertoires créés utilisent le mode 0750 sur les systèmes Unix. » Notez bien le mode : 0750, et non 0755. Si un autre utilisateur ou service a besoin de lire ces répertoires, cela risque de vous surprendre.
curl --fail -L --create-dirs -o data/2026/09/report.pdf https://example.com/report.pdf
**--remote-time
** — « définit la date et l’heure de modification du fichier système pour qu’elles correspondent à l’horodatage du fichier distant ». Vraiment utile pour la mise en miroir, car cela permet aux outils suivants de déterminer la fraîcheur des données.
**--limit-rate
** — « Limite la vitesse de transfert au débit spécifié », en acceptant les suffixes k
, M
et G
:
curl --limit-rate 2M -L -O https://example.com/large.iso
Une option qu’il vaut mieux utiliser plus souvent qu’on ne le fait. Saturer votre liaison montante rend tout le reste du réseau inutilisable, et sur une connexion partagée ou à volume limité, limiter le débit est une simple question de courtoisie. Cela réduit également le risque qu’un serveur vous considère comme un utilisateur abusif.
Récapitulatif des options pratiques :
curl --fail --location --continue-at - --retry 5 \
--remote-time --create-dirs \
--output downloads/archive.tar.gz \
"$URL"
Téléchargement via un proxy
Ajoutez -x
: toutes les instructions ci-dessus restent valables, avec trois précisions supplémentaires.
curl -x http://user:pass@proxy.example.com:9000 \
--fail -L -O https://example.com/file.zip
Il faut repenser les délais d’expiration. --max-time
n’est pas l’outil adapté aux téléchargements de taille imprévisible, car un transfert volumineux légitime dépassera toute limite fixe. Utilisez plutôt le détecteur de blocage basé sur la vitesse :
curl -x "$PROXY" --fail -L \
--connect-timeout 10 --speed-limit 1000 --speed-time 30 \
-O https://example.com/large.iso
Celui-ci interrompt le téléchargement si le débit reste inférieur à 1 000 octets par seconde pendant 30 secondes, tout en laissant se poursuivre un téléchargement lent mais progressif s'étalant sur plusieurs heures. Nous avons abordé l'ensemble des options de délai d'expiration dans la configuration d'un délai d'expiration avec curl.
Le comportement de reprise interagit avec la rotation. Si votre proxy fait tourner les adresses de sortie à chaque connexion, un transfert repris provient d’une adresse différente de celle d’origine. Certains serveurs l’acceptent ; d’autres renvoient vers un miroir différent ; d’autres encore rejettent la requête de plage. Pour les téléchargements longs, utilisez une session qui conserve la même adresse de sortie.
La bande passante est facturée dans les deux sens dans votre tête, mais une seule fois dans la réalité. Vous payez chaque octet qui transite par le proxy. Combinez cela avec l’option « --retry
» et une interruption à 90 % d’un fichier volumineux, et le calcul devient vite désagréable. Utilisez toujours l’option « -C -
» avec les téléchargements via proxy afin qu’une nouvelle tentative reprenne là où elle s’est arrêtée plutôt que de redémarrer depuis le début.
Vérifier ce que vous avez réellement téléchargé
Un code de sortie égal à zéro signifie que le transfert s'est achevé. Cela ne signifie pas pour autant que vous avez reçu les bons octets, et pour tout ce que vous comptez exécuter, installer ou archiver, il est important de combler cette lacune.
Vérifiez que la taille est plausible. C'est la vérification la plus simple qui soit, et elle permet de détecter les troncatures, les pages d'erreur et les réponses vides :
SIZE=$(stat -c%s pkg.tar.gz 2>/dev/null || stat -f%z pkg.tar.gz)
[ "$SIZE" -gt 100000 ] || { echo "suspiciously small: $SIZE bytes"; exit 1; }
Vérifiez le type de fichier. Une page d'erreur HTML enregistrée avec l'extension .tar.gz
est invisible pour une vérification de taille si la page est suffisamment volumineuse, mais elle est détectée par file
:
file pkg.tar.gz | grep -q 'gzip compressed' || exit 1
Vérifiez une somme de contrôle publiée. Lorsque la source en publie une, c’est la seule vérification qui porte sur le contenu plutôt que sur la forme :
curl --fail -sL -O https://example.com/pkg.tar.gz
curl --fail -sL -O https://example.com/pkg.tar.gz.sha256
sha256sum -c pkg.tar.gz.sha256 || exit 1
Notez bien cette limitation, car elle est souvent mal comprise : récupérer la somme de contrôle depuis le même serveur via la même connexion vous protège contre la corruption et la troncature, mais pas contre une source compromise. Si le serveur fournit un fichier corrompu, il fournira une somme de contrôle corrompue correspondante. La vérification de la signature avec GPG permet de remédier à cela, et cette étape supplémentaire en vaut la peine pour tout ce qui s’exécute avec des privilèges.
**Comparez avec Content-Length
lorsque cela est possible.** La commande curl renvoie un code de sortie différent de zéro (erreur 18) lorsqu’un transfert se termine avant la longueur annoncée, ce qui détecte automatiquement une catégorie de troncature — mais uniquement lorsque le serveur a annoncé une longueur, ce qui n’est pas le cas des réponses par blocs.
Pour les téléchargements via un proxy, mieux vaut vérifier davantage que pas assez. Un saut supplémentaire représente un point supplémentaire où le transfert peut être interrompu ou, dans le cas d’un intermédiaire filtrant, altéré. Les vérifications ci-dessus ne prennent que quelques millisecondes et éliminent toute une catégorie de rapports de bogues prêtant à confusion.
Quand curl n'est pas l'outil adapté
curl est excellent pour récupérer le contenu d'une URL. Pour plusieurs tâches connexes, il existe toutefois de meilleurs outils.
Téléchargements récursifs et mise en miroir. curl récupère les URL que vous lui indiquez. Il n'effectue pas de crawl. Pour mettre en miroir un répertoire ou un site, wget -r ou un outil dédié à la mise en miroir est le bon choix — une comparaison que nous avons approfondie dans curl vs wget.
Fichiers très volumineux sur des liaisons peu fiables. Les gestionnaires de téléchargement spécialisés gèrent mieux que curl les transferts segmentés et la reprise agressive. curl, associé à -C - et à des tentatives de réessai, est suffisant ; les outils spécialisés sont toutefois plus performants.
Torrents, rsync, S3 et autres. Il s’agit de protocoles différents, dotés de leurs propres clients, qui gèrent nativement l’intégrité, la déduplication et les autorisations. aws s3 cp n’est pas simplement une version de curl avec des étapes supplémentaires.
Lorsqu’un gestionnaire de paquets existe. curl | sh pour l’installation de logiciels est pratique, mais confère à un serveur distant un droit d’exécution arbitraire sur votre machine, sans aucune vérification. Utilisez le gestionnaire de paquets lorsqu’il en existe un.
Téléchargements répétés d’une même ressource. Si vous récupérez un fichier à intervalles réguliers pour vérifier s’il a changé, les requêtes conditionnelles avec -z ou If-None-Match évitent de télécharger à nouveau du contenu inchangé. Un cache vaut mieux qu’un téléchargement rapide.
Questions fréquentes
Comment télécharger un fichier avec curl ? La commande
curl -O https://example.com/file.zip l'enregistre sous le nom du fichier distant, tandis que -o name vous permet de choisir le nom. En pratique, ajoutez --fail et -L : sans ces options, curl ne suivra aucune redirection et enregistrera les pages d'erreur comme s'il s'agissait du fichier demandé.
Pourquoi curl télécharge-t-il un fichier vide ou un fichier HTML ?
Il s’agit presque toujours d’une redirection que vous n’avez pas suivie — ajoutez -L — ou d’une erreur HTTP enregistrée sous forme de fichier, ce que --fail permet d’éviter. Vérifiez ce que vous avez obtenu avec file downloaded.zip ou en ouvrant le fichier dans un éditeur de texte ; une page d’erreur HTML est immédiatement reconnaissable.
Comment reprendre un téléchargement interrompu avec curl ?
curl -C - -O <url>. curl vérifie la taille du fichier local et demande le reste via une requête par plage. Le serveur doit prendre en charge les plages — vérifiez Accept-Ranges: bytes — et sachez que la reprise d’un fichier partiel corrompu produit un fichier corrompu plus long sans aucun avertissement.
Comment télécharger plusieurs fichiers avec curl ?
Utilisez -Z pour les transferts parallèles avec --parallel-max afin de limiter le nombre de connexions simultanées, et --remote-name-all pour que chaque URL bénéficie du comportement « remote-name ». Pour une liste contenue dans un fichier, acheminez-la via xargs. Limitez le parallélisme à un niveau raisonnable : le débit plafonne puis chute lorsque les serveurs commencent à limiter le débit.
Comment limiter la vitesse de téléchargement dans curl ? L’option `
`--limit-rate 2Mlimite le transfert à 2 mégaoctets par seconde ; cette option accepte les suffixesk, MetG``. Elle est utile sur les connexions partagées et avec les petits serveurs, à la fois pour préserver la disponibilité du reste de votre réseau et pour éviter d’être considéré comme un utilisateur abusif.
Quelle est la différence entre -O et -o dans curl ?
-O utilise le nom de fichier issu de l’URL, en ignorant le chemin d’accès. -o écrit dans un fichier dont vous spécifiez le nom. Utilisez -o lorsque l’URL ne contient pas de nom de fichier utilisable, lorsque vous avez besoin d’un nom spécifique, ou lorsque vous souhaitez éviter les conflits entre des fichiers portant le même nom mais provenant de chemins d’accès différents.
L'option curl -OJ est-elle sûre ?
Pas avec des sources non fiables. Le manuel avertit explicitement que le nom de fichier obtenu via Content-Disposition « n'est ni validé ni nettoyé » et « peut contenir des séquences de traversée de chemin ». Cela signifie qu'un serveur distant choisit l'emplacement où le fichier sera enregistré. Récupérez l'en-tête, nettoyez le nom vous-même, puis utilisez -o.
Comment vérifier si un téléchargement avec curl a réussi ?
Utilisez --fail afin que les erreurs HTTP génèrent un code de sortie 22 plutôt qu’une page d’erreur enregistrée, puis vérifiez le code de sortie. Pour tout élément important, effectuez des vérifications supplémentaires : assurez-vous que la taille du fichier est plausible, exécutez file pour confirmer le type, et comparez la somme de contrôle si la source en publie une.
Conclusion
L'curl -Oe de base que l'on retrouve dans la plupart des exemples fonctionne jusqu'à ce qu'elle ne fonctionne plus, et son mode d'échec est le pire qui soit : un code de sortie égal à zéro et un fichier contenant autre chose que ce que vous aviez demandé.
Deux options permettent de remédier à cela. -L suit les redirections utilisées par pratiquement toutes les véritables URL de téléchargement, et --fail empêche curl d'enregistrer les réponses d'erreur HTTP comme s'il s'agissait de contenu. Ajoutez -C - pour tout fichier volumineux, car un téléchargement reprenable fait la différence entre un problème réseau passager et le fait de devoir tout recommencer.
Pour les scripts, la ligne à retenir est curl --fail --silent --show-error --location, à compléter par --continue-at - et --retry lorsque les fichiers sont volumineux. Et quels que soient les indicateurs utilisés, vérifiez le résultat plutôt que de vous fier uniquement au code de sortie : vérifiez la taille, vérifiez le type, vérifiez la somme de contrôle si elle existe. Les téléchargements échouent plus souvent en silence qu’ils ne signalent leur échec de manière évidente.