WebGLピクセルハッシュフィンガープリンティングは、GLSLシェーダーを使用して不可視の テストシーンをレンダリングし、gl.readPixels()で結果のピクセルを読み取ります — GPUの浮動小数点演算の微細な差異を悪用します。生成されたハッシュはすべてのブラウザで ハードウェアを識別し、クッキーのクリアを生き延び、VPNでは隠すことができません。 ご自身のWebGLピクセルハッシュを今すぐ whatsmy.fyiで確認できます。
要約(TL;DR)
GLSLシェーダープログラムが非表示のWebGLキャンバス内でGPU上にコンパイル・実行されます。 レンダリングされたピクセル値が読み取られ、コンパクトな識別子にハッシュ化されます。 GPUシェーダーユニットにおける浮動小数点の丸めはメーカー、アーキテクチャ、 ドライバーバージョンによって異なるため、同じシェーダーが異なるハードウェアでは 微妙に異なるピクセル出力を生成します — 同じGPUモデルでもドライバーのインストールが 異なる2台のマシンでも同様です。これにより、ピクセルハッシュはGPUレンダラー文字列を 単に読み取るよりも細かい識別子となります。GPUレンダラー文字列はハードウェアモデルのみを 示しますが、ピクセルハッシュはドライバーレベルの動作を捉えます。
WebGLピクセルハッシュフィンガープリンティングとは何か
WebGLピクセルハッシュフィンガープリンティングは、メタデータではなくGPUの計算出力を ターゲットとする、 WebGLフィンガープリンティングという広いファミリー内の特定の技術です。WEBGL_debug_renderer_infoを 介してGPUレンダラー文字列を読み取ることでトラッカーはGPUモデルを知ることができますが、 異なるドライバーバージョンを実行している2台の同一GPUを区別することはできません。 ピクセルハッシュはそのギャップを埋めます。
この技術が機能するのは、 WebGL APIがJavaScriptにGPUシェーダーの実行への直接アクセスを与えるためです。 フィンガープリンティングスクリプトは三角関数、小数部分、疑似ランダムノイズなどの 数学的演算を実行するGLSLフラグメントシェーダーを書き、GPUにそれを実行させます。 各ピクセルに書き込まれる色値は、GPUの浮動小数点ユニットがこれらの演算を内部で 処理する方法に依存します。異なるGPUアーキテクチャは丸めエラーを異なる方法で 蓄積し、同じGPU上でも異なるドライバーバージョンが測定可能に異なる出力を 生成することがあります。
これは キャンバスフィンガープリンティングと密接に関連しています — どちらもピクセル出力を読み取りますが、キャンバスフィンガー プリンティングは2Dフォントレンダリングとアンチエイリアスの差異をターゲットとしています。 WebGLピクセルハッシュはGPUの3Dシェーダー演算を直接ターゲットとしており、 より高いエントロピーで標準化がより困難です。
WebGLピクセルハッシュフィンガープリンティングの仕組み
プロセス全体がJavaScriptで実行され、50ミリ秒未満で完了し、ユーザーには完全に 不可視です。4つのステージで展開されます。
ステージ1 — 非表示WebGLキャンバスの作成
スクリプトはオフスクリーンのcanvas要素を作成し — ドキュメントには 追加されません — WebGLレンダリングコンテキストを取得します。キャンバスサイズは 通常小さく(256×128または512×256ピクセル)、実行を速く保ちます。 キャンバスは表示されません。
ステージ2 — バリエーションを最大化するように設計されたシェーダーのコンパイル
GLSLフラグメントシェーダーは浮動小数点精度の差異に敏感な演算を実行するように 書かれています。最も効果的なシェーダーはsin()、cos()、fract()、および大きな係数の乗算を組み合わせます — これらの演算が GPUアーキテクチャ間で異なる方法で丸めエラーを蓄積するためです。シェーダーは 各ピクセルの画面座標をこれらの数学関数を通じてマッピングして色値を生成します。
// ピクセルハッシュフィンガープリンティングに使用されるGLSLフラグメントシェーダー
precision highp float;
void main() {
float x = gl_FragCoord.x / 256.0;
float y = gl_FragCoord.y / 128.0;
// このsin/fractの組み合わせがGPUの浮動小数点差異を増幅する
float r = fract(sin(x * 12.9898 + y * 78.233) * 43758.5453);
float g = fract(sin(x * 93.989 + y * 17.211) * 43421.631);
float b = fract(cos(x * 51.234 + y * 31.456) * 12345.678);
gl_FragColor = vec4(r, g, b, 1.0);
}大きな定数乗数(43758.5453、43421.631、12345.678)は、中間結果の微小な 浮動小数点差異がfract()でラップされると目に見える色の違いに 増幅されることを意味します。中間演算で14桁の精度で一致する2つのGPUでも、 最終的なピクセル色が異なります。
ステージ3 — gl.readPixels()でのピクセル読み取り
シェーダーの実行後、スクリプトは gl.readPixels()を呼び出して、レンダリングされたピクセルデータをGPUメモリからJavaScriptのUint8Arrayに転送します。これにより、スクリプトはキャンバス内の すべてのピクセルのRGBA値に直接アクセスでき — GPUのシェーダー計算の生の 数値結果が得られます。
// JavaScript: シェーダーのコンパイル、レンダリング、ピクセルの抽出
const canvas = document.createElement('canvas');
canvas.width = 256;
canvas.height = 128;
const gl = canvas.getContext('webgl');
// 頂点シェーダーとフラグメントシェーダーのコンパイルとリンク(省略)
const program = compileAndLinkShaders(gl, vertexSrc, fragmentSrc);
gl.useProgram(program);
// フルスクリーントライアングルストリップの描画
const buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]),
gl.STATIC_DRAW
);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
// GPUメモリからピクセルデータを読み取る
const pixels = new Uint8Array(256 * 128 * 4); // 幅 × 高さ × RGBA
gl.readPixels(0, 0, 256, 128, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
// ピクセルバッファをハッシュ化 → 安定したGPUフィンガープリント
const hash = fnv1a(pixels); // または MurmurHash、xxHash などステージ4 — ピクセルバッファのハッシュ化
完全なピクセル配列 — 256×128キャンバスで131,072バイト — がコンパクトな値に ハッシュ化されます。一般的な選択肢はFNV-1a(高速、非暗号学的)、MurmurHash3、 またはサンプルピクセルバイトの単純な数値合計です。結果はGPUシェーダーユニットの 正確な浮動小数点動作を表す短い16進数文字列です。このハッシュはブラウザの再起動、 シークレットセッション、再起動をまたいで安定しています。変化するのはGPUドライバーが 更新されるか、物理ハードウェアが交換された場合のみです。
GPUレンダラー文字列の読み取りとどう違うのか
どちらもWebGLフィンガープリンティング技術ですが、ハードウェアスタックの異なるレベルで 動作し、一意性の異なる次元を捉えます。
| プロパティ | GPUレンダラー文字列 | WebGLピクセルハッシュ |
|---|---|---|
| 読み取る内容 | GPUモデル名 + ベンダー文字列 | シェーダー計算出力 |
| 使用するAPI | WEBGL_debug_renderer_info | gl.readPixels() |
| 同じGPU・異なるドライバーを区別できるか | 不可 — 同じGPUは常に同じ文字列を返す | 可能 — ドライバーの違いがピクセル出力を変える |
| privacy.resistFingerprintingでブロックされるか | はい — 汎用プレースホルダーを返す | 部分的 — 追加の標準化が必要 |
| 仮想マシンで動作するか | 不安定 — VMは多くの場合Mesa/SwiftShaderを返す | はい — ソフトウェアレンダラーも独自の出力を生成する |
| WebGL拡張機能が必要か | はい — WEBGL_debug_renderer_info | 不要 — コアWebGLを使用 |
ピクセルハッシュはより堅牢なシグナルとみなされています。なぜなら、ブラウザが単純に ブロックできるデバッグ拡張機能に依存しないためです。WebGLレンダリングが利用可能な 限り — ブラウザの95%以上で可能 — レンダラー文字列が汎用値を返す場合でも、 何らかの形のピクセルレベルのバリエーションが抽出できます。
WebGLピクセルハッシュの一意性
Fingerprint.comの研究とGPUベースのフィンガープリンティングに関する学術研究によると、 ピクセルハッシュは単独で約5〜7ビットのエントロピーに寄与します。これはあなたの ブラウザを約32〜128の類似した設定から区別することに相当します — 他のシグナルと 組み合わせる前でも意味のある絞り込みです。
| 調査結果 | 値 | 出典 |
|---|---|---|
| WebGLレンダリング出力単体のエントロピー | 約5.7ビット | Fingerprint.com research |
| ブラウザ再起動をまたいだピクセルハッシュの安定性 | ほぼ100%(ドライバー更新でのみ変化) | Cao et al., NDSS 2017 |
| 同じハードウェア上でのクロスブラウザ一貫性 | 高 — ハードウェア演算はブラウザに依存しない | Cao et al., NDSS 2017 |
| GPUレンダラー + ベンダーと組み合わせた識別精度 | 同じ組み合わせを持つ訪問者は0.01%未満 | Inria / KU Leuven フィールド研究 |
| WebGLブラウザサポート(Chrome、Edge、Safari、Firefox) | 95〜99% | BrowserLeaks WebGL Test |
GPUレンダラー文字列、ベンダー文字列、その他のハードウェアシグナルと組み合わせると、 WebGLフィンガープリントの組み合わせは訪問者を典型的なウェブサイトオーディエンスの 0.01%未満に絞り込むことができます — クロスサイトトラッキングにおいて、ほとんどの サードパーティクッキーが達成した精度を超えるレベルです。
ピクセルハッシュがブラウザをまたいで持続する理由
これがWebGLピクセルハッシュを、クッキーベースのシステムが根本的に対処できない クロスブラウザトラッキングに特に価値あるものにしている特徴です。同じマシンで Chrome、Firefox、Edgeを使用すると、各ブラウザは完全に独立したクッキージャーと ローカルストレージを持ちます。しかし、3つのブラウザはすべて同じ基盤となるGPUと ドライバーを共有します。GLSLシェーダーは各ブラウザで独立してコンパイルされますが、 同じハードウェアで実行されます — すべてのブラウザで同一(またはほぼ同一)の ピクセル出力を生成します。
Cao et al.によるNDSS 2017で発表された研究は、まさにこのアプローチを使用して クロスブラウザフィンガープリンティング能力を実証しました。GPUレンダリング出力が、 同じデバイス上の異なるブラウザのインストール間で、共有状態なしにブラウジング セッションをリンクするために使用されました。
WebGLピクセルハッシュフィンガープリンティングの利用者
商業デバイスインテリジェンスプラットフォーム
Fingerprint.com、Threatmetrix、iovationなどのプラットフォームは、他の多くのシグナルと共に WebGLレンダリングハッシュをデバイス識別子の計算に含めています。不正検出において、 ピクセルハッシュは安定したハードウェアのアンカーとして機能します — 詐欺師が クッキーをクリアし、IPアドレスを変更し、ブラウザを切り替えても、GPUレンダリング 出力がセッションを結びつけます。
アドテクトラッキング
SafariとFirefoxでサードパーティクッキーが廃止され、Chromeでも段階的に廃止されるにつれ、 広告ネットワークはクロスサイトのユーザー識別のためにハードウェアレベルの フィンガープリンティングへの依存を高めています。WebGLピクセルハッシュは ブラウザストレージも、ネットワークメタデータも必要としない — JavaScript内で 完全に自己完結しているため、特に魅力的です。
ヘッドレスブラウザとボット検出
サーバーインフラ上で動作する自動化ブラウザは通常、SwiftShader(ハードウェア アクセラレーションが無効または利用できないChrome headless)やMesa LLVMpipe (Linux)などのソフトウェアレンダラーを使用します。これらのソフトウェアレンダラーは、 実際のGPUハードウェアが生成するものとは明らかに異なるWebGLピクセルハッシュを 生成します — そして同じソフトウェアレンダラーバージョンを実行するすべての インスタンスでしばしば同じハッシュを生成します。セキュリティプラットフォームは この一貫性を利用してボットトラフィックをフラグします。
学術的対応:UNIGL
WebGLピクセルハッシュフィンガープリンティングに対する最も重要な学術的防御は UNIGLです。2019年のUSENIX Securityの論文「Rendered Private: Making GLSL Execution Uniform to Prevent WebGL-based Browser Fingerprinting」(Wu、Li、Cao、 Wang著)で提案されました。UNIGLはGLSLシェーダープログラムをGPUに到達する前に ブラウザ内で書き換えることで機能し、浮動小数点演算を基盤となるハードウェアに 関係なく均一な出力を生成する形式に変換します。
単純にWebGLをブロックする(Torブラウザ)かノイズを加える(Brave)アプローチとは 異なり、UNIGLはレンダリング出力を真に均一にすることを目指します — WebGL アプリケーションを壊すことなくトラッキングシグナルを排除します。研究者たちは、 UNIGLが典型的なウェブアプリケーションで3%未満のパフォーマンスオーバーヘッドで 異なるGPUハードウェア間でピクセルハッシュを同一にできることを実証しました。 しかし、UNIGLは2025年時点でいかなる主要ブラウザにも採用されておらず、 研究プロトタイプのままです。
WebGLピクセルハッシュフィンガープリンティングから身を守る方法
効果的な保護には、WebGLレンダリングアクセスのブロック、ピクセル出力へのノイズの 注入、または計算の標準化が必要です。最強から日常使用に最も実用的なものの順に 列挙します。
- Torブラウザ(最強の保護):Torブラウザはデフォルト設定で
gl.readPixels()を完全に無効化し、 スクリプトがレンダリングされたピクセルデータを読み取ることを不可能にします。 また、WebGLを最小限の機能モードに制限します。トレードオフはTorネットワークによる 遅いブラウジングと一部のWebGLアプリケーションの破損です。 - Braveブラウザ(日常使用に推奨): BraveのFarblingはWebGLピクセル出力に小さなランダム化されたセッションごとのノイズ値を注入します。 ノイズはセッション内で一貫している(WebGLアプリケーションが正しく動作する)が、 セッション間および異なるサイト間で変化します — ほとんどのWebGLコンテンツを 壊すことなく、ピクセルハッシュを信頼できないトラッキング識別子にします。
- Firefoxの
privacy.resistFingerprinting:about:configでこのフラグを有効にすると、FirefoxはWebGL出力を 標準化し、レンダリングハッシュの識別力を低下させます。保護はBraveのFarblingより 強力ではありませんが、ブラウザの切り替えは不要です。一部のWebGLアプリケーションは 予期しない動作をする可能性があります。 - Apple Silicon搭載のSafari(部分的な保護):Apple Mシリーズチップ上のSafariはキャンバス出力をランダム化し、一部のWebGL パラメーターを制限します。しかし、基盤となるApple GPUアーキテクチャはレンダリング 出力を通じてフィンガープリント検出可能です — 特に、測定可能に異なるシェーダー 結果を生成するM1、M2、M3世代の比較で。
- ブラウザ設定でのWebGL無効化:Firefoxでは
about:configでwebgl.disabledをtrueに設定するとWebGLレンダリングを完全に防ぎます。 これはピクセルハッシュシグナルを完全に排除しますが、WebGLベースのマップ (Googleマップ3D、Mapbox)、ブラウザゲーム、一部のビデオ会議インターフェースも 破損します。 - VPNができないこと:VPNはネットワークトラフィックを暗号化してあなたの見えるIPアドレスを変更しますが、 GPUシェーダーの実行には影響しません。ピクセルハッシュはブラウザ内で計算され、 ネットワークメタデータとしてではなくJavaScriptの値としてトラッキングサーバーに 送信されます。VPNのIPレベルの保護を whatsmy.fyiで確認してください。ただし、いかなる種類のフィンガープリンティングにも対処できない ことを理解しておいてください。
よくある質問
WebGLピクセルハッシュとWebGLレンダラー文字列の読み取りの違いは何ですか?
レンダラー文字列はテキストラベルです — たとえば「NVIDIA GeForce RTX 4080/PCIe/SSE2」 — WEBGL_debug_renderer_info拡張機能が返します。GPUモデルを 識別しますが、その正確なGPUを持つすべてのマシンで同じです。ピクセルハッシュは GPUの実際の計算の数値フィンガープリントです — テストシェーダーを実行して出力ピクセルを 読み取ることで生成されます。同一のGPUモデルを持つマシン間でも固有のドライバーレベルと シリコンレベルの違いを捉えます。
シークレットモードではピクセルハッシュは変わりますか?
いいえ。シークレットモードはブラウザがクッキー、履歴、ダウンロードをディスクに 保存するのを防ぎますが、GPUハードウェアやドライバーは変更しません。ピクセルハッシュは 完全にGPU計算から生成され、通常ウィンドウとプライベートウィンドウの両方で同一です。 アクティブなフィンガープリント保護(Brave、privacy.resistFingerprintingを 使用したFirefox、Torブラウザ)を持つブラウザのみが異なる出力を生成します。
2つの異なるGPUが同じピクセルハッシュを生成することはありますか?
はい、しかし統計的には稀です。異なるメーカー(NVIDIA対AMD対Intel対Apple)の GPUは、シェーダーアーキテクチャが浮動小数点演算を根本的に異なる方法で処理するため、 ほぼ同じハッシュを生成しません。同じ製品ファミリー内のGPU — たとえば同一ドライバーを 実行している2枚のRTX 3070カード — は一般的に同じハッシュを生成します。これが ピクセルハッシュがGPUレンダラー文字列や他のシグナルと組み合わせると最も強力になる 理由です。
ソフトウェアレンダラーもこの技術でフィンガープリンティングできますか?
はい。SwiftShader(ハードウェアアクセラレーションが無効または利用できない場合に Chromeが使用)やMesa LLVMpipeなどのソフトウェアレンダラーは独自のピクセルハッシュを 生成します。これらのソフトウェアレンダラーの異なるバージョンは異なるハッシュを 生成します。ハードウェアアクセラレーションを無効にしてChromeを実行しているマシンは、 セッション間で一定のSwiftShaderハッシュを生成します — そして実際のGPUハッシュとは 明らかに異なります。これがセキュリティプラットフォームがヘッドレスブラウザ環境を フラグするために使用する理由です。
GPUドライバーを更新するとピクセルハッシュは変わりますか?
変わる可能性があります。ドライバーの更新は時々シェーダー実行の浮動小数点動作を変更します — 特に古いGPU世代の三角関数で。特定のドライバー更新によってピクセルハッシュが変わるかは、 更新がフィンガープリンティングシェーダーで使用される演算のシェーダーコンパイラーまたは 浮動小数点ユニットの動作を変更するかどうかによります。実際には、主要なドライバー更新は 時々ハッシュを変更しますが、マイナーな安定性更新は通常変更しません。
WebGLピクセルハッシュフィンガープリンティングは広告ブロッカーでブロックされますか?
フィンガープリンティングスクリプトが広告ブロッカーのフィルターリストに含まれる サードパーティドメインからロードされた場合のみです。uBlock Originをミディアムまたは ハードモードで使用すると、商業トラッキングサービスのほとんどの既知のフィンガープリンティング スクリプトをブロックします。しかし、ファーストパーティスクリプト — ウェブサイトと 同じドメインからロードされたもの — はネットワークレベルの広告ブロッカーではブロックされません。 この技術自体(WebGLピクセル出力の読み取り)は標準的なブラウザ機能であり、 エクスプロイトではないため、ネットワークフィルタリングだけではブロックできません。
これは「Rendered Private」論文で説明されている技術と同じですか?
はい。Wu、Li、Cao、Wang著の2019年USENIX Securityの論文「Rendered Private: Making GLSL Execution Uniform to Prevent WebGL-based Browser Fingerprinting」は WebGLピクセルハッシュフィンガープリンティングを直接扱っています。提案された軽減策 UNIGLは、ブラウザレベルでGLSLシェーダーソースコードを書き直し、異なるハードウェアで レンダリング出力を均一にします。この論文は攻撃と潜在的な防御の両方について最も徹底的な 学術的扱いです。
関連記事
- WebGLフィンガープリンティングとは?GPUがブラウザを識別する方法 — GPUレンダラー文字列とベンダーがハードウェアモデルを公開する方法
- WebGLベンダーフィンガープリンティングとは? — GPUメーカー文字列がハードウェアファミリーを絞り込む方法
- キャンバスフィンガープリンティングとは?クッキーなしでウェブサイトがあなたを追跡する方法 — フォントレンダリングとOS差異を捉える2Dの兄弟技術
- オーディオフィンガープリンティングとは?AudioContextがブラウザを追跡する方法 — デバイスのオーディオスタックが一意の浮動小数点識別子を生成する方法
- ブラウザフィンガープリンティングとは?クッキーなしでサイトがあなたを追跡する方法 — すべてのフィンガープリンティングシグナルを組み合わせた完全ガイド


