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.
As opções que vale a pena memorizar
Tudo o que foi referido acima resume-se a um pequeno conjunto.
| Opção | Função |
|---|---|
-i | Mostrar os cabeçalhos da resposta juntamente com o corpo |
-o file / -O | Guardar num ficheiro com nome definido / no nome remoto |
-L | Seguir redirecionamentos |
-sS | Silencioso, mas continua a reportar erros |
-H | Adicionar um cabeçalho |
-d | Enviar dados (implica POST) |
-u | Autenticação básica |
-v | Mostrar a troca completa |
--fail | Tratar erros HTTP como falhas |
-m / --connect-timeout | Limites 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.
