Geonode logo
Geonode Team

Geonode Team

Atualizado: 7 de outubro de 2026

Publicado: 2 de setembro de 2026

curl para principiantes: um guia completo

O `curl` recupera um URL e apresenta o resultado. Tudo o resto são opções, e existem mais de duzentas. São necessárias cerca de oito para ser produtivo. Este guia aborda essas oito, o modelo mental que torna o resto compreensível e os erros mais comuns que todos cometem no início. No final, será capaz de enviar pedidos, ler respostas, depurar o que realmente foi transmitido e saber qual a página de manual a consultar a seguir.

Uma breve nota sobre quem está a escrever isto. Somos a Geonode e vendemos proxies, pelo que o curl é a ferramenta que mais frequentemente pedimos às pessoas para utilizarem quando é necessário diagnosticar algum problema. A verdade nua e crua para um principiante: o curl não é uma ferramenta de proxy e não precisas de um proxy para o aprenderes a utilizar. Tudo o que se segue funciona com endpoints públicos a partir da sua própria ligação, de forma gratuita. Os proxies só se tornam relevantes muito mais tarde, quando estiver a fazer pedidos suficientes para que um destino comece a limitar a sua taxa de acesso, ou quando precisar de ver como uma página aparece a partir de outro país. Nenhuma destas situações é um problema para um principiante. Aprenda primeiro a utilizar a ferramenta.

O que é o curl e para que serve

O curl é um programa de linha de comandos para a transferência de dados através de URLs. O seu próprio manual descreve-o como compatível com «DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS e WSS» — embora, na prática, quase toda a gente o utilize para HTTP e HTTPS.

Para que serve:

  • Chamar uma API a partir de um terminal ou de um script
  • Verificar se um URL funciona e o que devolve
  • Ver exatamente o que um servidor devolve, incluindo cabeçalhos e tudo o resto
  • Descarregar ficheiros
  • Depuração: reproduzir um pedido fora da sua aplicação para descobrir se o problema está no seu código ou no servidor

O que não é: um navegador. Não executa JavaScript, não renderiza nada e não mantém uma sessão, a menos que lhe seja solicitado. Uma página que pareça completa num navegador pode devolver um esqueleto quase vazio ao curl, o que é esperado e não significa que esteja com erros.

As tuas primeiras solicitações

curl https://example.com

Isto executa um GET e apresenta o corpo da resposta no teu terminal. Se o resultado for um texto extenso em HTML, significa que o curl está a funcionar.

Quatro variações úteis de imediato:

Ver os cabeçalhos, bem como o corpo com -i

, documentado em -i, --show-headers

: «Mostrar os cabeçalhos da resposta na saída.»

curl -i https://example.com

Guarde num ficheiro com -o

(o nome que escolher) ou -O

(o nome remoto):

curl -o page.html https://example.com
curl -O https://example.com/file.zip

Siga os redirecionamentos com -L

: «Siga os redirecionamentos HTTP e repita os pedidos com o método originalmente especificado.» Sem esta opção, o curl pára no primeiro redirecionamento e mostra-lhe a página de redirecionamento em vez do destino.

curl -L https://example.com

Não exibir mensagens, mas continuar a reportar erros com -sS

. -s

suprime a barra de progresso, -S

mantém as mensagens de erro. Juntas, são o que se pretende em qualquer script.

curl -sS https://example.com

Se tiver de se lembrar de uma única linha deste artigo, que seja esta:

curl -sSL https://example.com

Ler a resposta

Os principiantes costumam ficar a olhar para o corpo da resposta quando a resposta está nos cabeçalhos.

curl -i https://example.com
HTTP/2 200
content-type: text/html; charset=UTF-8
content-length: 1256

A primeira linha é o estado. 200

significa sucesso. 301

e 302

são redirecionamentos — acrescente -L

. 401

e 403

significam que não tem permissão. 404

significa que não existe. 429

significa que está a ir demasiado depressa. 500

e valores superiores significam que o servidor tem um problema.

content-type

indica o que recebeu efetivamente e esclarece muitas dúvidas. Se chamou uma API à espera de JSON e vê text/html

, recebeu uma página de erro ou um redirecionamento para o login, e o erro de análise que está prestes a encontrar é um sintoma e não a causa.

Para obter os cabeçalhos sem o corpo:

curl -sS -o /dev/null -D - https://example.com

Isto executa um GET normal, descarta o corpo e apresenta os cabeçalhos. É mais fiável do que -I

, que envia um pedido HEAD

e pode comportar-se de forma diferente — uma distinção abordada no nosso guia sobre pedidos HEAD do curl.

Para obter um resumo em vez dos cabeçalhos em bruto, -w

apresenta valores selecionados:

curl -sS -o /dev/null -w 'status=%{response_code} time=%{time_total}s\n' https://example.com

Mais informações sobre como ler corretamente os cabeçalhos em como mostrar cabeçalhos de resposta com o curl.

Envio de dados

A outra metade do trabalho.

Um POST com dados de formulário:

curl -d "name=Ada&role=engineer" https://api.example.com/users

A utilização de -d implica um POST e define Content-Type: application/x-www-form-urlencoded.

Um POST com JSON — e este é o erro mais comum entre os principiantes, porque -d, por si só, não define um tipo de conteúdo JSON:

curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d '{"name":"Ada","role":"engineer"}'

Se ignorar esse cabeçalho, muitas APIs devolvem 415 Unsupported Media Type, o que é um erro confuso até perceber que se refere ao seu Content-Type e não aos seus dados. Escrevemos sobre esse erro específico em o que é um código de estado 415.

Dados de um ficheiro, utilizando @ para significar «ler este ficheiro»:

curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d @payload.json

Um GET com parâmetros de consulta construído a partir de pares chave-valor, utilizando -G:

curl -G https://api.example.com/search -d "q=proxy" -d "limit=10"

Outros métodos com -X. Utilize-o apenas para métodos que não tenham uma opção dedicada — PUT, DELETE, PATCH. Tenha em atenção o aviso do manual de que -X «apenas altera a palavra utilizada na solicitação HTTP, não altera o comportamento do curl», razão pela qual -X HEAD não funciona e -I existe.

Cabeçalhos, autenticação e cookies

Cabeçalhos personalizados com -H

, repetível:

curl -H "Authorization: Bearer eyJhbG..." \
     -H "Accept: application/json" \
     https://api.example.com/me

Autenticação básica com -u

:

curl -u username:password https://api.example.com/private

Omita a palavra-passe e o curl irá solicitá-la, o que evita que fique registada no histórico do seu shell:

curl -u username https://api.example.com/private

Um agente de utilizador com -A

, uma vez que o curl se identifica como curl por predefinição e alguns servidores respondem de forma diferente:

curl -A "Mozilla/5.0 (compatible; MyBot/1.0; +https://example.com/bot)" https://example.com

Se estiver a escrever um cliente automatizado, um agente de utilizador honesto com um URL de contacto é tanto uma questão de boa educação como uma vantagem prática — a automação anónima é bloqueada com muito mais facilidade do que a automação identificada.

Cookies. O curl não os mantém entre chamadas, a menos que o solicite:

curl -c cookies.txt -d "user=ada&pass=secret" https://example.com/login
curl -b cookies.txt https://example.com/dashboard

-c

grava um cookie, -b

lê um. É assim que se lida com tudo o que requer uma sessão.

Ver o que foi realmente transmitido

O hábito que distingue quem depura rapidamente daqueles que se limitam a adivinhar.

curl -v https://example.com

O manual explica os prefixos: «>

» cabeçalho enviado pelo curl, «<

» cabeçalho recebido pelo curl, «}

» dados enviados pelo curl, «{

» dados recebidos pelo curl, «*

» informações adicionais fornecidas pelo curl.

Para ver apenas o que enviou:

curl -v https://example.com 2>&1 | grep '^>'

Isto esclarece toda uma categoria de confusão, porque o cabeçalho que definiu no código nem sempre é o cabeçalho que foi transmitido. As bibliotecas adicionam valores por predefinição, substituem valores e reordenam os elementos. Quando um servidor «ignora» o seu cabeçalho, verifique primeiro se o enviou realmente.

A saída detalhada é enviada para o stderr, razão pela qual é necessário utilizar «2>&1

» antes do piping — isto é deliberado, para que o corpo permaneça limpo no stdout.

Um aviso que o manual apresenta e que vale a pena repetir: a saída detalhada e de rastreio «pode conter dados sensíveis, incluindo nomes de utilizador, credenciais ou conteúdo de dados confidenciais». Ocultem esses dados antes de os colarem num ticket.

As opções que vale a pena memorizar

Tudo o que foi referido acima resume-se a um pequeno conjunto.

OpçãoFunção
-iMostrar os cabeçalhos da resposta juntamente com o corpo
-o file / -OGuardar num ficheiro com nome definido / no nome remoto
-LSeguir redirecionamentos
-sSSilencioso, mas continua a reportar erros
-HAdicionar um cabeçalho
-dEnviar dados (implica POST)
-uAutenticação básica
-vMostrar a troca completa
--failTratar erros HTTP como falhas
-m / --connect-timeoutLimites de tempo

Os dois últimos são aqueles que os principiantes ignoram e mais tarde se arrependem.

--fail é importante porque, por predefinição, o curl trata um 404 como uma transferência bem-sucedida — descarrega a página de erro e termina com o código de saída 0. Num script, isso significa que se guarda uma página de erro HTML com o nome installer.dmg e se continua. --fail faz com que os erros HTTP produzam um código de saída diferente de zero e nenhuma saída.

Os tempos de espera são importantes porque o curl não tem, por predefinição, um limite de tempo global. Uma solicitação bloqueada deixa o seu script pendente indefinidamente. --connect-timeout 5 -m 30 define esse limite. Há mais informações sobre isto em definir um tempo de espera com o curl.

A linha que vale a pena incluir em todos os scripts:

curl --fail --silent --show-error --location --connect-timeout 5 --max-time 30 "$URL"

Um exemplo prático do início ao fim

Juntar as peças numa tarefa realista: chamar uma API pública, verificar se funcionou e lidar com o caso de falha.

Primeiro passo — ver o que o endpoint devolve. Comece pelos cabeçalhos, não pelo corpo:

curl -sS -o /dev/null -D - https://api.github.com/repos/curl/curl

Recebe uma linha de estado e cabeçalhos. Se o estado for 200

e content-type

indicar JSON, está a comunicar com o destino certo.

Passo dois — analise o corpo, formatado. JSON bruto numa única linha é ilegível, por isso passe-o pelo jq

:

curl -sS https://api.github.com/repos/curl/curl | jq '{name, stargazers_count, language}'

Se o jq

não estiver instalado, o python3 -m json.tool

faz a formatação sem dependências adicionais.

Passo três — verifique o que enviou. Se algo não estiver a funcionar como esperado, analise o pedido em vez de adivinhar:

curl -v https://api.github.com/repos/curl/curl 2>&1 | grep '^>'

Passo quatro — torne-o seguro para um script. Adicione tratamento de erros e limites de tempo, e capture o estado separadamente do corpo:

#!/usr/bin/env bash
set -euo pipefail

URL="https://api.github.com/repos/curl/curl"
BODY=$(mktemp)

STATUS=$(curl --silent --show-error --location \
              --connect-timeout 5 --max-time 30 \
              --write-out '%{response_code}' --output "$BODY" \
              "$URL")

case "$STATUS" in
  200) jq -r '.stargazers_count' < "$BODY" ;;
  404) echo "not found" >&2; exit 1 ;;
  429) echo "rate limited, retry after: $(date)" >&2; exit 1 ;;
  *)   echo "unexpected status $STATUS" >&2; head -c 200 "$BODY" >&2; exit 1 ;;
esac

rm -f "$BODY"

Há três aspetos aqui que vale a pena incorporar em tudo o que escrever. --write-out '%{response_code}'

com --output

separa o estado do corpo, para que possa ramificar com base nisso. Imprimir os primeiros 200 caracteres do corpo num estado inesperado transforma um mistério num erro legível. E --connect-timeout

com --max-time

significa que o script termina mesmo quando a rede não o faz.

Passo cinco — respeite o limite de taxa. As APIs públicas publicam os seus limites nos cabeçalhos. Lê-los não custa nada e evita a forma mais comum de ser bloqueado:

curl -sS -o /dev/null -D - https://api.github.com/repos/curl/curl | grep -i ratelimit

Erros comuns de principiantes

Esquecer de definir -L. Recebe-se uma resposta curta com um aviso de redirecionamento e conclui-se que o URL está avariado. Não está.

Esquecer de definir --fail nos scripts. Um 404 transforma-se numa página de erro gravada e num código de saída igual a zero. É um erro silencioso, mas que mais tarde pode sair caro.

Utilizar -d com JSON sem definir Content-Type. Produz 415 ou um erro de análise confuso no servidor.

Aspas no shell. As aspas simples preservam tudo literalmente; as aspas duplas permitem que o shell expanda $ e as aspas invertidas. Para um corpo JSON que contenha aspas duplas, coloque-o entre aspas simples. Se os seus dados também contiverem aspas simples, coloque-os num ficheiro e utilize -d @file.json.

Partir do princípio de que o curl vê o que um navegador vê. O curl não executa JavaScript. Uma resposta quase vazia de uma página que parece cheia num navegador significa que o conteúdo é renderizado do lado do cliente, e o curl está a comportar-se corretamente.

Ignorar o código de estado. Um corpo que indique «erro» com o estado 200 e um corpo que indique «erro» com o estado 500 são problemas diferentes. Leia ambos.

Colocar credenciais na linha de comandos. Estas ficam registadas no histórico do shell e são visíveis na lista de processos para outros utilizadores na máquina. Utilize -u user e deixe que o curl solicite as credenciais, ou leia-as a partir de uma variável de ambiente.

Desativar a verificação de certificados para que algo funcione. -k silencia um aviso que lhe estava a dizer algo. Descubra primeiro o que é.

Próximos passos

Depois de se sentir à vontade com os conceitos básicos, os próximos passos naturais são:

Transferências corretas — retomar transferências interrompidas, transferências em paralelo, limitação de velocidade. Abordado em transferir um ficheiro com o curl.

Tempos limite e novas tentativas, que é onde os scripts deixam de ser frágeis. Consulte definir um tempo limite com o curl.

Ler cabeçalhos como dados, com %{header_json} a fornecer-lhe uma saída JSON em vez de texto para analisar.

curl versus wget, uma vez que se sobrepõem e são bons em aspetos diferentes — curl vs wget aborda quando utilizar cada um.

Proxies, quando eventualmente precisar deles: -x http://host:port encaminha um pedido através de um proxy. Realmente útil para verificações geográficas e para distribuir o volume; realmente desnecessário para aprendizagem ou para uma utilização modesta.

O manual. man curl é extenso e constitui a fonte de referência. Ler a entrada relativa a um sinalizador que já utiliza é uma forma fiável de descobrir a opção que realmente pretendia.

Perguntas frequentes

Para que serve o curl?

Para transferir dados através de URLs a partir de uma linha de comandos ou de um script — chamar APIs, verificar o que um servidor devolve, descarregar ficheiros e reproduzir um pedido fora de uma aplicação para isolar um problema. Suporta vários protocolos, mas é utilizado principalmente para HTTP e HTTPS.

Como faço uma solicitação GET com o curl?

curl https://example.com. O GET é o padrão, pelo que não é necessário qualquer sinalizador. Adicione -L para seguir redirecionamentos e -i para ver os cabeçalhos da resposta juntamente com o corpo.

Como é que envio JSON com o curl?

curl -X POST -H "Content-Type: application/json" -d '{"key":"value"}' URL. O cabeçalho é essencial — -d, por si só, envia um tipo de conteúdo codificado como formulário, e as APIs que esperam JSON irão normalmente rejeitá-lo com um erro 415.

Por que razão o curl não devolve nada?

Existem várias possibilidades: o corpo da resposta está realmente vazio, seguiu um redirecionamento que não tinha pretendido (adicione -L), o conteúdo é renderizado por JavaScript que o curl não executa, ou o pedido falhou e não viu o erro devido a -s sem -S. Execute com -i para ver o código de estado.

Qual é a diferença entre -o e -O no curl?

-o filename guarda com um nome à sua escolha. -O guarda com o nome de ficheiro da URL, descartando o caminho. Utilize -o quando a URL não tiver um nome de ficheiro útil ou quando precisar de um nome específico.

Como posso ver o pedido que o curl envia?

curl -v URL e procure as linhas que começam por >. A saída detalhada é enviada para o stderr, por isso adicione 2>&1 antes do redirecionamento. Esta é a forma mais rápida de confirmar que um cabeçalho que configurou foi efetivamente enviado.

O curl segue redirecionamentos por predefinição?

Não. Adicione -L. Esta é a razão mais comum pela qual o comando curl de um principiante devolve uma resposta curta e inesperada — está a ver o redirecionamento, não o destino.

Preciso de um proxy para utilizar o curl?

Não. O curl funciona bem com pontos finais públicos a partir da sua própria ligação. Os proxies só se tornam relevantes quando está a fazer pedidos suficientes para ser limitado em termos de taxa, ou quando precisa de ver o que um site disponibiliza noutro país. Nenhuma destas situações é motivo para comprar nada enquanto está a aprender.

Conclusão

O curl tem um número intimidante de opções e um núcleo útil muito reduzido. -i para ver os cabeçalhos, -L para seguir redirecionamentos, -o para guardar, -H para adicionar cabeçalhos, -d para enviar dados, -u para autenticação, -v para ver o que aconteceu e --fail mais um tempo limite para qualquer coisa que seja executada sem supervisão. Esse é todo o conjunto de funções necessárias para a maioria das pessoas.

Os dois hábitos que importam mais do que qualquer opção: ler o código de estado e o Content-Type antes de ler o corpo da mensagem, porque normalmente identificam o problema de forma direta; e usar -v para verificar o que realmente enviou em vez do que pretendia enviar, porque a diferença entre esses dois é onde reside uma percentagem surpreendente de erros.

Tudo o que vem a seguir está no manual, que é extenso, fidedigno e vale a pena consultar sempre que se vir a escrever uma solução alternativa. A opção que procura geralmente existe.