Comando curl: uso de opções, requisições POST e download de arquivos

Ambiente de testeFamília RHELAlmaLinux 9.8conta rootVerificado em 2026-10-28

O comando curl é uma ferramenta que envia uma requisição a um endereço web pelo terminal e mostra a resposta exatamente como veio. Com uma única linha, você confere o corpo da página, os cabeçalhos e o código de status. Ao enviar requisições curl de um servidor AlmaLinux 9 para um site WordPress, o endereço http respondeu com um 301 indicando o endereço https, e uma requisição à REST API sem autenticação foi recusada com 401.

1️⃣ Uso básico do comando curl e o corpo da resposta

Se você colocar um endereço depois de curl, ele envia uma requisição GET para esse endereço e mostra na tela o corpo da resposta. Ao pedir o robots.txt que o WordPress gera, o conteúdo do arquivo de três linhas veio exatamente como está.

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

É fácil esperar a mesma página que você vê ao digitar o endereço no navegador, mas o que o curl mostra é o HTML bruto que o servidor enviou. O curl não executa scripts nem pede imagens e CSS separadamente. O HTML de uma página é longo, então, para endereços de páginas web, passamos a saída para o head por um pipe e conferimos só as primeiras linhas.

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

Com -s, o indicador de progresso que se mistura à tela quando a saída passa por um pipe fica oculto. O HTML recebido só do endereço da página inicial tinha 96.679 bytes. Arquivos de imagem e de script não entram nesse tamanho.

2️⃣ Conferir cabeçalhos com curl -I e seguir redirecionamentos com -L

Só pelo corpo não dá para saber se a requisição deu certo, então você confere o código de status e os cabeçalhos separadamente com -I. O -I envia uma requisição HEAD e mostra só os cabeçalhos da resposta, sem o corpo. É como conferir a etiqueta de envio sem abrir a caixa.

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

O [HTTP/2 200] da primeira linha é o código de status. Abaixo vêm o tipo de servidor, o tipo de conteúdo e os cabeçalhos de cache. Se você enviar a mesma requisição ao endereço http, aparece um 301 junto com o endereço https de destino no cabeçalho [Location].

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/

Ao pedir o endereço http sem opções, o curl não fez nova requisição ao endereço de [Location]: mostrou só as 7 linhas do corpo da resposta 301 e terminou.

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>

Com -L, o curl faz nova requisição ao endereço de [Location]. Combinando com -I e executando -IL, os cabeçalhos da resposta 301 são seguidos, em ordem, pelos da resposta 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

No diagrama abaixo, você compara passo a passo quantas requisições saem e o que aparece na tela conforme a opção.

🧭 Requisições e saída por opção do curl: o 301 do endereço http
Diagrama explicativo
⚙️ Opção
$ curl -I -L -IL http://example.com/
① GETHEAD Solicitaçãohttp://example.com/
➜
301 Moved PermanentlyLocation: https://example.com/
② GETHEAD Solicitaçãohttps://example.com/Sem requisição
➜
200Sem resposta
🖥️ O que aparece na tela
Corpo da resposta 301 (7 linhas de HTML)
Cabeçalhos da resposta 301, 7 linhas
Corpo da resposta 200 (HTML da página inicial, 96.679 bytes)
Cabeçalhos 301, 7 linhas → cabeçalhos 200, 10 linhas
Sem opções, o curl não faz nova requisição ao endereço https de [Location] e mostra só o corpo da resposta 301.
O -I recebe só os cabeçalhos com uma requisição HEAD e, sem pedir o novo endereço, mostra o status 301 e o cabeçalho [Location].
O -L faz mais uma requisição ao endereço https de [Location] e mostra o corpo da resposta 200 final.
O -IL mostra em ordem os cabeçalhos das duas respostas. Depois do 301 vem o 200.

3️⃣ Baixar arquivos com o comando curl (-o, -O)

O -O salva o arquivo na pasta atual com o último nome de arquivo do endereço. Enquanto salva, a tela mostra o indicador de progresso em vez do 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

Depois do download, [Total] e [Received] no indicador de progresso marcavam 3113, e o tamanho do arquivo conferido com ls -l também bateu: 3.113 bytes.

Para escolher você mesmo o nome do arquivo, escreva-o depois de -o. Abaixo está o resultado de salvar o endereço da página inicial como 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 -O usa o nome de arquivo do fim do endereço exatamente como está, por isso não serve para endereços de páginas que terminam em barra. Se você adicionar -O ao endereço da página inicial, o curl não encontra um nome de arquivo e termina com o erro abaixo.

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

4️⃣ Requisições POST com curl e envio de dados JSON

Para enviar dados em uma requisição que até agora só lia, use -d, e adicione -H para indicar o formato dos dados. O -d envia como corpo POST os dados que você escrever depois dele. Sem outra indicação, o [Content-Type] é [application/x-www-form-urlencoded].

Com -d, o método da requisição passa a ser POST, então você pode omitir [-X POST]. A documentação oficial também explica que normalmente o -X não é necessário.

Para enviar JSON, mude o [Content-Type] para [application/json] com -H. Abaixo está o resultado de enviar à REST API do WordPress uma requisição de criação de post sem autenticação.

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}}

O site para o qual enviamos a requisição bloqueia requisições à REST API de usuários que não fizeram login e por isso code retornou [rest_authentication_error], com status 401. Pela mesma configuração, pedir com GET a lista de posts no mesmo endereço também retornou 401. O valor de message é uma frase de erro escrita no idioma do site e convertida para a notação Unicode do JSON.

Para ver só o código de status, descarte o corpo com [-o /dev/null] e mostre só o http_code com -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️⃣ Medir o tempo de resposta com o comando curl (-w)

Quando uma resposta está lenta, é fácil olhar só o total, mas para saber se o tempo foi gasto na conexão ou no processamento do servidor é preciso mostrar separadamente o tempo de cada etapa. O -w mostra os valores medidos no formato que você indicar quando a requisição termina. Os valores preenchem os espaços [%{nome da variável}] do formato.

Descarte o corpo com [-o /dev/null] e oculte o indicador de progresso com -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 é a conexão TCP, tls a negociação TLS, ttfb o tempo até pouco antes do envio do primeiro byte e total o tempo até o fim da transferência. Os quatro valores são segundos acumulados desde o início da requisição.

Como o servidor que executava o curl e o site que recebia a requisição estavam no mesmo servidor, a conexão levou só 0,0015 segundo; a negociação TLS terminou em 0,0177 segundo e o primeiro byte chegou em 0,0219 segundo. Do fim da negociação TLS até a chegada do primeiro byte passaram cerca de 0,004 segundo. A documentação oficial explica que essa etapa inclui o tempo que o servidor leva para gerar o resultado.

Ao executar o mesmo comando mais três vezes, o total ficou entre 0,0219 e 0,0226 segundo.

🔲 Simulador do comando curl

No simulador abaixo, você pode digitar os comandos vistos até aqui e conferir como a saída muda com cada opção.

Simulador do comando curlcurl 7.76.1
[root@server work]#
Use as teclas ↑↓ para chamar de volta os comandos digitados antes.

🔢 FAQ & conteúdo recomendado

O -s oculta tanto o indicador de progresso quanto as mensagens de erro. Ao pedir um endereço que não existe, nada apareceu e só restou o código de saída 6. Se você indicar -sS, o indicador de progresso continua oculto, mas erros como [curl: (6) Could not resolve host] continuam aparecendo.

O -k pula a etapa que verifica se a conexão é segura, então o curl envia os dados sem conferir se o servidor alcançado é mesmo daquele domínio. O curl verifica se o certificado do servidor contém o nome de domínio ao qual você se conectou e se ele pode ser validado pelo repositório de certificados. Se esse erro aparecer, confira primeiro o nome de domínio e o emissor do certificado.

Segundo a documentação oficial, ao receber uma resposta 301, 302 ou 303, o curl muda a requisição seguinte para GET. Para manter o POST, use opções específicas como [--post301]. Um método definido com -X tem prioridade sobre essa conversão.

🧭 Conteúdo recomendado sobre comandos de rede 9 posts · 2 referências
🗂️ Comandos de rede
📄 Comando SSH 📄 Comando rsync 📄 Comando wget 📄 Comandos rz · sz 📄 Comando curl
📄 Comando host 📄 Comando nslookup
📄 Comando ip 📄 Comandos netstat · ifconfig

ℹ️ Aviso de afiliados
O conteúdo deste site contém links de afiliados. Quando um visitante compra um produto ou serviço por meio de um desses links, o site recebe uma comissão do vendedor. O valor que o comprador paga (em promoções, ele diminui ↓) não aumenta por causa disso. Preços, descontos e informações de estoque valem para o momento em que o texto foi escrito e podem ter mudado, por isso confirme com o vendedor antes de comprar. Os produtos são escolhidos e avaliados por critérios próprios, e o recebimento de comissão não influencia a ordem de apresentação nem o conteúdo das avaliações.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Demonstre sua humanidade: 3   +   5   =