Comando curl: uso delle opzioni, richieste POST e download di file

Ambiente di testFamiglia RHELAlmaLinux 9.8account rootVerificato il 2026-10-28

Il comando curl è uno strumento che invia una richiesta a un indirizzo web dal terminale e stampa la risposta così com'è. Con una sola riga controlli il corpo della pagina, le intestazioni e il codice di stato. Inviando richieste curl da un server AlmaLinux 9 a un sito WordPress, l'indirizzo http ha risposto con un 301 che indicava l'indirizzo https, e una richiesta alla REST API senza autenticazione è stata rifiutata con 401.

1️⃣ Uso di base del comando curl e corpo della risposta

Se metti un indirizzo dopo curl, invia una richiesta GET a quell'indirizzo e stampa a schermo il corpo della risposta. Chiedendo il robots.txt generato da WordPress, il contenuto del file di tre righe è arrivato così com'è.

curl https://example.com/robots.txt
User-agent: *
Disallow: /wp-admin/
Allow: /wp-admin/admin-ajax.php

È facile aspettarsi la stessa pagina che vedi digitando l'indirizzo nel browser, ma curl stampa l'HTML grezzo inviato dal server. curl non esegue script e non richiede a parte immagini e CSS. L'HTML di una pagina è lungo, quindi per l'indirizzo di una pagina web passiamo l'output a head con una pipe e controlliamo solo le prime righe.

curl -s https://example.com/ | head -n 2
<!DOCTYPE html>
<html lang="ko-KR">

Con -s nascondi l'indicatore di avanzamento che altrimenti si mescola allo schermo quando passi l'output con una pipe. L'HTML ricevuto dal solo indirizzo della home page era di 96.679 byte. I file di immagini e script non sono inclusi in questa dimensione.

2️⃣ Controllare le intestazioni con curl -I e seguire i reindirizzamenti con -L

Dal solo corpo non capisci se la richiesta è andata a buon fine, quindi controlli codice di stato e intestazioni a parte con -I. -I invia una richiesta HEAD e stampa solo le intestazioni della risposta, senza il corpo. È come leggere l'etichetta di spedizione senza aprire il pacco.

curl -I https://example.com/
HTTP/2 200
server: nginx/1.28.0
date: Wed, 28 Oct 2026 05:29:23 GMT
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
last-modified: Tue, 27 Oct 2026 21:12:18 GMT
cache-control: max-age=0
expires: Wed, 28 Oct 2026 05:29:23 GMT
accept-ranges: none
alt-svc: h3=":443"; ma=86400

L'[HTTP/2 200] della prima riga è il codice di stato. Sotto seguono il tipo di server, il tipo di contenuto e le intestazioni della cache. Se invii la stessa richiesta all'indirizzo http, compare un 301 con, nell'intestazione [Location], l'indirizzo https a cui spostarsi.

curl -I http://example.com/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.28.0
Date: Wed, 28 Oct 2026 05:27:51 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://example.com/

Chiedendo l'indirizzo http senza opzioni, curl non ha richiesto di nuovo l'indirizzo di [Location]: ha stampato solo le 7 righe del corpo della risposta 301 e si è chiuso.

curl http://example.com/
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.28.0</center>
</body>
</html>

Con -L, curl richiede di nuovo l'indirizzo di [Location]. Se lo combini con -I ed esegui -IL, le intestazioni della risposta 301 sono seguite in ordine da quelle della risposta 200.

curl -IL http://example.com/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.28.0
Date: Wed, 28 Oct 2026 05:29:23 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://example.com/

HTTP/2 200
server: nginx/1.28.0
date: Wed, 28 Oct 2026 05:29:23 GMT
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
last-modified: Tue, 27 Oct 2026 21:12:18 GMT
cache-control: max-age=0
expires: Wed, 28 Oct 2026 05:29:23 GMT
accept-ranges: none
alt-svc: h3=":443"; ma=86400

Nel diagramma qui sotto puoi confrontare passo per passo quante richieste partono e cosa compare a schermo a seconda dell'opzione.

🧭 Richieste e output per opzione di curl: il 301 dell'indirizzo http
Diagramma esplicativo
⚙️ Opzione
$ curl -I -L -IL http://example.com/
① GETHEAD Richiestahttp://example.com/
➜
301 Moved PermanentlyLocation: https://example.com/
② GETHEAD Richiestahttps://example.com/Nessuna richiesta
➜
200Nessuna risposta
🖥️ Cosa viene stampato a schermo
Corpo della risposta 301 (7 righe di HTML)
Intestazioni della risposta 301, 7 righe
Corpo della risposta 200 (HTML della home page, 96.679 byte)
Intestazioni 301, 7 righe → intestazioni 200, 10 righe
Senza opzioni, curl non richiede di nuovo l'indirizzo https di [Location] e stampa solo il corpo della risposta 301.
-I riceve solo le intestazioni con una richiesta HEAD e, senza chiedere il nuovo indirizzo, stampa lo stato 301 e l'intestazione [Location].
-L invia un'altra richiesta all'indirizzo https di [Location] e stampa il corpo della risposta 200 finale.
-IL stampa in ordine le intestazioni di entrambe le risposte. Dopo il 301 viene il 200.

3️⃣ Scaricare file con il comando curl (-o, -O)

-O salva il file nella cartella corrente con l'ultimo nome di file dell'indirizzo. Durante il salvataggio lo schermo mostra l'indicatore di avanzamento al posto del corpo.

curl -O https://example.com/wp-includes/images/w-logo-blue.png
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100  3113  100  3113    0     0   178k      0 --:--:-- --:--:-- --:--:--  190k
ls -l w-logo-blue.png
-rw-r--r-- 1 root root 3113 Oct 28 14:29 w-logo-blue.png

Dopo il download, [Total] e [Received] nell'indicatore di avanzamento segnavano entrambi 3113, e anche la dimensione del file controllata con ls -l corrispondeva: 3.113 byte.

Per scegliere tu il nome del file, scrivilo dopo -o. Qui sotto c'è il risultato del salvataggio dell'indirizzo della home page come home.html.

curl -o home.html https://example.com/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 96679    0 96679    0     0  4291k      0 --:--:-- --:--:-- --:--:-- 4291k
ls -l home.html
-rw-r--r-- 1 root root 96679 Oct 28 14:29 home.html

-O usa così com'è il nome di file alla fine dell'indirizzo, quindi non va bene per gli indirizzi di pagina che finiscono con una barra. Se aggiungi -O all'indirizzo della home page, curl non trova un nome di file e si chiude con l'errore qui sotto.

curl -O https://example.com/
curl: Remote file name has no length!
curl: (23) Failed writing received data to disk/application

4️⃣ Richieste POST con curl e invio di dati JSON

Per inviare dati con una richiesta che finora si limitava a leggere, usa -d, e aggiungi -H per indicare il formato dei dati. -d invia come corpo POST i dati che scrivi dopo. Se non indichi altro, il [Content-Type] è [application/x-www-form-urlencoded].

Con -d il metodo della richiesta diventa POST, quindi puoi omettere [-X POST]. Anche la documentazione ufficiale spiega che di solito -X non serve.

Per inviare JSON, cambia il [Content-Type] in [application/json] con -H. Qui sotto c'è il risultato di una richiesta di creazione di un articolo inviata alla REST API di WordPress senza autenticazione.

curl -s -X POST -H 'Content-Type: application/json' -d '{"title":"curl test"}' https://example.com/wp-json/wp/v2/posts
{"code":"rest_authentication_error","message":"\uc8c4\uc1a1\ud569\ub2c8\ub2e4. REST API \uc694\uccad\uc744 \ud560 \uc218 \uc788\ub294 \uad8c\ud55c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.","data":{"status":401}}

Il sito a cui abbiamo inviato la richiesta blocca le richieste REST API degli utenti che non hanno effettuato l'accesso e perciò code ha restituito [rest_authentication_error], con stato 401. Per la stessa impostazione, anche una richiesta GET dell'elenco degli articoli allo stesso indirizzo ha restituito 401. Il valore di message è una frase di errore scritta nella lingua del sito e convertita nella notazione Unicode di JSON.

Per controllare solo il codice di stato, scarta il corpo con [-o /dev/null] e stampa solo http_code con -w.

curl -s -o /dev/null -w '%{http_code}\n' -X POST -H 'Content-Type: application/json' -d '{"title":"curl test"}' https://example.com/wp-json/wp/v2/posts
401

5️⃣ Misurare il tempo di risposta con il comando curl (-w)

Quando una risposta è lenta viene da guardare solo total, ma per capire se il tempo è andato nella connessione o nell'elaborazione del server devi stampare a parte il tempo di ogni fase. -w stampa i valori misurati nel formato che indichi quando la richiesta finisce. I valori riempiono i posti [%{nome della variabile}] del formato.

Scarta il corpo con [-o /dev/null] e nascondi l'indicatore di avanzamento con -s.

curl -o /dev/null -s -w 'code: %{http_code}\nconnect: %{time_connect}\ntls: %{time_appconnect}\nttfb: %{time_starttransfer}\ntotal: %{time_total}\n' https://example.com/
code: 200
connect: 0.001507
tls: 0.017728
ttfb: 0.021912
total: 0.022825

connect è la connessione TCP, tls la negoziazione TLS, ttfb il tempo fino a poco prima dell'invio del primo byte e total il tempo fino alla fine del trasferimento. Tutti e quattro i valori sono secondi accumulati dall'inizio della richiesta.

Poiché il server che eseguiva curl e il sito che riceveva la richiesta stavano sullo stesso server, la connessione è durata solo 0,0015 secondi; la negoziazione TLS era finita a 0,0177 secondi e il primo byte è arrivato a 0,0219 secondi. Dalla fine della negoziazione TLS all'arrivo del primo byte sono passati circa 0,004 secondi. La documentazione ufficiale spiega che questa fase include il tempo che il server impiega per produrre il risultato.

Eseguendo lo stesso comando altre tre volte, total è rimasto tra 0,0219 e 0,0226 secondi.

🔲 Simulatore del comando curl

Nel simulatore qui sotto puoi digitare tu i comandi visti finora e controllare come cambia l'output con ogni opzione.

Simulatore del comando curlcurl 7.76.1
[root@server work]#
Con i tasti ↑↓ richiami i comandi digitati prima.

🔢 FAQ & contenuti consigliati

-s nasconde sia l'indicatore di avanzamento sia i messaggi di errore. Chiedendo un indirizzo che non esiste, non è stato stampato nulla ed è rimasto solo il codice di uscita 6. Se indichi -sS, l'indicatore di avanzamento resta nascosto, ma errori come [curl: (6) Could not resolve host] compaiono comunque.

-k salta il passaggio che controlla se la connessione è sicura, quindi curl invia i dati senza verificare che il server raggiunto appartenga davvero a quel dominio. curl controlla che il certificato del server contenga il nome di dominio a cui ti sei collegato e che si possa verificare con l'archivio dei certificati. Se compare questo errore, controlla prima il nome di dominio e l'ente emittente del certificato.

Secondo la documentazione ufficiale, quando riceve una risposta 301, 302 o 303, curl trasforma la richiesta successiva in GET. Per mantenere POST, usa opzioni dedicate come [--post301]. Un metodo indicato con -X ha la precedenza su questa conversione.

🧭 Contenuti consigliati sui comandi di rete 9 articoli · 2 riferimenti
🗂️ Comandi di rete
📄 Comando SSH 📄 Comando rsync 📄 Comando wget 📄 Comandi rz · sz 📄 Comando curl
📄 Comando host 📄 Comando nslookup
📄 Comando ip 📄 Comandi netstat · ifconfig

ℹ️ Informativa sull'affiliazione
I contenuti di questo sito includono link di affiliazione. Se un visitatore acquista un prodotto o un servizio tramite uno di questi link, il sito riceve una commissione dal venditore. In questo processo l'importo pagato dall'acquirente (durante le promozioni l'importo scende↓) non aumenta. Prezzi, sconti e disponibilità indicati si riferiscono al momento della stesura e possono differire da quelli reali: prima di acquistare verifica sempre presso il venditore. I prodotti vengono scelti e valutati secondo criteri propri, e le commissioni non influiscono sull'ordine di presentazione né sul contenuto delle valutazioni.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Dimostra di essere umano: 0   +   3   =