← Voltar ao blog

A Migração para User-Agent Client Hints: Medindo Dispositivos Sem a String UA Completa

O Chrome está reduzindo a string User-Agent a uma casca congelada. Veja como uma analítica privacy-first lê sinais de dispositivo via Client Hints sem recorrer a fingerprinting.

A morte lenta da string User-Agent

Por décadas, o cabeçalho de requisição User-Agent foi o burro de carga da analítica para responder perguntas básicas: qual navegador, qual sistema operacional, mobile ou desktop? Ele também era um passivo em termos de fingerprinting. Uma string UA completa como Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/xxx.0.0.0 Safari/537.36 vaza números de versão precisos e detalhes de plataforma que, combinados com outros sinais, ajudam a identificar visitantes individuais.

O esforço de Redução do User-Agent do Google vem aparando essa string há anos. O Chrome agora envia uma UA reduzida, na qual a versão da plataforma fica congelada e os segmentos de versão menor são zerados. A intenção, segundo a documentação do Chrome, é remover entropia disponível passivamente preservando um substituto estruturado e opt-in: os User-Agent Client Hints (UA-CH).

Para quem constrói analítica em 2026, a consequência prática é clara. Fazer parsing da string UA legada para qualquer coisa além da família aproximada do navegador é cada vez menos confiável — e cada vez mais a abordagem errada.

Como os Client Hints realmente funcionam

O UA-CH divide as informações de dispositivo em hints discretos e requisitáveis, em vez de uma única string densa. Os hints de baixa entropia são enviados por padrão em toda requisição:

  • Sec-CH-UA — lista de marca e versão significativa
  • Sec-CH-UA-Mobile — um booleano ?0 / ?1
  • Sec-CH-UA-Platform — por exemplo, "macOS"

Hints de alta entropia — versão completa da plataforma, arquitetura, modelo, bitness — não são enviados a menos que o servidor peça explicitamente por eles. O servidor os solicita com um cabeçalho de resposta Accept-CH, e o navegador pode então incluí-los nas requisições seguintes. O prefixo Sec- significa que esses cabeçalhos são controlados pelo navegador e não podem ser definidos por scripts, o que é uma propriedade de integridade relevante.

Essa inversão importa para a privacidade. A postura padrão é a divulgação mínima. Entropia adicional passa a ser um ato deliberado, registrado nos seus próprios cabeçalhos de resposta, em vez de algo colhido silenciosamente de cada visitante.

A leitura privacy-first dessa mudança

O Monoid permanece deliberadamente do lado de baixa entropia dessa fronteira. Nunca enviamos Accept-CH para puxar arquitetura, modelo ou versão completa da plataforma, e nunca combinamos os hints que vemos em uma assinatura estável de dispositivo. Isso seria fingerprinting — reconstruir um identificador a partir de características do dispositivo —, exatamente o que a redução da UA foi projetada para impedir e o que o Artigo 5(3) da Diretiva ePrivacy e as políticas antifingerprinting dos navegadores tratam como acesso a informações do equipamento terminal.

Os hints padrão de baixa entropia bastam para as perguntas que a analítica deveria estar fazendo:

  • Família e versão maior do navegador a partir de Sec-CH-UA, para planejamento de compatibilidade e suporte.
  • Mobile vs não mobile a partir de Sec-CH-UA-Mobile, para segmentação de layout e Core Web Vitals.
  • Plataforma a partir de Sec-CH-UA-Platform, para recortes por sistema operacional.

Fundamental: essas são dimensões agregadas, não chaves por visitante. Um booleano e um nome de plataforma compartilhados por milhões de visitantes não carregam, por si sós, nenhum poder identificador significativo.

Lendo hints na edge

Como os Client Hints são cabeçalhos de requisição comuns, um worker de edge consegue lê-los sem nenhum script no cliente. Na Cloudflare, os hints de baixa entropia chegam no objeto Request da requisição:

export default {
  async fetch(request) {
    const brands = request.headers.get('Sec-CH-UA') || '';
    const isMobile = request.headers.get('Sec-CH-UA-Mobile') === '?1';
    const platform = request.headers.get('Sec-CH-UA-Platform') || '';
    // Derive apenas dimensões grosseiras; nunca persista uma chave composta.
    return new Response('ok');
  }
};

Note o que está ausente: nenhum eco de Accept-CH, nenhum pedido de hints de alta entropia, nenhum hash dos valores combinados. O valor de Sec-CH-UA é uma lista estruturada, então faça o parsing com cuidado — ele contém entradas de marca "GREASE" intencionais, feitas para quebrar parsing frágil por correspondência exata, uma técnica que a especificação toma emprestada do TLS.

O que mudar no seu pipeline

Se a sua analítica ainda faz regex na string UA completa, três coisas se quebram com o tempo. Os números de versão migram para .0.0.0, as versões de plataforma congelam e a detecção de mobile baseada em correspondência de substring fica pouco confiável. O caminho de migração é direto:

  1. Prefira os hints estruturados de baixa entropia ao parsing da string UA.
  2. Trate a string UA reduzida como fallback apenas para clientes antigos.
  3. Resista à tentação de pedir hints de alta entropia "por via das dúvidas" — cada hint adicional amplia sua superfície de fingerprinting e sua exposição em conformidade.

A lição mais ampla é coerente com tudo o que construímos. Os fornecedores de navegadores estão removendo de forma constante a entropia passiva da plataforma web. A resposta certa não é persegui-la por novas APIs, e sim projetar uma medição que nunca precisou dela.

Sources

Comments

Loading comments…