get-browser-fingerprint 3.1.0 → 3.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/package.json +10 -8
- package/src/index.js +29 -41
package/README.md
CHANGED
|
@@ -13,7 +13,8 @@ console.log(fingerprint);
|
|
|
13
13
|
|
|
14
14
|
Options available:
|
|
15
15
|
- `hardwareOnly` (default `false`): leverage only hardware info about device
|
|
16
|
-
- `enableWebgl` (default `false`): enable webgl renderer, ~4x times slower but adds another deadly powerful hardware detection layer on top of canvas
|
|
16
|
+
- `enableWebgl` (default `false`): enable webgl renderer, ~4x times slower but adds another deadly powerful hardware detection layer on top of canvas
|
|
17
|
+
- `enableScreen` (default `true`): enable screen resolution detection, disable it if your userbase may use multiple screens
|
|
17
18
|
- `debug`: log data used to generate fingerprint to console and add canvas/webgl canvas to body to see rendered image (default `false`)
|
|
18
19
|
|
|
19
20
|
⚠️ Be careful: the strongest discriminating factor is canvas token which can't be computed on old devices (eg: iPhone 6), deal accordingly ⚠️
|
|
@@ -29,5 +30,5 @@ yarn test
|
|
|
29
30
|
|
|
30
31
|
To run example locally:
|
|
31
32
|
```sh
|
|
32
|
-
|
|
33
|
-
```
|
|
33
|
+
pnpm serve -p 80 ./src
|
|
34
|
+
```
|
package/package.json
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "get-browser-fingerprint",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.2",
|
|
4
4
|
"author": "Damiano Barbati <damiano.barbati@gmail.com> (https://github.com/damianobarbati)",
|
|
5
5
|
"repository": "https://github.com/damianobarbati/get-browser-fingerprint",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "src/index.js",
|
|
8
|
+
"type": "module",
|
|
8
9
|
"files": [
|
|
9
10
|
"README.md",
|
|
10
11
|
"package.json",
|
|
11
|
-
"src/index.js"
|
|
12
|
+
"src/index.js",
|
|
13
|
+
"src/index.d.js"
|
|
12
14
|
],
|
|
13
|
-
"
|
|
15
|
+
"types": "./src/index.d.ts",
|
|
14
16
|
"scripts": {
|
|
15
|
-
"
|
|
17
|
+
"lint": "biome check --write",
|
|
16
18
|
"test": "vitest run"
|
|
17
19
|
},
|
|
18
20
|
"devDependencies": {
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"vitest": "^0.
|
|
21
|
+
"@biomejs/biome": "^1.8.3",
|
|
22
|
+
"@playwright/test": "^1.47.0",
|
|
23
|
+
"serve": "^14.2.3",
|
|
24
|
+
"vitest": "^2.0.5"
|
|
23
25
|
}
|
|
24
26
|
}
|
package/src/index.js
CHANGED
|
@@ -1,21 +1,10 @@
|
|
|
1
|
-
const getBrowserFingerprint = ({ hardwareOnly = false, enableWebgl = false, debug = false } = {}) => {
|
|
2
|
-
const {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
doNotTrack,
|
|
6
|
-
hardwareConcurrency,
|
|
7
|
-
language,
|
|
8
|
-
languages,
|
|
9
|
-
maxTouchPoints,
|
|
10
|
-
platform,
|
|
11
|
-
userAgent,
|
|
12
|
-
vendor,
|
|
13
|
-
} = window.navigator;
|
|
14
|
-
|
|
15
|
-
const { width, height, colorDepth, pixelDepth } = window.screen;
|
|
1
|
+
const getBrowserFingerprint = ({ hardwareOnly = false, enableWebgl = false, enableScreen = true, debug = false } = {}) => {
|
|
2
|
+
const { cookieEnabled, deviceMemory, doNotTrack, hardwareConcurrency, language, languages, maxTouchPoints, platform, userAgent, vendor } = window.navigator;
|
|
3
|
+
|
|
4
|
+
const { width, height, colorDepth, pixelDepth } = enableScreen ? window.screen : {}; // undefined will remove this from the stringify down here
|
|
16
5
|
const timezoneOffset = new Date().getTimezoneOffset();
|
|
17
6
|
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
18
|
-
const touchSupport =
|
|
7
|
+
const touchSupport = "ontouchstart" in window;
|
|
19
8
|
const devicePixelRatio = window.devicePixelRatio;
|
|
20
9
|
|
|
21
10
|
const canvas = getCanvasID(debug);
|
|
@@ -64,7 +53,7 @@ const getBrowserFingerprint = ({ hardwareOnly = false, enableWebgl = false, debu
|
|
|
64
53
|
|
|
65
54
|
const datastring = JSON.stringify(data, null, 4);
|
|
66
55
|
|
|
67
|
-
if (debug) console.log(
|
|
56
|
+
if (debug) console.log("fingerprint data", datastring);
|
|
68
57
|
|
|
69
58
|
const result = murmurhash3_32_gc(datastring);
|
|
70
59
|
return result;
|
|
@@ -72,17 +61,17 @@ const getBrowserFingerprint = ({ hardwareOnly = false, enableWebgl = false, debu
|
|
|
72
61
|
|
|
73
62
|
export const getCanvasID = (debug) => {
|
|
74
63
|
try {
|
|
75
|
-
const canvas = document.createElement(
|
|
76
|
-
const ctx = canvas.getContext(
|
|
64
|
+
const canvas = document.createElement("canvas");
|
|
65
|
+
const ctx = canvas.getContext("2d");
|
|
77
66
|
const text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`~1!2@3#4$5%6^7&8*9(0)-_=+[{]}|;:',<.>/?";
|
|
78
|
-
ctx.textBaseline =
|
|
67
|
+
ctx.textBaseline = "top";
|
|
79
68
|
ctx.font = "14px 'Arial'";
|
|
80
|
-
ctx.textBaseline =
|
|
81
|
-
ctx.fillStyle =
|
|
69
|
+
ctx.textBaseline = "alphabetic";
|
|
70
|
+
ctx.fillStyle = "#f60";
|
|
82
71
|
ctx.fillRect(125, 1, 62, 20);
|
|
83
|
-
ctx.fillStyle =
|
|
72
|
+
ctx.fillStyle = "#069";
|
|
84
73
|
ctx.fillText(text, 2, 15);
|
|
85
|
-
ctx.fillStyle =
|
|
74
|
+
ctx.fillStyle = "rgba(102, 204, 0, 0.7)";
|
|
86
75
|
ctx.fillText(text, 4, 17);
|
|
87
76
|
|
|
88
77
|
const result = canvas.toDataURL();
|
|
@@ -101,22 +90,23 @@ export const getCanvasID = (debug) => {
|
|
|
101
90
|
|
|
102
91
|
export const getWebglID = (debug) => {
|
|
103
92
|
try {
|
|
104
|
-
const canvas = document.createElement(
|
|
105
|
-
const ctx = canvas.getContext(
|
|
93
|
+
const canvas = document.createElement("canvas");
|
|
94
|
+
const ctx = canvas.getContext("webgl");
|
|
106
95
|
canvas.width = 256;
|
|
107
96
|
canvas.height = 128;
|
|
108
97
|
|
|
109
98
|
const f =
|
|
110
|
-
|
|
111
|
-
const g =
|
|
112
|
-
'precision mediump float;varying vec2 varyinTexCoordinate;void main() {gl_FragColor=vec4(varyinTexCoordinate,0,1);}';
|
|
99
|
+
"attribute vec2 attrVertex;varying vec2 varyinTexCoordinate;uniform vec2 uniformOffset;void main(){varyinTexCoordinate=attrVertex+uniformOffset;gl_Position=vec4(attrVertex,0,1);}";
|
|
100
|
+
const g = "precision mediump float;varying vec2 varyinTexCoordinate;void main() {gl_FragColor=vec4(varyinTexCoordinate,0,1);}";
|
|
113
101
|
const h = ctx.createBuffer();
|
|
114
102
|
|
|
115
103
|
ctx.bindBuffer(ctx.ARRAY_BUFFER, h);
|
|
116
104
|
|
|
117
105
|
const i = new Float32Array([-0.2, -0.9, 0, 0.4, -0.26, 0, 0, 0.7321, 0]);
|
|
118
106
|
|
|
119
|
-
ctx.bufferData(ctx.ARRAY_BUFFER, i, ctx.STATIC_DRAW)
|
|
107
|
+
ctx.bufferData(ctx.ARRAY_BUFFER, i, ctx.STATIC_DRAW);
|
|
108
|
+
h.itemSize = 3;
|
|
109
|
+
h.numItems = 3;
|
|
120
110
|
|
|
121
111
|
const j = ctx.createProgram();
|
|
122
112
|
const k = ctx.createShader(ctx.VERTEX_SHADER);
|
|
@@ -133,8 +123,8 @@ export const getWebglID = (debug) => {
|
|
|
133
123
|
ctx.linkProgram(j);
|
|
134
124
|
ctx.useProgram(j);
|
|
135
125
|
|
|
136
|
-
j.vertexPosAttrib = ctx.getAttribLocation(j,
|
|
137
|
-
j.offsetUniform = ctx.getUniformLocation(j,
|
|
126
|
+
j.vertexPosAttrib = ctx.getAttribLocation(j, "attrVertex");
|
|
127
|
+
j.offsetUniform = ctx.getUniformLocation(j, "uniformOffset");
|
|
138
128
|
|
|
139
129
|
ctx.enableVertexAttribArray(j.vertexPosArray);
|
|
140
130
|
ctx.vertexAttribPointer(j.vertexPosAttrib, h.itemSize, ctx.FLOAT, !1, 0, 0);
|
|
@@ -144,7 +134,7 @@ export const getWebglID = (debug) => {
|
|
|
144
134
|
const n = new Uint8Array(canvas.width * canvas.height * 4);
|
|
145
135
|
ctx.readPixels(0, 0, canvas.width, canvas.height, ctx.RGBA, ctx.UNSIGNED_BYTE, n);
|
|
146
136
|
|
|
147
|
-
const result = JSON.stringify(n).replace(/,?"[0-9]+":/g,
|
|
137
|
+
const result = JSON.stringify(n).replace(/,?"[0-9]+":/g, "");
|
|
148
138
|
|
|
149
139
|
if (debug) {
|
|
150
140
|
document.body.appendChild(canvas);
|
|
@@ -160,7 +150,7 @@ export const getWebglID = (debug) => {
|
|
|
160
150
|
|
|
161
151
|
export const getWebglInfo = () => {
|
|
162
152
|
try {
|
|
163
|
-
const ctx = document.createElement(
|
|
153
|
+
const ctx = document.createElement("canvas").getContext("webgl");
|
|
164
154
|
|
|
165
155
|
const result = {
|
|
166
156
|
VERSION: String(ctx.getParameter(ctx.VERSION)),
|
|
@@ -181,14 +171,12 @@ export const murmurhash3_32_gc = (key) => {
|
|
|
181
171
|
const c1 = 0xcc9e2d51;
|
|
182
172
|
const c2 = 0x1b873593;
|
|
183
173
|
|
|
184
|
-
let h1
|
|
174
|
+
let h1;
|
|
175
|
+
let h1b;
|
|
176
|
+
let k1;
|
|
185
177
|
|
|
186
178
|
for (let i = 0; i < bytes; i++) {
|
|
187
|
-
k1 =
|
|
188
|
-
(key.charCodeAt(i) & 0xff) |
|
|
189
|
-
((key.charCodeAt(++i) & 0xff) << 8) |
|
|
190
|
-
((key.charCodeAt(++i) & 0xff) << 16) |
|
|
191
|
-
((key.charCodeAt(++i) & 0xff) << 24);
|
|
179
|
+
k1 = (key.charCodeAt(i) & 0xff) | ((key.charCodeAt(++i) & 0xff) << 8) | ((key.charCodeAt(++i) & 0xff) << 16) | ((key.charCodeAt(++i) & 0xff) << 24);
|
|
192
180
|
++i;
|
|
193
181
|
|
|
194
182
|
k1 = ((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
|
|
@@ -236,7 +224,7 @@ export const murmurhash3_32_gc = (key) => {
|
|
|
236
224
|
return h1 >>> 0;
|
|
237
225
|
};
|
|
238
226
|
|
|
239
|
-
if (typeof window !==
|
|
227
|
+
if (typeof window !== "undefined") {
|
|
240
228
|
window.getBrowserFingerprint = getBrowserFingerprint;
|
|
241
229
|
}
|
|
242
230
|
|