User-Agent Client Hints API によるユーザーのプライバシーとデベロッパー エクスペリエンスの向上

User-Agent Client Hints は、Client Hints API の新しい拡張機能です。これにより、デベロッパーはプライバシーを保護し、使いやすい方法でユーザーのブラウザに関する情報にアクセスできます。

Client Hints を使用すると、デベロッパーは User-Agent(UA)文字列から解析する必要なく、ユーザーのデバイスや状態に関する情報を能動的にリクエストできます。この代替ルートを提供する方法は、最終的にユーザー エージェント文字列の粒度を下げる最初のステップです。

User-Agent 文字列の解析に依存する既存の機能を更新して、代わりに User-Agent Client Hints を使用する方法を学びます。

背景

ウェブブラウザがリクエストを行うと、ブラウザとその環境に関する情報が含まれるため、サーバーは分析を有効にしてレスポンスをカスタマイズできます。これは 1996 年に定義されました(HTTP/1.0 の RFC 1945)。ここでは、User-Agent 文字列の元の定義(例を含む)を確認できます。

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

このヘッダーは、重要度の高い順に、プロダクト(ブラウザやライブラリなど)とコメント(バージョンなど)を指定することを目的としていました。

User-Agent 文字列の状態

その後の数十年の間に、この文字列にはリクエストを送信したクライアントに関するさまざまな詳細情報が追加され(下位互換性のために不要な情報も追加されました)、これは、Chrome の現在の User-Agent 文字列で確認できます。

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

上記の文字列には、ユーザーのオペレーティング システムとバージョン、デバイスのモデル、ブラウザのブランドと完全なバージョンに関する情報が含まれています。これは、モバイル ブラウザであることを推測するのに十分な手がかりです。また、歴史的な理由から、他のブラウザへの参照も多数含まれています。

これらのパラメータと、想定される値の多様性により、User-Agent 文字列には、個々のユーザーを一意に識別できる十分な情報が含まれる可能性があります。

User-Agent 文字列は、多くの正当なユースケースを可能にし、デベロッパーとサイト所有者にとって重要な役割を果たします。ただし、ユーザーのプライバシーを秘密のトラッキング方法から保護することも重要です。デフォルトで UA 情報を送信することは、その目標に反しています。

また、User-Agent 文字列に関しては、ウェブの互換性を改善する必要もあります。構造化されていないため、解析すると不要な複雑さが発生し、多くの場合、バグやサイトの互換性の問題が発生してユーザーに悪影響を及ぼします。また、サイトがその構成に対してテストに失敗している可能性があるため、これらの問題は、あまり一般的でないブラウザのユーザーに不釣り合いなほど大きな影響を与えます。

新しい User-Agent Client Hints のご紹介

User-Agent Client Hints を使用すると、同じ情報にアクセスできますが、プライバシーを保護する方法でアクセスできます。これにより、ブラウザは最終的に、すべてをブロードキャストする User-Agent 文字列のデフォルトを削減できます。クライアント ヒントは、サーバーがクライアントに関する一連のデータ(ヒント)をブラウザにリクエストし、ブラウザが独自のポリシーまたはユーザー設定を適用して返されるデータを決定するモデルを適用します。つまり、デフォルトで User-Agent 情報をすべて公開するのではなく、アクセスが明示的かつ監査可能な方法で管理されるようになりました。デベロッパーにとっても、正規表現が不要になるなど、API がシンプルになります。

現在のクライアント ヒントのセットは、主にブラウザのディスプレイと接続機能について説明しています。詳細については、クライアント ヒントによるリソース選択の自動化をご覧ください。ここでは、このプロセスについて簡単に説明します。

サーバーはヘッダーを介して特定の Client Hints をリクエストします。

⬇️ サーバーからのレスポンス

Accept-CH: Viewport-Width, Width

または、メタタグを使用します。

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

ブラウザは、後続のリクエストで次のヘッダーを返すことを選択できます。

⬆️ 後続のリクエスト

Viewport-Width: 460
Width: 230

サーバーは、適切な解像度で画像を提供するなど、レスポンスの変更を選択できます。

User-Agent Client Hints は、Accept-CH サーバー レスポンス ヘッダーで指定できる Sec-CH-UA 接頭辞を使用してプロパティの範囲を拡張します。詳細については、説明から始めて、提案書全体をご覧ください。

Chromium 89 の User-Agent Client Hints

User-Agent Client Hints は、Chrome バージョン 89 以降ではデフォルトで有効になっています。

デフォルトでは、ブラウザはブラウザのブランド、重要なバージョン / メジャー バージョン、プラットフォーム、クライアントがモバイル デバイスかどうかを示すインジケーターを返します。

⬆️ すべてのリクエスト

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"

User-Agent レスポンスとリクエストのヘッダー

⬇️ レスポンス Accept-CH
⬆️ リクエスト ヘッダー
⬆️ リクエスト
値の例
説明
Sec-CH-UA "Chromium";v="84",
"Google Chrome";v="84"
ブラウザ ブランドとその重要なバージョンのリスト。
Sec-CH-UA-Mobile ?1 ブラウザがモバイル デバイス上にあるかどうかを示すブール値(true の場合は ?1、false の場合は ?0)。
Sec-CH-UA-Full-Version "84.0.4143.2" [非推奨]ブラウザの完全なバージョン。
Sec-CH-UA-Full-Version-List "Chromium";v="84.0.4143.2",
"Google Chrome";v="84.0.4143.2"
ブラウザのブランドとその完全版のリスト。
Sec-CH-UA-Platform "Android" デバイスのプラットフォーム(通常はオペレーティング システム(OS))。
Sec-CH-UA-Platform-Version "10" プラットフォームまたは OS のバージョン。
Sec-CH-UA-Arch "arm" デバイスの基盤となるアーキテクチャ。これはページの表示には関係ありませんが、サイトでは、デフォルトで適切な形式のダウンロードを提供することもできます。
Sec-CH-UA-Model "Pixel 3" デバイスのモデル。
Sec-CH-UA-Bitness "64" 基盤となるアーキテクチャのビット数(整数またはメモリアドレスのビット数)

交換の例

やり取りの例は次のようになります。

⬆️ ブラウザからの最初のリクエスト
ブラウザがサイトから /downloads ページをリクエストし、デフォルトの基本的な User-Agent を送信します。

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"

⬇️ サーバーからのレスポンス
サーバーはページを返送し、ブラウザの完全なバージョンとプラットフォームをさらに要求します。

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

⬆️ 後続のリクエスト
ブラウザはサーバーに追加情報へのアクセス権を付与し、後続のすべてのリクエストで追加のヒントを送り返します。

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

ヘッダーに加えて、User-Agent には JavaScript で navigator.userAgentData を介してアクセスすることもできます。デフォルトの Sec-CH-UASec-CH-UA-MobileSec-CH-UA-Platform ヘッダー情報には、それぞれ brands プロパティと mobile プロパティからアクセスできます。

// 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";

追加の値には、getHighEntropyValues() 呼び出しを介してアクセスします。「高エントロピー」という用語は、情報エントロピー、つまり、これらの値がユーザーのブラウザについて明らかにする情報量を指しています。追加のヘッダーをリクエストする場合と同様に、返される値(存在する場合)はブラウザによって異なります。

// 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"
}

デモ

ヘッダーと JavaScript API の両方を、user-agent-client-hints.glitch.me でご利用のデバイスで試すことができます。

ヒントの有効期間とリセット

Accept-CH ヘッダーを介して指定されたヒントは、ブラウザのセッション中、または別のヒントセットが指定されるまで送信されます。

つまり、サーバーが次のように送信した場合:

⬇️ レスポンス

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

ブラウザが閉じられるまで、ブラウザはそのサイトのすべてのリクエストで Sec-CH-UA-Full-Version-List ヘッダーを送信します。

⬆️ 後続のリクエスト

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"

ただし、別の Accept-CH ヘッダーが受信されると、ブラウザが送信している現在のヒントが完全に置き換えられます

⬇️ レスポンス

Accept-CH: Sec-CH-UA-Bitness

⬆️ 後続のリクエスト

Sec-CH-UA-Platform: "64"

以前にリクエストした Sec-CH-UA-Full-Version-List送信されません

Accept-CH ヘッダーは、そのページに必要なヒントの完全なセットを指定すると考えるのがよいでしょう。つまり、ブラウザは、そのページ上のすべてのサブリソースに対して指定されたヒントを送信します。ヒントは次のナビゲーションまで保持されますが、サイトはヒントが配信されることを前提としたり、期待したりしないでください。

また、レスポンスで空の Accept-CH を送信することで、ブラウザから送信されるすべてのヒントを効果的に消去することもできます。ユーザーが設定をリセットしたり、サイトからログアウトしたりする場所に追加することを検討してください。

このパターンは、<meta http-equiv="Accept-CH" …> タグ経由でヒントが機能する仕組みとも一致します。リクエストされたヒントは、ページによって開始されたリクエストでのみ送信され、その後のナビゲーションでは送信されません。

ヒントのスコープとクロスオリジン リクエスト

デフォルトでは、クライアント ヒントは同じオリジンのリクエストでのみ送信されます。つまり、https://example.com に関する特定のヒントをリクエストしても、最適化したいリソースが https://downloads.example.com にある場合、ヒントは受信されません

クロスオリジン リクエストのヒントを許可するには、各ヒントとオリジンを Permissions-Policy ヘッダーで指定する必要があります。これを User-Agent Client Hint に適用するには、ヒントを小文字にして、sec- 接頭辞を削除する必要があります。次に例を示します。

⬇️ 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");

⬆️ downloads.example.com へのリクエスト

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

⬆️ cdn.provider または img.example.com へのリクエスト

DPR: 2

User-Agent Client Hints を使用する場所

簡単に言うと、User-Agent ヘッダーを解析しているインスタンスや、同じ情報にアクセスする JavaScript 呼び出し(navigator.userAgentnavigator.appVersionnavigator.platform など)を使用しているインスタンスは、すべてリファクタリングして、代わりに User-Agent Client Hints を使用するようにする必要があります。

さらに一歩進んで、User-Agent 情報の使用を再検討し、可能な限り他の方法に置き換える必要があります。多くの場合、プログレッシブ エンハンスメント、機能検出、レスポンシブ デザインを利用することで、同じ目標を達成できます。User-Agent データに依存する基本的な問題は、検査対象のプロパティと、そのプロパティが有効にする動作との間のマッピングを常に維持する必要があることです。検出が包括的で最新の状態を維持するために、メンテナンス オーバーヘッドが発生します。

これらの注意事項を念頭に置き、User-Agent Client Hints リポジトリにサイトの有効なユースケースがいくつか記載されています

User-Agent 文字列はどうなりますか?

既存のサイトに過度の混乱を招くことなく、既存の User-Agent 文字列で公開される識別情報の量を減らすことで、ウェブ上の秘密裏なトラッキングを最小限に抑えることが計画されています。User-Agent Client Hints の導入により、User-Agent 文字列に変更を加える前に、新しい機能を理解してテストできるようになりました。

最終的には、User-Agent 文字列の情報が削減され、従来の形式を維持しながら、デフォルトのヒントと同じ高レベルのブラウザと重要なバージョン情報のみが提供されるようになります。Chromium では、エコシステムが新しい User-Agent Client Hints 機能を評価するための時間を確保するため、この変更は 2022 年まで延期されています。

このバージョンは、Chrome 93 の about://flags/#reduce-user-agent フラグを有効にすることでテストできます(注: このフラグは、Chrome 84 ~ 92 のバージョンでは about://flags/#freeze-user-agent という名前でした)。互換性のため、履歴エントリを含む文字列が返されますが、詳細はサニタイズされます。たとえば、次のような内容です。

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

サムネイル: UnsplashSergey Zolkin