Como melhorar a privacidade do usuário e a experiência do desenvolvedor com as dicas de cliente HTTP do user agent

As dicas de cliente do user agent são uma nova expansão da API Client Hints. Com ela, os desenvolvedores podem acessar informações sobre o navegador do usuário de maneira ergonômica e que preserva a privacidade.

Com as dicas do cliente, os desenvolvedores podem solicitar ativamente informações sobre o dispositivo ou as condições do usuário, em vez de analisá-las fora da string do user agent (UA). Fornecer essa rota alternativa é a primeira etapa para reduzir a granularidade da string do user agent.

Saiba como atualizar as funcionalidades atuais que dependem da análise da string do user agent para usar as dicas do cliente do user agent.

Contexto

Quando os navegadores da Web fazem solicitações, eles incluem informações sobre o navegador e o ambiente dele para que os servidores possam ativar a análise e personalizar a resposta. Isso foi definido em 1996 (RFC 1945 para HTTP/1.0), em que você pode encontrar a definição original para a string do user agent, que inclui um exemplo:

User-Agent: CERN-LineMode/2.15 libwww/2.17b3

O objetivo desse cabeçalho era especificar, em ordem de importância, o produto (por exemplo, navegador ou biblioteca) e um comentário (por exemplo, versão).

O estado da string do user agent

Ao longo das décadas intervenientes, essa string acumulou vários detalhes adicionais sobre o cliente que fez a solicitação, bem como cruft devido à compatibilidade com versões anteriores. Observe que, ao analisar a string do user agent atual do Chrome:

Mozilla/5.0 (Linux; Android 10; Pixel 3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4076.0 Mobile Safari/537.36

A string acima contém informações sobre o sistema operacional e a versão do usuário, o modelo do dispositivo, a marca e a versão completa do navegador, pistas suficientes para inferir se é um navegador para dispositivos móveis e para não mencionar uma série de referências a outros navegadores por motivos históricos.

A combinação desses parâmetros com a grande diversidade de valores possíveis significa que a string do user agent pode conter informações suficientes para permitir que usuários individuais sejam identificados de maneira exclusiva. Se você testar seu próprio navegador no AmIUnique, poderá verificar o quanto sua string do user agent o identifica. Quanto menor for a "Proporção de similaridade" resultante, quanto mais exclusivas forem as solicitações, mais fácil será para os servidores rastrearem você secretamente.

A string do user agent permite muitos casos de uso legítimos e tem um propósito importante para desenvolvedores e proprietários de sites. No entanto, também é fundamental que a privacidade dos usuários seja protegida contra métodos de rastreamento ocultos, e o envio de informações do UA por padrão vai contra essa meta.

Também é necessário melhorar a compatibilidade com a Web quando se trata da string do user agent. Por não ser estruturado, sua análise resulta em complexidade desnecessária, o que geralmente é a causa de bugs e problemas de compatibilidade de sites que prejudicam os usuários. Esses problemas também prejudicam de maneira desproporcional os usuários de navegadores menos comuns, já que os sites podem ter falhado no teste da configuração.

Apresentação das novas dicas de cliente do user agent

As dicas de cliente do user agent permitem o acesso às mesmas informações, mas preservando a privacidade, permitindo que os navegadores reduzam o padrão da string do user agent de transmitir tudo. As Dicas de cliente aplicam um modelo em que o servidor precisa pedir ao navegador um conjunto de dados sobre o cliente (as dicas), e o navegador aplica as próprias políticas ou configurações do usuário para determinar quais dados são retornados. Isso significa que, em vez de expor todas as informações do user agent por padrão, o acesso agora é gerenciado de maneira explícita e auditável. Os desenvolvedores também se beneficiam de uma API mais simples, sem expressões regulares.

O conjunto atual de dicas do cliente descreve principalmente os recursos de exibição e conexão do navegador. Confira os detalhes em Como automatizar a seleção de recursos com dicas do cliente, mas aqui está uma revisão rápida do processo.

O servidor solicita dicas de cliente específicas por meio de um cabeçalho:

⬇️ Resposta do servidor

Accept-CH: Viewport-Width, Width

Ou uma metatag:

<meta http-equiv="Accept-CH" content="Viewport-Width, Width" />

O navegador pode então optar por enviar os seguintes cabeçalhos de volta nas solicitações subsequentes:

⬆️ Solicitação subsequente

Viewport-Width: 460
Width: 230

O servidor pode optar por variar as respostas, por exemplo, veiculando imagens em uma resolução adequada.

As dicas de cliente do user agent expandem o intervalo de propriedades com o prefixo Sec-CH-UA, que pode ser especificado pelo cabeçalho de resposta do servidor Accept-CH. Para conhecer todos os detalhes, comece com a explicação e, em seguida, aprofunde-se na proposta completa.

Dicas de cliente do user agent do Chromium 89

As dicas de cliente do user agent estão ativadas por padrão no Chrome desde a versão 89.

Por padrão, o navegador retorna a marca, a versão principal ou significativa, a plataforma e um indicador se o cliente é um dispositivo móvel:

⬆️ Todas as solicitações

Sec-CH-UA: "Chromium";v="93", "Google Chrome";v="93", " Not;A Brand";v="99"
Sec-CH-UA-Mobile: ?0
Sec-CH-UA-Platform: "macOS"

Cabeçalhos de solicitação e resposta do user agent

⬇️ Resposta Accept-CH
⬆️ Cabeçalho da solicitação
⬆️ Solicitação
Exemplo de valor
Descrição
Sec-CH-UA "Chromium";v="84",
"Google Chrome";v="84"
Lista de marcas de navegador e as versões relevantes delas.
Sec-CH-UA-Mobile ?1 Booleano que indica se o navegador está em um dispositivo móvel (?1 para "true") ou não (?0 para "false").
Sec-CH-UA-Full-Version "84.0.4143.2" [Descontinuada]A versão completa do navegador.
Sec-CH-UA-Full-Version-List "Chromium";v="84.0.4143.2",
"Google Chrome";v="84.0.4143.2"
Lista de marcas de navegador e a versão completa delas.
Sec-CH-UA-Platform "Android" A plataforma do dispositivo, geralmente o sistema operacional (SO).
Sec-CH-UA-Platform-Version "10" A versão da plataforma ou do SO.
Sec-CH-UA-Arch "arm" A arquitetura subjacente do dispositivo. Embora isso possa não ser relevante para a exibição da página, o site pode oferecer um download com o formato padrão.
Sec-CH-UA-Model "Pixel 3" O modelo do dispositivo.
Sec-CH-UA-Bitness "64" A quantidade de bits da arquitetura (ou seja, o tamanho em bits de um número inteiro ou endereço de memória)

Exemplo de troca

Veja um exemplo de troca:

⬆️ Solicitação inicial do navegador
O navegador está solicitando a página /downloads do site e envia o user agent básico padrão.

GET /downloads HTTP/1.1
Host: example.site

Sec-CH-UA: "Chromium";v="93", "Google Chrome";v="93", " Not;A Brand";v="99"
Sec-CH-UA-Mobile: ?1
Sec-CH-UA-Platform: "Android"

⬇️ Resposta do servidor
O servidor envia a página de volta e também solicita a versão completa do navegador e a plataforma.

HTTP/1.1 200 OK
Accept-CH: Sec-CH-UA-Full-Version-List

⬆️ Solicitações subsequentes
O navegador concede ao servidor acesso às informações adicionais e as envia de volta em todas as solicitações subsequentes.

GET /downloads/app1 HTTP/1.1
Host: example.site

Sec-CH-UA: " Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"
Sec-CH-UA-Mobile: ?1
Sec-CH-UA-Full-Version-List: " Not A;Brand";v="99.0.0.0", "Chromium";v="98.0.4738.0", "Google Chrome";v="98.0.4738.0"
Sec-CH-UA-Platform: "Android"

JavaScript API

Além dos cabeçalhos, o user agent também pode ser acessado em JavaScript via navigator.userAgentData. As informações de cabeçalho padrão Sec-CH-UA, Sec-CH-UA-Mobile e Sec-CH-UA-Platform podem ser acessadas pelas propriedades brands e mobile, respectivamente:

// Log the brand data
console.log(navigator.userAgentData.brands);

// output
[
  {
    brand: 'Chromium',
    version: '93',
  },
  {
    brand: 'Google Chrome',
    version: '93',
  },
  {
    brand: ' Not;A Brand',
    version: '99',
  },
];

// Log the mobile indicator
console.log(navigator.userAgentData.mobile);

// output
false;

// Log the platform value
console.log(navigator.userAgentData.platform);

// output
"macOS";

Os valores extras são acessados pela chamada getHighEntropyValues(). O termo de "alta entropia" é uma referência à entropia da informação, ou seja, a quantidade de informações que esses valores revelam sobre o navegador do usuário. Assim como na solicitação de cabeçalhos adicionais, cabe ao navegador quais valores, se houver, são retornados.

// Log the full user-agent data
navigator
  .userAgentData.getHighEntropyValues(
    ["architecture", "model", "bitness", "platformVersion",
     "fullVersionList"])
  .then(ua => { console.log(ua) });

// output
{
   "architecture":"x86",
   "bitness":"64",
   "brands":[
      {
         "brand":" Not A;Brand",
         "version":"99"
      },
      {
         "brand":"Chromium",
         "version":"98"
      },
      {
         "brand":"Google Chrome",
         "version":"98"
      }
   ],
   "fullVersionList":[
      {
         "brand":" Not A;Brand",
         "version":"99.0.0.0"
      },
      {
         "brand":"Chromium",
         "version":"98.0.4738.0"
      },
      {
         "brand":"Google Chrome",
         "version":"98.0.4738.0"
      }
   ],
   "mobile":false,
   "model":"",
   "platformVersion":"12.0.1"
}

Demonstração

Teste os cabeçalhos e a API JavaScript no seu próprio dispositivo em user-agent-client-hints.glitch.me.

Dicas sobre o ciclo de vida e a redefinição

As dicas especificadas pelo cabeçalho Accept-CH serão enviadas durante a sessão do navegador ou até que um conjunto diferente de dicas seja especificado.

Isso significa que, se o servidor enviar:

⬇️ Resposta

Accept-CH: Sec-CH-UA-Full-Version-List

Em seguida, o navegador vai enviar o cabeçalho Sec-CH-UA-Full-Version-List em todas as solicitações para esse site até que ele seja fechado.

⬆️ Solicitações subsequentes

Sec-CH-UA-Full-Version-List: " Not A;Brand";v="99.0.0.0", "Chromium";v="98.0.4738.0", "Google Chrome";v="98.0.4738.0"

No entanto, se outro cabeçalho Accept-CH for recebido, isso substituirá completamente as dicas atuais que o navegador está enviando.

⬇️ Resposta

Accept-CH: Sec-CH-UA-Bitness

⬆️ Solicitações subsequentes

Sec-CH-UA-Platform: "64"

A Sec-CH-UA-Full-Version-List solicitada anteriormente não será enviada.

É melhor pensar que o cabeçalho Accept-CH especifica o conjunto completo de dicas desejadas para essa página, o que significa que o navegador envia as dicas especificadas para todos os sub-recursos da página. Embora as dicas continuem na próxima navegação, o site não pode confiar nem presumir que elas serão exibidas.

Também é possível usar isso para limpar efetivamente todas as dicas enviadas pelo navegador, enviando um Accept-CH em branco na resposta. Considere adicioná-lo em qualquer lugar em que o usuário esteja redefinindo preferências ou saindo do site.

Esse padrão também corresponde à forma como as dicas funcionam com a tag <meta http-equiv="Accept-CH" …>. As dicas solicitadas só vão ser enviadas em solicitações iniciadas pela página, e não em qualquer navegação subsequente.

Escopo da dica e solicitações de origem cruzada

Por padrão, as dicas de cliente serão enviadas apenas em solicitações de mesma origem. Isso significa que, se você pedir dicas específicas sobre https://example.com, mas os recursos que quer otimizar estão em https://downloads.example.com, eles não vão receber dicas.

Para permitir dicas em solicitações de origem cruzada, cada dica e origem precisam ser especificadas por um cabeçalho Permissions-Policy. Para aplicar isso a uma dica de cliente do user agent, coloque a dica em letras minúsculas e remova o prefixo sec-. Exemplo:

⬇️ Resposta de example.com

Accept-CH: Sec-CH-UA-Platform-Version, DPR
Permissions-Policy: ch-ua-platform-version=(self "downloads.example.com"),
                    ch-dpr=(self "cdn.provider" "img.example.com");

⬆️ Solicitação para downloads.example.com

Sec-CH-UA-Platform-Version: "10"

⬆️ Solicitações para cdn.provider ou img.example.com

DPR: 2

Onde usar as dicas do cliente do user agent?

A resposta rápida é que você precisa refatorar todas as instâncias em que estiver analisando o cabeçalho do user agent ou fazendo uso de qualquer uma das chamadas JavaScript que acessem as mesmas informações (por exemplo, navigator.userAgent, navigator.appVersion ou navigator.platform) para usar as dicas do cliente do user agent.

Indo um pouco mais além, examine novamente o uso das informações do user agent e substitua-o por outros métodos sempre que possível. Muitas vezes, é possível atingir a mesma meta usando o aprimoramento progressivo, a detecção de recursos ou o design responsivo. O principal problema de confiar nos dados do user agent é que você sempre mantém um mapeamento entre a propriedade que está inspecionando e o comportamento que ela permite. É uma sobrecarga de manutenção para garantir que a detecção seja abrangente e permaneça atualizada.

Pensando nessas ressalvas, o repositório de dicas do cliente do user agent lista alguns casos de uso válidos para sites.

O que acontece com a string do user agent?

O plano é minimizar a capacidade de rastreamento oculto na Web reduzindo a quantidade de informações de identificação expostas pela string do user agent atual, sem causar interrupções indevidas nos sites atuais. Com as dicas de cliente do user agent, agora você pode entender e testar o novo recurso antes de fazer qualquer alteração nas strings do user agent.

Por fim, as informações na string do user agent serão reduzidas para manter o formato legado e fornecer apenas o mesmo navegador de alto nível e informações significativas de versão de acordo com as dicas padrão. No Chromium, essa mudança foi adiada pelo menos até 2022 para dar mais tempo ao ecossistema para avaliar os novos recursos das Dicas de cliente do user agent.

Você pode testar uma versão desse recurso ativando a sinalização about://flags/#reduce-user-agent no Chrome 93. Observação: essa sinalização era nomeada como about://flags/#freeze-user-agent nas versões do Chrome 84 a 92. Isso retornará uma string com as entradas históricas por motivos de compatibilidade, mas com especificidades limpas. Por exemplo, algo como:

Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Mobile Safari/537.36

Miniatura de Sergey Zolkin no Unsplash (link em inglês)