A nossa posição, em termos simples: somos a Geonode e vendemos proxies, e as perguntas sobre o user-agent surgem normalmente a par de «por que estou a ser bloqueado». A resposta sincera é que o agente de utilizador é um dos sinais mais fracos disponíveis, e uma string de navegador numa solicitação cuja impressão digital TLS indica o contrário é pior do que não ter qualquer disfarce — criou uma inconsistência que um navegador real nunca produz. Há uma secção sobre isso mais abaixo. A estratégia que funciona com mais frequência do que as pessoas esperam é precisamente a oposta: diga quem é, forneça um URL de contacto e comporte-se de forma razoável. A automação anónima é bloqueada com muito mais facilidade do que a automação identificada, e identificar-se não custa nada.
A sintaxe
curl -A "MyBot/1.0" https://example.com
O manual do curl descreve -A, --user-agent <name>
: «Especifique a cadeia de caracteres User-Agent a enviar ao servidor HTTP. Para codificar espaços na cadeia de caracteres, coloque-a entre aspas simples ou duplas.»
O valor predefinido também é indicado: «Por predefinição, o curl utiliza curl/VERSION
, tal como User-Agent: curl/8.22.0
.»
Assim, sem qualquer opção, cada pedido que efetuar identifica-se como curl e indica a sua versão. Alguns servidores respondem de forma diferente com base nisso, o que vale a pena saber antes de concluir que um site está avariado.
O equivalente utilizando um cabeçalho genérico:
curl -H "User-Agent: MyBot/1.0" https://example.com
Ambas produzem o mesmo resultado — o manual refere que o cabeçalho «também pode ser definido com as opções --header
ou --proxy-header
». -A
é mais curto; -H
é consistente com a forma como se define todos os outros cabeçalhos, o que é importante se estiver a gerar comandos programaticamente.
Se o definir várias vezes, «é utilizado o último valor definido».
Remover completamente o cabeçalho
Um caso que muitas pessoas desconhecem, e o manual é específico quanto a essa distinção:
Se passar um argumento vazio à função
--user-agent(""), esta remove o cabeçalho completamente da solicitação. Se preferir um cabeçalho em branco, pode defini-lo como um único espaço (" ").
curl -A "" https://example.com # no User-Agent header at all
curl -A " " https://example.com # User-Agent: (empty value)
Trata-se de pedidos genuinamente diferentes. Não enviar qualquer cabeçalho não é o mesmo que enviar um vazio, e os servidores conseguem distingui-los.
Ambos são invulgares, e o facto de serem invulgares é, por si só, um sinal. Um pedido sem qualquer agente de utilizador é mais raro do que um que se identifique como «curl», pelo que remover o cabeçalho para parecer menos suspeito geralmente acaba por ter o efeito oposto.
O mesmo mecanismo funciona através de -H, e o manual explica a sintaxe para ambos os casos: «Remova um cabeçalho interno fornecendo um substituto sem conteúdo à direita dos dois pontos, como em: -H "Host:"», enquanto um cabeçalho com um valor vazio necessita de um ponto e vírgula — -H "X-Custom-Header;" envia X-Custom-Header:.
Por que é que o valor predefinido é importante «
curl/8.22.0» é uma sequência de caracteres perfeitamente legítima, mas tem consequências.
Alguns servidores bloqueiam-na de imediato. É fácil criar uma regra geral contra ferramentas de automação conhecidas, e é tão comum que vais deparar-te com ela.
Alguns apresentam conteúdo diferente. Marcação simplificada, sem secções dependentes de JavaScript e, ocasionalmente, uma página totalmente diferente.
Alguns registam-no e não tomam nenhuma medida. De longe, o caso mais comum.
Algumas CDNs tratam-na como um sinal entre muitos, em vez de uma decisão por si só.
A consequência prática é que «funciona no meu navegador, mas não no curl» tem várias causas possíveis, e o agente de utilizador é apenas uma delas. Antes de o alterar, verifique se a diferença se deve realmente ao JavaScript — o curl não o executa, pelo que uma página montada do lado do cliente parecerá quase vazia para o curl, independentemente do cabeçalho que enviar. Isso não é um problema bloqueante e nenhum agente de utilizador o corrige.
O que enviar em vez disso
Para clientes automatizados, a sequência de caracteres que é menos bloqueada é aquela que indica o que é.
curl -A "AcmePriceBot/1.2 (+https://acme.example.com/bot)" https://example.com
A convenção tem três partes: um nome, uma versão e um URL onde é possível descobrir o que é e como contactá-lo. Funciona porque oferece ao operador do site outras opções além do bloqueio. Um padrão inexplicável de pedidos é um problema a ser resolvido; um rastreador identificado com uma página de contacto é uma decisão a tomar e, frequentemente, a decisão é permitir o acesso.
Três benefícios práticos, todos reais:
**robots.txt
permite que se dirijam a si especificamente.** As regras são comparadas com base no token do user-agent, pelo que um site pode conceder ao seu rastreador uma autorização que não concede a todos. Isso não pode acontecer se for anónimo.
Os operadores podem contactá-lo antes de o bloquear. Isto acontece com mais frequência do que as pessoas esperam, e é um resultado muito melhor do que descobrir um bloqueio três semanas mais tarde.
Permite solicitar acesso. «Somos o rastreador identificado como AcmePriceBot; eis o que fazemos» é uma conversa que pode levar a algum lado. «Somos um script não identificado» não o é.
Acompanhe isso com um comportamento que corresponda à afirmação: cumpra robots.txt
, respeite Crawl-delay
e Retry-After
, mantenha a sua taxa de acesso moderada e utilize a cache para nunca ir buscar duas vezes o mesmo recurso inalterado.
Definir de forma consistente nos scripts
Para qualquer coisa que envolva mais do que um comando, coloque a cadeia de caracteres num único local.
UA="AcmePriceBot/1.2 (+https://acme.example.com/bot)"
curl -sS --fail --location \
--user-agent "$UA" \
--connect-timeout 5 --max-time 30 \
"$URL"
Ou defina-a uma única vez num ficheiro de configuração do curl, o que mantém todas as chamadas consistentes sem repetir o sinalizador:
# bot.conf
--user-agent "AcmePriceBot/1.2 (+https://acme.example.com/bot)"
--location
--show-error
curl -K bot.conf "$URL"
Uma advertência específica sobre ~/.curlrc
: aplica-se a todas as chamadas do curl feitas por esse utilizador, incluindo comandos que não tenha escrito. Definir um agente de utilizador de bot nesse local significa que todos os pedidos ad hoc que alguma vez fizer serão identificados como sendo do seu rastreador, o que produz resultados confusos meses mais tarde. Utilize um ficheiro de configuração com nome em -K
para tudo o que seja específico da carga de trabalho.
Se precisar de vários agentes de utilizador numa carga de trabalho, mantenha-os num array e selecione-os deliberadamente, em vez de aleatoriamente — a rotação aleatória dentro de uma sessão faz com que o cliente pareça mudar de navegador a meio da visita, o que constitui mais uma inconsistência do que um disfarce.
Verificar o que realmente enviou
É um hábito que vale a pena adquirir, porque as suposições sobre os cabeçalhos estão erradas com uma frequência surpreendente.
curl -v -A "MyBot/1.0" https://example.com 2>&1 | grep -i '^> user-agent'
A saída detalhada é enviada para o stderr, daí o comando «2>&1». As linhas «>» correspondem ao que o curl transmitiu.
Ou peça a um serviço para o repetir:
curl -sS -A "MyBot/1.0" https://httpbin.org/user-agent
Isto é mais importante do que parece, devido a um comportamento específico descrito no manual: «se adicionar um cabeçalho personalizado com o mesmo nome que um dos cabeçalhos internos que o curl utilizaria, o seu cabeçalho definido externamente será utilizado em vez do interno». Assim, combinar -A com -H "User-Agent: ..." significa que um deles prevalece silenciosamente, e saber qual requer uma verificação. Vale a pena repetir o próprio conselho do manual: «Não deve substituir cabeçalhos definidos internamente sem saber exatamente o que está a fazer.»
A mesma verificação aplica-se através de um proxy, onde --proxy-header define cabeçalhos na ligação do proxy em vez de na solicitação de destino — uma distinção que confunde as pessoas quando um cabeçalho que definiram parece não chegar ao destino.
Ler uma cadeia de caracteres «User-Agent»
Vale a pena compreender isto, tanto porque poderá precisar de criar uma, como porque o formato explica por que razão as cadeias de caracteres dos navegadores parecem tão estranhas.
Uma cadeia de caracteres moderna do Chrome tem, aproximadamente, este aspeto:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36
Quase nada disso é verdade. Não é o Mozilla, não é o Safari e AppleWebKit/537.36 está inalterado há anos. A string é um registo fóssil de duas décadas de negociação de conteúdo: cada navegador adicionou os tokens dos seus antecessores para que os servidores que detetassem um concorrente lhe apresentassem a versão correta da página. O resultado é um formato que quase não contém informação fiável e que, mesmo assim, é analisado por uma grande quantidade de software.
A gramática estrutural subjacente é simples: uma sequência de tokens Product/Version, cada um opcionalmente seguido por um comentário entre parênteses. Essa é toda a especificação, e é por isso que uma string como AcmePriceBot/1.2 (+https://acme.example.com/bot) é bem-formada — um token de produto, uma versão e um comentário contendo um URL. O prefixo + no URL é uma convenção e não um requisito, e é amplamente reconhecido.
A questão dos dispositivos móveis. Muitos sites apresentam uma marcação diferente aos clientes móveis, e o token distintivo é normalmente Mobile algures na string. Se estiver a verificar legitimamente como uma página é apresentada aos visitantes móveis, enviar um agente de utilizador móvel é uma negociação de conteúdo comum, em vez de uma falsificação de identidade — embora se aplique a mesma ressalva de sempre: uma string móvel numa ligação de tipo computador de secretária com uma janela de visualização de computador de secretária é apenas uma afirmação parcial, e um navegador móvel verdadeiro diferiria em vários outros aspetos.
E a tendência de congelamento de versões. Os navegadores têm vindo a reduzir progressivamente os detalhes que expõem neste cabeçalho, transferindo as informações de capacidade para dicas estruturadas do cliente. A implicação prática é que a análise do agente de utilizador é uma fonte de informação cada vez menos relevante para todos — incluindo os sites que decidem o que fazer com os seus pedidos, o que constitui mais uma razão pela qual se trata de um sinal fraco em torno do qual construir uma estratégia.
Quando o User Agent não é o problema
Casos em que alterá-lo não vai ajudar, listados porque as pessoas tentam isso em primeiro lugar.
Quando o conteúdo é renderizado por JavaScript. O curl não executa scripts. Uma resposta quase vazia significa que a página é montada do lado do cliente, e a solução está no navegador ou na API subjacente, não num cabeçalho.
Quando existe uma limitação de taxa. Uma restrição de taxa (429) diz respeito ao volume, não à identidade. Abrandar o ritmo ajuda; um novo agente de utilizador não ajuda.
Quando o endereço é o problema. Se um intervalo inteiro estiver bloqueado, todos os pedidos provenientes desse intervalo falham, independentemente dos cabeçalhos.
Quando é necessária autenticação. Um 401 requer credenciais.
Quando a impressão digital TLS o denuncia. Já abordado acima, e é por isso que a simulação de um navegador apenas através dos cabeçalhos tende a ser decepcionante.
Quando o site simplesmente não quer tráfego automatizado. Alguns sites indicam isso nos seus termos e aplicam essa regra. Alterar um cabeçalho não altera os termos, e um site que te disse para não o rastreares deu-te uma informação, em vez de um enigma.
O diagnóstico que distingue rapidamente estas situações: solicite o mesmo URL a partir de um navegador normal na mesma ligação. Se o navegador funcionar e o curl não, compare as duas solicitações cabeçalho a cabeçalho — e se a única diferença relevante for algo que não pode alterar a partir da linha de comandos, essa é a sua resposta.
Perguntas frequentes
Como configuro um User-Agent no curl?
curl -A "MyBot/1.0" URL, ou, de forma equivalente, curl -H "User-Agent: MyBot/1.0" URL. Coloque a string entre aspas se esta contiver espaços. Se for especificada mais do que uma vez, prevalece o último valor.
Qual é o User-Agent predefinido do curl?
curl/VERSION — por exemplo, curl/8.22.0. É enviado em todos os pedidos, a menos que o substitua ou remova, e alguns servidores respondem de forma diferente com base nele.
Como removo o cabeçalho User-Agent no curl?
curl -A "" URL remove o cabeçalho por completo. curl -A " " URL envia-o com um valor vazio, o que constitui uma solicitação diferente. Note que não enviar nenhum User-Agent é mais invulgar do que enviar o valor predefinido do curl, pelo que chama mais atenção em vez de menos.
Devo falsificar um User-Agent de navegador com o curl?
Normalmente, não. Uma string de navegador numa solicitação cuja impressão digital TLS, conjunto de cabeçalhos e ordem sejam todos do curl constitui uma inconsistência que os navegadores reais nunca produzem, o que o torna mais identificável em vez de menos. Se precisar de solicitações com o formato de um navegador, utilize um navegador.
Alterar o User-Agent impedirá que eu seja bloqueado?
Raramente por si só. Ajuda contra regras genéricas que rejeitam ferramentas conhecidas, mas não tem qualquer efeito contra limites de taxa, bloqueios baseados em endereços, impressão digital TLS ou análise comportamental. Identificar-se honestamente com um URL de contacto funciona frequentemente melhor do que disfarçar-se.
Como deve ser o User-Agent de um bot?
Nome, versão e um URL de contacto: AcmePriceBot/1.2 (+https://acme.example.com/bot). Isto permite que robots.txt se dirija a si especificamente, permite que os operadores o contactem em vez de o bloquearem e dá-lhe legitimidade para solicitar acesso.
Posso definir um User-Agent diferente por pedido?
Sim — -A aplica-se à invocação, por isso forneça um valor diferente de cada vez, ou utilize --next para executar várias operações com opções diferentes num único comando. Evite alternar aleatoriamente dentro de uma sessão, o que faz com que o cliente pareça mudar de navegador a meio da visita.
Porque é que o meu User-Agent personalizado não aparece?
Provavelmente definiu-o duas vezes por meios diferentes, uma vez que o curl utiliza o cabeçalho definido externamente em vez do seu cabeçalho interno e a última definição prevalece. Verifique em curl -v ... 2>&1 | grep -i '^> user-agent' para ver o que foi efetivamente transmitido.
Conclusão
Definir um agente de utilizador no curl é uma opção, e a escolha do valor é mais importante do que a sintaxe.
O valor predefinido identifica o curl de forma honesta, e a honestidade é uma posição defensável: consistente, discreta e, por vezes, a razão pela qual um site o trata de forma razoável. É possível remover o cabeçalho — um argumento vazio elimina-o por completo, um único espaço envia-o em branco — e ambas as opções são mais invulgares do que o valor predefinido, o que é o oposto do que as pessoas normalmente pretendem.
Copiar uma string de navegador é o instinto comum e a opção mais fraca, porque a afirmação é verificável. As impressões digitais TLS, a composição e a ordem dos cabeçalhos, e o facto de se ir buscar ou não os subrecursos da página, contradizem-na, e uma contradição é mais identificável do que uma simples admissão. Se forem genuinamente necessárias solicitações com a forma de um navegador, um navegador é a ferramenta adequada.
A abordagem que funciona melhor do que a maioria das pessoas espera não custa nada: um nome, uma versão e um URL onde alguém possa descobrir quem é que tu és. Permite que robots.txt se dirija a si, permite que um operador lhe envie um e-mail em vez de o bloquear e transforma «tráfego inexplicável» em «um rastreador com um proprietário» — o que é uma posição muito melhor para se estar quando alguém está a decidir o que fazer em relação a si.
