A nossa posição, tal como declaramos: somos a Geonode e vendemos proxies; por isso, o que é importante ter em conta ao descarregar ficheiros através de um proxy é que a largura de banda representa a totalidade do custo e os ficheiros são grandes. Encaminhar um download de 4 GB através de tráfego residencial com limite de dados a 0,79 $/GB custa aproximadamente 3,16 $ por um ficheiro, contra 0,56 $ com tráfego de centro de dados a 0,14 $/GB. Se o seu download não precisar de parecer que veio de uma ligação de consumidor — e a maioria dos downloads não precisa —, a largura de banda residencial é dinheiro deitado fora. Os preços são da nossa página de preços, verificados em setembro de 2026. Melhor ainda: se puder fazer o download diretamente, faça-o e não pague nada.
Dito isto, eis como fazê-lo corretamente.
As três formas de nomear o ficheiro de saída
Por predefinição, o curl escreve na saída padrão, razão pela qual um comando simples como ``curl https://example.com/file.zip`
` enche o terminal com dados binários. Existem três opções que alteram esse comportamento.
** ``-o filename`
** escreve num ficheiro com o nome que escolher:
curl -o archive.zip https://example.com/download?id=1234
`. Utilize esta opção sempre que souber como pretende que o ficheiro se chame e, em particular, quando o URL não contiver um nome de ficheiro útil.
**-O
** utiliza o nome remoto. O manual do curl descreve-o da seguinte forma: «Grava a saída num ficheiro com o nome do ficheiro remoto. Apenas a parte do nome do ficheiro remoto é utilizada; o caminho é omitido.»
curl -O https://example.com/files/report.pdf
# saves as report.pdf
Repare na ressalva nessa frase. O caminho é descartado, pelo que dois ficheiros com o mesmo nome base em diretórios diferentes sobrescrevem-se mutuamente. E se a URL terminar numa barra ou não tiver qualquer componente de nome de ficheiro, -O
falha.
**-J
** obtém o nome a partir do cabeçalho Content-Disposition
do servidor. Está documentado como indicando a -O
«para utilizar o nome de ficheiro Content-Disposition especificado pelo servidor, em vez de extrair um da URL». Útil para pontos finais de transferência em que a URL é um identificador opaco.
Contém também o aviso mais enfático do manual, e vale a pena reproduzi-lo:
AVISO: O nome de ficheiro Content-Disposition não é validado nem sanitizado. Pode conter sequências de traversal de caminho (..); não guarde a saída num local não fiável nem com esta opção ativa sem aviso prévio.
Por outras palavras, ``-OJ`
permite que um servidor remoto escolha um caminho no seu sistema de ficheiros. Se for uma fonte que controla, tudo bem. Num script que obtém dados de URLs arbitrárias, isso constitui uma vulnerabilidade. Se precisar de nomes fornecidos pelo servidor a partir de fontes não confiáveis, recupere os cabeçalhos, limpe o nome você mesmo e utilize ``-o
`.
Redirecionamentos: Por que é quase sempre necessário utilizar «-L»
Por predefinição, o curl não segue redirecionamentos. A opção -L está documentada como «Seguir redirecionamentos HTTP e repetir os pedidos com o método originalmente especificado».
Esta é a razão mais comum pela qual um download produz um ficheiro minúsculo contendo HTML, em vez do conteúdo pretendido. Os URLs de download redirecionam constantemente — para CDNs, para URLs assinados, para espelhos, para pontos finais regionais. Sem -L, o que se guarda é a página de redirecionamento.
curl -L -O https://example.com/latest.tar.gz
Dois pontos relacionados.
A ordem é importante com -o. Ao seguir redirecionamentos com vários URLs, o curl associa os argumentos -o aos URLs por ordem. Com um único URL, isto não constitui um problema, mas pode surpreender quem escreve comandos com vários URLs.
Limite os redirecionamentos. --max-redirs limita o número de redirecionamentos que o curl irá seguir. O valor predefinido é generoso e um ciclo de redirecionamentos sem limite não é um cenário de falha desejável numa tarefa cron.
A falha silenciosa: guardar páginas de erro como ficheiros
Esta é a parte mais importante deste artigo.
Por predefinição, o curl trata uma resposta de erro HTTP como uma transferência bem-sucedida. Um erro 404 tem um corpo; o curl descarrega o corpo; o curl termina com o código de saída 0. Agora tem um ficheiro chamado «installer.dmg
» que contém uma página HTML com a mensagem «Não encontrado», e o seu script prosseguiu como se tudo tivesse funcionado.
«--fail
» corrige isso. O manual: «Falhar com o código de erro 22 para respostas HTTP com códigos de estado 400 ou superiores, sem saída do corpo da resposta.»
curl --fail -L -O https://example.com/installer.dmg
Agora, um 404 produz o código de saída 22 e nenhum ficheiro. O seu script pode verificar isso.
Dois aperfeiçoamentos:
**--fail-with-body
** faz o mesmo, mas mantém o corpo da resposta, o que é útil quando as APIs devolvem mensagens de erro JSON úteis que pretende registar.
**--fail
não é perfeito.** Não deteta um servidor que devolva um 200 com uma página de erro, o que alguns fazem. Para qualquer coisa importante, verifique o resultado — verifique se o tamanho do ficheiro é plausível, verifique uma soma de verificação, se houver uma publicada, ou verifique os bytes mágicos:
curl --fail -L -o pkg.tar.gz "$URL" || exit 1
file pkg.tar.gz | grep -q gzip || { echo "not a gzip archive"; exit 1; }
A linha de download canónica, para scripts, é, portanto:
curl --fail --silent --show-error --location -o output.bin "$URL"
-sS
suprime a barra de progresso, mantendo as mensagens de erro, que é o que se pretende na automatização. Para utilização interativa, -#
apresenta-lhe a barra de progresso simples em vez da barra padrão.
Retomar transferências interrompidas
Os ficheiros de grande dimensão e as ligações instáveis tornam isto essencial. A opção `
`-C -`` está documentada da seguinte forma: «Retoma uma transferência anterior a partir do deslocamento de bytes indicado. Utilize '-C -' para instruir o curl a determinar automaticamente onde e como retomar a transferência.»
curl -C - -L -O https://example.com/large-file.iso
O curl verifica o tamanho do ficheiro local e solicita apenas o restante utilizando um cabeçalho Range. Em combinação com novas tentativas, isto torna os downloads longos mais suportáveis:
curl --fail -L -C - --retry 5 --retry-delay 5 -O https://example.com/large-file.iso
Três advertências.
O servidor tem de suportar pedidos de intervalo. Se não suportar, o curl não poderá retomar e irá reiniciar ou falhar. Verifique se existe Accept-Ranges: bytes nos cabeçalhos da resposta.
Retomar um ficheiro corrompido resulta num ficheiro corrompido ainda mais extenso. O -C - confia nos bytes locais. Se o ficheiro parcial tiver sido truncado a meio da gravação ou se a fonte tiver sido alterada, o resultado estará silenciosamente incorreto. Verifique com base numa soma de verificação, caso a fonte a publique.
Uma fonte alterada invalida a retoma. Se o ficheiro tiver sido substituído entre tentativas, obtém-se uma mistura de duas versões sem que seja apresentado qualquer erro.
Transferência de vários ficheiros em paralelo
Desde o curl 7.66, -Z
realiza «transferências em paralelo em vez de sequencialmente», sendo que --parallel-max
define o «número máximo de transferências a realizar em paralelo».
curl -Z --parallel-max 8 --fail -L \
-O https://example.com/a.zip \
-O https://example.com/b.zip \
-O https://example.com/c.zip
A partir de um ficheiro de URLs:
xargs -a urls.txt curl -Z --parallel-max 8 --fail -L --remote-name-all
--remote-name-all
aplica o comportamento -O
a cada URL, o que evita ter de repetir o sinalizador.
Escolha o paralelismo de forma deliberada. Mais não é melhor a partir de um certo ponto: os servidores limitam a taxa de transferência, a sua própria ligação fica saturada e, para além do patamar, gera erros em vez de débito. Oito é um valor inicial razoável para um servidor bem provisionado; num servidor pequeno, quatro ou menos é mais «educado» e, muitas vezes, mais rápido no geral. O comportamento aqui é a mesma curva de rendimento que descrevemos em concorrência vs. paralelismo — sobe, atinge um patamar e, em seguida, desce.
Diretórios, carimbos de data/hora e limites de taxa
Três opções que eliminam os scripts de envoltório que as pessoas costumam escrever.
**--output-dir
** — «Especifica o diretório onde os ficheiros devem ser guardados. Esta opção funciona com as opções --remote-name ou --output.» Já não é necessário usar cd
antes e depois.
**--create-dirs
** — com -o
, «o curl cria a hierarquia de diretórios locais necessária. Os diretórios criados utilizam o modo 0750 em sistemas Unix.» Repare no modo: 0750, não 0755. Se outro utilizador ou serviço precisar de ler esses diretórios, isto irá surpreendê-lo.
curl --fail -L --create-dirs -o data/2026/09/report.pdf https://example.com/report.pdf
**--remote-time
** — «define a data e a hora de modificação do ficheiro do sistema para corresponder ao carimbo de data/hora do ficheiro remoto». É verdadeiramente útil para espelhamento, uma vez que permite que ferramentas subsequentes avaliem a atualidade dos dados.
**--limit-rate
** — «Limita a velocidade de transferência à taxa especificada», aceitando os sufixos k
, M
e G
:
curl --limit-rate 2M -L -O https://example.com/large.iso
Vale a pena utilizá-lo mais do que as pessoas costumam fazer. Saturar a sua ligação de subida torna tudo o resto na rede inutilizável e, numa ligação partilhada ou com tráfego limitado, um limite de velocidade é uma simples questão de cortesia. Também reduz a probabilidade de um servidor o considerar um utilizador abusivo.
Reunindo as opções mais práticas:
curl --fail --location --continue-at - --retry 5 \
--remote-time --create-dirs \
--output downloads/archive.tar.gz \
"$URL"
Transferências através de um proxy
Adicione -x
e tudo o que foi referido acima continua a aplicar-se, com três aditamentos.
curl -x http://user:pass@proxy.example.com:9000 \
--fail -L -O https://example.com/file.zip
Os tempos de espera têm de ser repensados. --max-time
não é a ferramenta adequada para transferências de tamanho imprevisível, uma vez que uma transferência legítima de grande dimensão excederá qualquer limite fixo. Em vez disso, utilize o detetor de estagnação baseado na velocidade:
curl -x "$PROXY" --fail -L \
--connect-timeout 10 --speed-limit 1000 --speed-time 30 \
-O https://example.com/large.iso
Este interrompe o download se a taxa de transferência se mantiver abaixo de 1000 bytes por segundo durante 30 segundos, ao mesmo tempo que não interfere num download lento, mas que avança, com duração de várias horas. Abordámos o conjunto completo de opções de tempo limite em definir um tempo limite com o curl.
O comportamento de retoma interage com a rotação. Se o seu proxy alternar os endereços de saída por ligação, uma transferência retomada chega de um endereço diferente do original. Alguns servidores aceitam isto; outros servem um espelho diferente; outros rejeitam o pedido de intervalo. Para downloads longos, utilize uma sessão que mantenha o mesmo endereço de saída.
A largura de banda é cobrada duas vezes na sua cabeça, mas apenas uma vez na realidade. Paga por cada byte que atravessa o proxy. Combine isso com --retry
e uma falha a 90% de um ficheiro grande, e a conta torna-se rapidamente desagradável. Utilize sempre -C -
em downloads através de proxy, para que uma nova tentativa retome o processo em vez de o reiniciar.
Verificar o que realmente descarregou
Um código de saída igual a zero significa que a transferência foi concluída. Não significa que tenha recebido os bytes corretos e, para qualquer coisa que pretenda executar, instalar ou arquivar, vale a pena colmatar essa lacuna.
Verifique se o tamanho é plausível. É a verificação mais económica possível e deteta truncamentos, páginas de erro e respostas vazias:
SIZE=$(stat -c%s pkg.tar.gz 2>/dev/null || stat -f%z pkg.tar.gz)
[ "$SIZE" -gt 100000 ] || { echo "suspiciously small: $SIZE bytes"; exit 1; }
Verifique o tipo de ficheiro. Uma página de erro HTML guardada com a extensão .tar.gz
fica invisível para uma verificação de tamanho se a página for suficientemente grande, mas é detetável pelo file
:
file pkg.tar.gz | grep -q 'gzip compressed' || exit 1
Verifique uma soma de verificação publicada. Quando a fonte publica uma, esta é a única verificação que verifica o conteúdo em vez da forma:
curl --fail -sL -O https://example.com/pkg.tar.gz
curl --fail -sL -O https://example.com/pkg.tar.gz.sha256
sha256sum -c pkg.tar.gz.sha256 || exit 1
Tenha em atenção a limitação, pois é frequentemente mal interpretada: obter a soma de verificação do mesmo servidor através da mesma ligação protege-o contra corrupção e truncamento, mas não contra uma fonte comprometida. Se o servidor estiver a servir um ficheiro corrompido, fornecerá uma soma de verificação incorreta correspondente. A verificação de assinatura com o GPG é o que resolve essa situação, e vale a pena dar esse passo adicional para qualquer coisa que seja executada com privilégios.
**Compare com Content-Length
, quando disponível.** O curl termina com um valor diferente de zero e o erro 18 quando uma transferência termina antes do comprimento anunciado, o que deteta automaticamente uma classe de truncamento — mas apenas quando o servidor anunciou um comprimento, o que não acontece com respostas fragmentadas.
Para downloads através de proxy, verifique mais em vez de menos. Um salto adicional representa mais um ponto onde uma transferência pode ser interrompida ou, no caso de um intermediário de filtragem, alterada. As verificações acima demoram milésimos de segundo e eliminam toda uma categoria de relatórios de erros confusos.
Quando o curl não é a ferramenta adequada
O curl é excelente para recuperar uma URL. Para várias tarefas relacionadas, existem ferramentas mais adequadas.
Transferências recursivas e espelhamento. O curl recupera os URLs que indicar. Não faz rastreamento. Para espelhar um diretório ou um site, o wget -r ou uma ferramenta dedicada ao espelhamento é a escolha certa — uma comparação que abordámos em curl vs wget.
Ficheiros muito grandes através de ligações pouco fiáveis. Os gestores de transferências concebidos especificamente para o efeito lidam melhor com transferências segmentadas e retomadas agressivas do que o curl. O curl com -C - e tentativas de repetição é adequado; as ferramentas especializadas são melhores.
Torrents, rsync, S3 e similares. Protocolos diferentes com os seus próprios clientes que gerem integridade, deduplicação e permissões de forma nativa. O comando aws s3 cp não é apenas o curl com passos adicionais.
Quando existe um gestor de pacotes. O comando curl | sh para a instalação de software é conveniente, mas concede a um servidor remoto a execução arbitrária na sua máquina sem qualquer verificação. Utilize o gestor de pacotes, caso exista.
Transferências repetidas do mesmo recurso. Se descarregar um ficheiro periodicamente para verificar se há alterações, os pedidos condicionais com -z ou If-None-Match evitam a transferência repetida de conteúdo inalterado. Um cache é melhor do que uma transferência rápida.
Perguntas frequentes
Como faço para descarregar um ficheiro com o curl?
curl -O https://example.com/file.zip guarda-o com o nome remoto, e -o name permite-lhe escolher o nome. Na prática, adicione --fail e -L: sem elas, o curl não seguirá redirecionamentos e guardará as páginas de erro como se fossem o ficheiro que solicitou.
Por que razão o curl descarrega um ficheiro vazio ou HTML?
Quase sempre se trata de um redirecionamento que não seguiu — adicione -L — ou de um erro HTTP guardado como ficheiro, o que --fail evita. Verifique o que obteve com file downloaded.zip ou abrindo-o num editor de texto; uma página de erro HTML é imediatamente reconhecível.
Como posso retomar um download interrompido com o curl?
curl -C - -O <url>. O curl verifica o tamanho do ficheiro local e solicita o restante através de um pedido de intervalo. O servidor tem de suportar intervalos — procure Accept-Ranges: bytes — e tenha em atenção que retomar um ficheiro parcial corrompido produz um ficheiro corrompido mais longo, sem qualquer aviso.
Como faço para descarregar vários ficheiros com o curl?
Utilize -Z para transferências paralelas com --parallel-max para limitar a simultaneidade, e --remote-name-all para que cada URL tenha o comportamento de «remote-name». Para uma lista num ficheiro, encaminhe-a através de xargs. Mantenha o paralelismo moderado — a taxa de transferência estabiliza e depois cai à medida que os servidores começam a limitar a taxa de transferência.
Como limito a velocidade de download no curl?
--limit-rate 2M limita a transferência a 2 megabytes por segundo, e a opção aceita os sufixos k, M e G. Vale a pena utilizar em ligações partilhadas e com servidores pequenos, tanto para manter o resto da sua rede utilizável como para evitar ser considerado um utilizador abusivo.
Qual é a diferença entre -O e -o no curl?
-O utiliza o nome do ficheiro da URL, descartando o caminho. -o grava num nome que especificar. Utilize -o quando a URL não tiver um nome de ficheiro utilizável, quando precisar de um nome específico ou quando quiser evitar colisões entre ficheiros com o mesmo nome provenientes de caminhos diferentes.
O curl -OJ é seguro?
Não com fontes não confiáveis. O manual avisa explicitamente que o nome de ficheiro Content-Disposition «não é validado nem sanitizado» e «pode conter sequências de traversal de caminho». Isso significa que um servidor remoto escolhe onde o ficheiro é guardado. Obtenha o cabeçalho, sanitize o nome você mesmo e utilize -o.
Como posso verificar se um download com o curl foi bem-sucedido?
Utilize --fail para que os erros HTTP produzam o código de saída 22 em vez de uma página de erro guardada e, em seguida, verifique o código de saída. Para qualquer coisa importante, verifique mais detalhadamente: verifique se o tamanho do ficheiro é plausível, execute file para confirmar o tipo e compare uma soma de verificação, caso a fonte a publique.
Conclusão
O código simples curl -O que se encontra na maioria dos exemplos funciona bem até deixar de funcionar, e o seu modo de falha é do pior tipo — um código de saída igual a zero e um ficheiro que contém algo diferente do que se pediu.
Duas opções resolvem isso. -L segue os redirecionamentos que praticamente todos os URLs de download reais utilizam, e --fail impede que o curl guarde respostas de erro HTTP como se fossem conteúdo. Adicione -C - para ficheiros de grande dimensão, uma vez que um download retomável é a diferença entre um problema de rede passageiro e ter de recomeçar do zero.
Para scripts, curl --fail --silent --show-error --location é a linha que vale a pena memorizar, juntamente com --continue-at - e --retry quando os ficheiros são grandes. E sejam quais forem as opções, verifique o resultado em vez de confiar apenas no código de saída — verifique o tamanho, verifique o tipo, verifique a soma de verificação, caso exista. Os downloads falham silenciosamente com mais frequência do que falham de forma evidente.