Aller au contenu
Administration Linux medium

wget : télécharger en ligne de commande

24 min de lecture

wget récupère un fichier depuis un serveur HTTP, HTTPS ou FTP sans aucune interaction. Vous lui donnez une URL, il écrit le fichier sur le disque, et il sait reprendre un transfert coupé, limiter son débit et aspirer un site entier. C'est l'outil que vous appelez dans un script d'installation, un cron ou un conteneur de build : il tourne sans terminal, sans clavier et sans surveillance.

Cette page est une référence : chaque option est présentée avec le moment où elle sert vraiment en administration. Si vous cherchez plutôt à interroger une API REST, à lire des en-têtes ou à envoyer du JSON, c'est curl qu'il vous faut. La règle tient en une phrase : wget télécharge, curl dialogue.

Les options décrites ici portent sur GNU Wget 1.21.4, la version livrée avec Ubuntu 24.04. Une option manquante sur une machine plus ancienne se vérifie d'un wget --version.

  • Télécharger un fichier, le renommer et reprendre un transfert interrompu.
  • Scripter wget proprement : silence, journal, délais, tentatives, codes de retour.
  • Récupérer plusieurs fichiers à partir d'une liste ou d'une série numérotée.
  • Aspirer un site en maîtrisant profondeur, domaines et types de fichiers.
  • Vous authentifier par mot de passe, jeton ou cookie, et traverser un proxy.
  • Éviter les pièges classiques : écrasement, globbing inexistant en HTTP, -q qui masque les erreurs.

wget est présent par défaut sur la plupart des distributions serveur, mais pas dans toutes les images de conteneur minimales, où seul curl est parfois installé. Le réflexe avant de bâtir un script dessus : vérifier sa présence avec wget --version, sous peine de voir le build casser en production.

Fenêtre de terminal
sudo apt install wget

La commande suit toujours la même forme : des options, puis une ou plusieurs URL. Les options se placent avant ou après l'URL, mais les grouper avant reste bien plus lisible dans un script.

Fenêtre de terminal
wget [options] URL...

Voici les dix options que vous utiliserez réellement au quotidien. Chacune est détaillée plus bas avec son contexte d'usage : une page de référence ne sert à rien si elle ne dit pas quand sortir l'option du tiroir.

OptionRôleQuand elle sert
-O fichierÉcrit dans le fichier indiquéImposer un nom, ou écrire vers /dev/null
-cReprend un transfert partielISO ou dump coupé en cours de route
-ncNe réécrit pas un fichier existantScript rejoué plusieurs fois
-q / -nvSilence total / sortie condenséeCron, CI, logs propres
-i liste.txtLit les URL dans un fichierLot de paquets ou d'artefacts
-P dossierRange les fichiers dans un dossierÉviter de polluer le répertoire courant
--limit-rate=RATEPlafonne le débitNe pas saturer un lien partagé
--tries=N / --timeout=STentatives et délaisRendre un script prévisible
--spiderTeste sans téléchargerVérifier qu'une URL répond encore
-mMiroir d'un siteSauvegarde d'une documentation

Sans option, wget enregistre le fichier sous le dernier segment de l'URL, dans le répertoire courant, et affiche une barre de progression. C'est le cas d'usage de loin le plus fréquent : récupérer une image ISO, un paquet ou un binaire de release.

Fenêtre de terminal
wget https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA256SUMS

Le fichier SHA256SUMS apparaît dans le dossier courant. Vérifiez toujours d'un ls -l que la taille n'est pas nulle : un serveur qui renvoie une page d'erreur HTML produit un fichier bien présent, mais inutilisable.

L'option -O (lettre O majuscule, pour output document) impose le nom local. Elle est indispensable quand l'URL se termine par un identifiant illisible, et quand vous voulez jeter le contenu vers /dev/null en ne gardant que le code de retour.

Fenêtre de terminal
wget -O jq https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-amd64
chmod +x jq

Deux variantes utiles évitent de deviner le nom. --content-disposition respecte le nom annoncé par le serveur dans l'en-tête Content-Disposition, ce que font les releases GitHub derrière leurs URL de redirection :

Fenêtre de terminal
wget --content-disposition https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-amd64
# écrit bien : jq-linux-amd64

--trust-server-names nomme le fichier d'après l'URL finale après redirection, et non d'après celle que vous avez tapée. Sur un lien court qui redirige vers installeur-2.14.tar.gz, la différence est très concrète : sans l'option, wget écrit un fichier portant le nom de départ, souvent illisible.

Contrairement à une intuition répandue, wget n'écrase pas un fichier de même nom : il crée SHA256SUMS.1, puis SHA256SUMS.2. Dans un script rejoué tous les jours, vous accumulez donc des doublons numérotés qui remplissent le disque sans aucun message.

L'option -nc (no-clobber) coupe court : si le fichier est déjà présent, wget ne télécharge rien, ne renumérote rien et passe au suivant.

Fenêtre de terminal
wget -nc https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA256SUMS
# File ‘SHA256SUMS’ already there; not retrieving.

C'est le bon réflexe pour un cache local d'artefacts. Attention toutefois : -nc ne vérifie ni la date ni le contenu. Si le fichier distant a changé, vous gardez l'ancien. Pour rafraîchir en fonction de la date, utilisez -N (timestamping), qui ne retélécharge que si la copie distante est plus récente que la locale.

Sur une ISO de 4 Go coupée à 80 %, relancer wget à zéro est une perte de temps. L'option -c (continue) envoie un en-tête Range au serveur, qui répond 206 Partial Content et reprend à l'octet exact où le transfert s'était arrêté.

Fenêtre de terminal
wget -c https://releases.ubuntu.com/24.04/ubuntu-24.04-live-server-amd64.iso

La reprise n'est possible que si le serveur accepte les requêtes partielles. S'il les ignore, wget repart du début : c'est le comportement attendu, pas un bug. Et si le fichier local est plus gros que le distant, wget considère qu'il n'y a rien à reprendre.

Un wget lancé à la main peut se permettre d'être bavard. Dans un cron, un pipeline CI ou un Dockerfile, il doit être silencieux, borné dans le temps et vérifiable. Ces quatre réglages font la différence entre un script fiable et un script qui pend indéfiniment un vendredi soir.

-q (quiet) supprime toute sortie, y compris les erreurs. -nv (no-verbose) supprime la barre de progression mais conserve les messages d'erreur et une ligne de résumé par fichier : c'est le meilleur compromis pour un journal de CI.

Fenêtre de terminal
wget -nv -O /tmp/SHA256SUMS https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA256SUMS

Pour un très gros transfert lancé depuis une session SSH, -b détache wget en arrière-plan et -o écrit le déroulé dans un fichier de log. La session peut alors se fermer sans interrompre la récupération.

Fenêtre de terminal
wget -b -o /var/log/iso-ubuntu.log https://releases.ubuntu.com/24.04/ubuntu-24.04-live-server-amd64.iso

C'est le point le plus souvent oublié. Avec -q, une erreur 404 ne produit aucun message : le script continue comme si tout allait bien, et échoue trois étapes plus loin sur un fichier vide. Seul le code de retour dit la vérité.

Fenêtre de terminal
wget -q -O paquet.deb https://depot.interne.lan/paquets/agent_2.4.1_amd64.deb
echo "code de retour : $?"
CodeSignification observéeCause typique
0Téléchargement réussiRien à faire
4Échec réseauDNS introuvable, hôte injoignable
8Le serveur a répondu par une erreur404, 403, 500

D'où le réflexe à ancrer dans tout script : tester le code de retour, ou laisser set -e interrompre l'exécution. Un téléchargement non vérifié est un échec silencieux en attente.

Fenêtre de terminal
if ! wget -nv -O paquet.deb https://depot.interne.lan/paquets/agent_2.4.1_amd64.deb; then
echo "Téléchargement du paquet impossible, on arrête là." >&2
exit 1
fi

Par défaut, wget réessaie 20 fois, ce qui peut faire pendre un script très longtemps sur un serveur qui ne répond pas. Deux options remettent de l'ordre : --tries fixe le nombre de tentatives, --timeout fixe les délais.

Fenêtre de terminal
wget --tries=2 --timeout=10 -O agent.deb https://depot.interne.lan/paquets/agent_2.4.1_amd64.deb

Retenez la portée exacte de --timeout : il règle d'un coup les trois délais, à savoir la résolution DNS, l'établissement de la connexion et la lecture des données. Si vous avez besoin de finesse, les trois options existent séparément :

  • --dns-timeout=SEC : délai de résolution du nom.
  • --connect-timeout=SEC : délai d'établissement de la connexion TCP.
  • --read-timeout=SEC : délai d'inactivité pendant le transfert.

Sur un hôte injoignable, --tries=2 --timeout=3 rend la main en quelques secondes au lieu de plusieurs minutes. C'est exactement ce que vous voulez dans un healthcheck ou une tâche planifiée.

Un wget lancé sur une grosse ISO sature volontiers le lien partagé du site et fait souffrir tout le monde. --limit-rate plafonne le débit, en k (kilo-octets) ou m (méga-octets) par seconde.

Fenêtre de terminal
wget --limit-rate=500k https://releases.ubuntu.com/24.04/ubuntu-24.04-live-server-amd64.iso

L'effet est immédiat et mesurable : 5 Mio plafonnés à 500 k/s prennent 10 secondes au lieu d'être avalés instantanément. C'est la bonne manière de récupérer une grosse image en heures ouvrées sans dégrader la ligne partagée.

--spider effectue la requête, lit la réponse et n'écrit rien sur le disque. Combiné au code de retour, il donne une sonde d'URL en une ligne, parfaite pour vérifier qu'un miroir interne répond encore ou qu'un lien de documentation n'est pas mort.

Fenêtre de terminal
wget --spider -q https://depot.interne.lan/paquets/agent_2.4.1_amd64.deb
echo $? # 0 : l'URL répond ; 8 : le serveur renvoie une erreur

Ajoutez -S (server response) pour afficher les en-têtes HTTP renvoyés et diagnostiquer une redirection en boucle ou un cache mal configuré.

Trois approches, selon la forme de votre besoin : une liste d'URL connue, une série numérotée, ou une logique plus riche qui réclame une boucle shell.

L'option -i lit un fichier texte contenant une URL par ligne. C'est la méthode la plus robuste pour récupérer un lot de paquets ou d'artefacts, parce que la liste est versionnable et relisable avant exécution.

Fenêtre de terminal
cat > paquets.txt <<'EOF'
https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA256SUMS
https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA512SUMS
EOF
wget -nv -i paquets.txt -P /srv/miroir/

-P range tout dans le dossier de destination indiqué, sans polluer le répertoire courant. Ajoutez -c pour rejouer la liste après une coupure sans repartir de zéro.

C'est une confusion fréquente : wget ne génère pas d'URL à partir d'un motif en HTTP. Écrire wget https://serveur/rapport-0[1-5].csv demande littéralement le fichier nommé rapport-0[1-5].csv au serveur, qui répond par une erreur 404. Le motif entre crochets est la syntaxe de curl, pas celle de wget.

La solution avec wget consiste à laisser le shell générer les URL, grâce à l'expansion d'accolades de Bash. L'accolade est développée avant l'appel, et wget reçoit donc plusieurs URL distinctes :

Fenêtre de terminal
wget https://depot.interne.lan/rapports/rapport-0{1..5}.csv

Bash gère aussi les zéros en tête et les pas d'incrément, ce qui couvre la quasi-totalité des besoins réels, comme une série de dumps numérotés :

Fenêtre de terminal
wget https://depot.interne.lan/sauvegardes/dump-{01..10}.sql.gz

Avec curl, le motif entre crochets fonctionne nativement, et -O conserve le nom distant de chaque fichier :

Fenêtre de terminal
curl -O "https://depot.interne.lan/rapports/rapport-0[1-5].csv"

Dès qu'il faut renommer, filtrer ou tester entre deux téléchargements, la boucle reprend l'avantage. Elle rend aussi le script plus lisible qu'une commande wget surchargée d'options.

Fenêtre de terminal
while read -r url; do
wget -nc -nv -P /srv/miroir/ "$url" || echo "Échec : $url" >> /tmp/echecs.txt
done < paquets.txt

Les guillemets autour de $url ne sont pas décoratifs : sans eux, une URL contenant & ou un espace casse la commande. wget n'est pas parallèle : pour accélérer, lancez plusieurs instances en arrière-plan avec & puis wait, en gardant à l'esprit que vous multipliez la charge sur le serveur distant.

Le mode récursif suit les liens contenus dans les pages HTML et télécharge ce qu'il trouve. C'est la fonction qui distingue vraiment wget de curl : elle sert à archiver une documentation avant la coupure d'un service, ou à garder une copie hors ligne d'un site interne.

-r active le suivi des liens, -m (mirror) est le raccourci prêt à l'emploi. Le manuel est formel : -m équivaut à -r -N -l inf --no-remove-listing, donc profondeur infinie, mise à jour par date et conservation des listings FTP.

Fenêtre de terminal
wget -m -k -p -np -nH https://docs.interne.lan/runbooks/

Cette combinaison est celle qu'on utilise réellement pour un archivage :

  • -k (--convert-links) réécrit les liens pour qu'ils pointent vers les fichiers locaux, sans quoi la copie n'est pas navigable hors ligne.
  • -p (--page-requisites) récupère images, CSS et scripts nécessaires à l'affichage.
  • -np (--no-parent) interdit de remonter au-dessus du dossier de départ.
  • -nH (--no-host-directories) évite de créer un dossier au nom du serveur.

Une précision qui évite beaucoup d'incompréhension : wget ne découvre que les fichiers réellement liés depuis les pages parcourues. Un fichier présent sur le serveur mais qu'aucun lien ne référence ne sera jamais récupéré : le mode récursif n'est pas un explorateur de répertoires.

Par défaut, la profondeur de récursion est de 5 niveaux. -l la modifie, -l inf la rend infinie. Une aspiration mal bornée peut télécharger des gigaoctets : commencez toujours petit, puis élargissez.

Fenêtre de terminal
wget -r -l 2 -np https://docs.interne.lan/runbooks/

Par sécurité, wget reste sur l'hôte de départ. Pour élargir, -H (--span-hosts) autorise les autres hôtes, et se borne alors avec -D (--domains) ou --exclude-domains. Le trio se lit comme une liste blanche et une liste noire de domaines.

Fenêtre de terminal
wget -r -l 2 -H -D docs.interne.lan,cdn.interne.lan https://docs.interne.lan/runbooks/

-A (accept) et -R (reject) prennent une liste d'extensions séparées par des virgules, ce qui suffit dans la plupart des cas. Pour cibler un motif d'URL, --accept-regex et --reject-regex acceptent une expression régulière.

Fenêtre de terminal
# Ne récupérer que les PDF et les archives d'un dépôt interne
wget -r -l 2 -np -A pdf,tar.gz https://docs.interne.lan/livrables/
# Ignorer les URL contenant un identifiant de session
wget -r -np --reject-regex ".*\?sessionid=.*" https://docs.interne.lan/runbooks/

Ajoutez -Q (quota) pour plafonner le volume total téléchargé, par exemple -Q500m. C'est le garde-fou qui évite de remplir un disque pendant la nuit, et il se combine avec -l pour borner l'aspiration sur deux axes.

Trois mécanismes couvrent l'essentiel des ressources protégées que vous rencontrerez : le mot de passe HTTP, le jeton dans un en-tête, et le cookie de session. Dans les trois cas, la règle de sécurité est la même : ne jamais écrire un secret dans la ligne de commande, car elle est visible de tous via ps aux et finit dans l'historique du shell.

--http-user et --http-password fournissent les identifiants d'une authentification Basic ou Digest : wget choisit la méthode annoncée par le serveur, vous n'avez rien à forcer.

Fenêtre de terminal
wget --http-user=deploy --ask-password https://depot.interne.lan/paquets/agent_2.4.1_amd64.deb

--ask-password demande le mot de passe de manière interactive, sans le laisser en clair dans la ligne de commande : c'est la forme à privilégier en usage manuel. Pour un script, préférez un fichier ~/.netrc en chmod 600, que wget lit automatiquement. L'option --auth-no-challenge envoie les identifiants dès la première requête, sans attendre le défi du serveur ; ne l'activez que si le serveur l'exige, car elle expose le mot de passe même quand ce n'était pas nécessaire.

Les dépôts d'artefacts et les API attendent le plus souvent un jeton Bearer. --header ajoute un en-tête HTTP arbitraire, et la variable d'environnement garde le secret hors de la ligne de commande.

Fenêtre de terminal
export DEPOT_TOKEN="..." # lu depuis un coffre, jamais écrit dans le script
wget --header="Authorization: Bearer ${DEPOT_TOKEN}" \
-O agent.deb https://depot.interne.lan/api/paquets/agent-2.4.1

--header peut être répété autant de fois que nécessaire, par exemple pour ajouter un en-tête Accept: ou un en-tête maison exigé par un proxy d'entreprise.

Pour une application qui protège ses téléchargements derrière un formulaire de connexion, il faut d'abord obtenir un cookie, puis le rejouer. --keep-session-cookies est indispensable : sans lui, wget ne sauvegarde que les cookies persistants et jette celui de la session, précisément celui dont vous avez besoin.

Fenêtre de terminal
wget --save-cookies cookies.txt --keep-session-cookies \
--post-data="user=deploy&password=${MDP}" \
-O /dev/null https://portail.interne.lan/login
wget --load-cookies cookies.txt -O rapport.csv https://portail.interne.lan/exports/rapport.csv

Le fichier cookies.txt contient un jeton de session valide : traitez-le comme un mot de passe, mettez-le en chmod 600 et supprimez-le à la fin du script.

wget gère encore le FTP, protocole qu'on croise sur de vieux miroirs internes ou des équipements industriels. Les identifiants passent par --ftp-user et --ftp-password, et une URL en ftps:// bascule sur la variante chiffrée.

Fenêtre de terminal
wget --ftp-user=archives --ask-password ftp://miroir.interne.lan/isos/debian-12.iso

Le FTP simple transporte les identifiants en clair sur le réseau. S'il reste utilisé chez vous, c'est un point à remonter : privilégiez ftps://, ou mieux, un accès HTTPS.

Sur un serveur qui n'a pas d'accès direct à Internet, tout passe par un proxy sortant. wget respecte les variables d'environnement standard, ce qui en fait la méthode la plus simple et la plus portable.

Fenêtre de terminal
export http_proxy="http://proxy.interne.lan:3128/"
export https_proxy="http://proxy.interne.lan:3128/"
export no_proxy="localhost,127.0.0.1,depot.interne.lan"
wget https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA256SUMS

no_proxy liste les destinations qui doivent rester en connexion directe, typiquement vos dépôts internes. Pour un appel ponctuel sans toucher à l'environnement, -e injecte la directive de configuration correspondante, et --proxy-user fournit les identifiants si le proxy authentifie :

Fenêtre de terminal
wget -e "http_proxy=http://proxy.interne.lan:3128" \
--proxy-user=deploy --ask-password \
https://depot.interne.lan/paquets/agent_2.4.1_amd64.deb

À l'inverse, --no-proxy ignore le proxy configuré pour cette requête : c'est le premier test à faire quand un téléchargement interne échoue sans raison apparente. Enfin, sur un réseau à double pile, -4 et -6 forcent la famille d'adresses et règlent bien des lenteurs dues à une IPv6 annoncée mais non routée.

Fenêtre de terminal
wget -4 https://depot.interne.lan/paquets/agent_2.4.1_amd64.deb

Répéter les mêmes options de proxy et de délais dans chaque script est une source d'erreur. Le fichier ~/.wgetrc (configuration personnelle) porte ces valeurs par défaut une fois pour toutes ; /etc/wgetrc fait de même pour toute la machine. Chaque ligne est une directive, pas une commande shell.

~/.wgetrc
http_proxy = http://proxy.interne.lan:3128/
https_proxy = http://proxy.interne.lan:3128/
no_proxy = localhost,127.0.0.1,depot.interne.lan
dns_timeout = 5
connect_timeout = 10
read_timeout = 20
tries = 3
limit_rate = 2m

L'option -e de la ligne de commande accepte exactement ces mêmes directives, et rien d'autre : -e "tries=3" fonctionne, alors que -e "chmod 644" est rejeté avec le message Invalid --execute command. Ce n'est pas une commande shell, et la confusion est fréquente.

Fenêtre de terminal
wget -nv -O jq https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-amd64 \
&& sha256sum jq \
&& chmod +x jq

Cette forme est aussi la bonne pratique de sécurité : vous téléchargez, vous vérifiez l'empreinte, et seulement ensuite vous rendez le binaire exécutable. Ne pipez jamais un téléchargement directement dans un interpréteur : un serveur compromis, ou une simple coupure au milieu du transfert, exécuterait du code arbitraire sur votre machine avant même que vous ayez pu le lire.

Ces erreurs reviennent aussi bien chez les débutants que dans les équipes expérimentées. Les connaître fait gagner des heures de diagnostic : dans la majorité des cas, le symptôme visible est très loin de la cause réelle.

SymptômeCauseSolution
Des fichiers .1, .2 s'accumulentwget ne remplace pas, il numéroteAjouter -nc (cache) ou -N (rafraîchir sur la date)
Le script continue malgré une 404-q masque les erreursTester $?, ou utiliser -nv
rapport-0[1-5].csv renvoie 404Pas de globbing HTTPExpansion d'accolades du shell : rapport-0{1..5}.csv
Le fichier téléchargé est du HTMLLe serveur a renvoyé une page d'erreur ou de login--spider -S pour lire le code et les en-têtes
Le script pend plusieurs minutes20 tentatives par défaut--tries=2 --timeout=10
L'aspiration récupère tout le siteProfondeur infinie avec -mBorner avec -l, -np, -Q
Le fichier n'a pas le bon nom après redirectionNom pris sur l'URL d'origine--content-disposition ou --trust-server-names

Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

  • wget télécharge, curl dialogue : pour une API REST ou un diagnostic HTTP fin, passez à curl.
  • wget n'écrase pas un fichier existant, il crée fichier.1 : utilisez -nc pour ne rien retélécharger, -N pour rafraîchir selon la date.
  • -c reprend un transfert coupé si le serveur accepte les requêtes partielles, ce qui change tout sur une ISO de plusieurs gigaoctets.
  • -q masque les erreurs : dans un script, testez toujours le code de retour (0 succès, 4 échec réseau, 8 erreur du serveur).
  • Bornez vos scripts avec --tries et --timeout, sinon wget réessaie 20 fois par défaut.
  • Le globbing d'URL n'existe pas en HTTP : passez par l'expansion d'accolades du shell (fichier-{1..5}.csv), le motif entre crochets étant propre à curl.
  • -m aspire sans limite de profondeur : encadrez avec -np, -l, -Q et --limit-rate pour ne pas assommer le serveur distant.
  • wget n'exécute rien après le téléchargement : enchaînez dans le shell, en vérifiant l'empreinte avant de rendre un binaire exécutable, et jamais de téléchargement redirigé directement dans un interpréteur.
  • Référence httpie : Alternative ergonomique à curl pour les échanges API en ligne de commande.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn