jumpy-lion 0.1.6-beta.9 → 1.0.0-beta.4

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.
Files changed (450) hide show
  1. package/README.md +1 -607
  2. package/browser/fonts/macos-bundle/41-macos-remaining.conf +157 -0
  3. package/browser/fonts/macos-bundle/README.md +24 -0
  4. package/browser/fonts/macos-bundle/build-metric-fonts.py +1010 -0
  5. package/browser/fonts/macos-bundle/generated/AmericanTypewriter-Bold.ttf +0 -0
  6. package/browser/fonts/macos-bundle/generated/AmericanTypewriter-Regular.ttf +0 -0
  7. package/browser/fonts/macos-bundle/generated/AndaleMono-Bold.ttf +0 -0
  8. package/browser/fonts/macos-bundle/generated/AndaleMono-BoldItalic.ttf +0 -0
  9. package/browser/fonts/macos-bundle/generated/AndaleMono-Italic.ttf +0 -0
  10. package/browser/fonts/macos-bundle/generated/AndaleMono-Regular.ttf +0 -0
  11. package/browser/fonts/macos-bundle/generated/AppleChancery-Bold.ttf +0 -0
  12. package/browser/fonts/macos-bundle/generated/AppleChancery-BoldItalic.ttf +0 -0
  13. package/browser/fonts/macos-bundle/generated/AppleChancery-Italic.ttf +0 -0
  14. package/browser/fonts/macos-bundle/generated/AppleChancery-Regular.ttf +0 -0
  15. package/browser/fonts/macos-bundle/generated/Arial-Bold.ttf +0 -0
  16. package/browser/fonts/macos-bundle/generated/Arial-BoldItalic.ttf +0 -0
  17. package/browser/fonts/macos-bundle/generated/Arial-Italic.ttf +0 -0
  18. package/browser/fonts/macos-bundle/generated/Arial-Regular.ttf +0 -0
  19. package/browser/fonts/macos-bundle/generated/ArialBlack-Bold.ttf +0 -0
  20. package/browser/fonts/macos-bundle/generated/ArialBlack-BoldItalic.ttf +0 -0
  21. package/browser/fonts/macos-bundle/generated/ArialBlack-Italic.ttf +0 -0
  22. package/browser/fonts/macos-bundle/generated/ArialBlack-Regular.ttf +0 -0
  23. package/browser/fonts/macos-bundle/generated/ArialNarrow-Bold.ttf +0 -0
  24. package/browser/fonts/macos-bundle/generated/ArialNarrow-BoldItalic.ttf +0 -0
  25. package/browser/fonts/macos-bundle/generated/ArialNarrow-Italic.ttf +0 -0
  26. package/browser/fonts/macos-bundle/generated/ArialNarrow-Regular.ttf +0 -0
  27. package/browser/fonts/macos-bundle/generated/Avenir-Bold.ttf +0 -0
  28. package/browser/fonts/macos-bundle/generated/Avenir-BoldItalic.ttf +0 -0
  29. package/browser/fonts/macos-bundle/generated/Avenir-Italic.ttf +0 -0
  30. package/browser/fonts/macos-bundle/generated/Avenir-Regular.ttf +0 -0
  31. package/browser/fonts/macos-bundle/generated/AvenirNext-Bold.ttf +0 -0
  32. package/browser/fonts/macos-bundle/generated/AvenirNext-BoldItalic.ttf +0 -0
  33. package/browser/fonts/macos-bundle/generated/AvenirNext-Italic.ttf +0 -0
  34. package/browser/fonts/macos-bundle/generated/AvenirNext-Regular.ttf +0 -0
  35. package/browser/fonts/macos-bundle/generated/AvenirNextCondensed-Bold.ttf +0 -0
  36. package/browser/fonts/macos-bundle/generated/AvenirNextCondensed-BoldItalic.ttf +0 -0
  37. package/browser/fonts/macos-bundle/generated/AvenirNextCondensed-Italic.ttf +0 -0
  38. package/browser/fonts/macos-bundle/generated/AvenirNextCondensed-Regular.ttf +0 -0
  39. package/browser/fonts/macos-bundle/generated/Baskerville-Bold.ttf +0 -0
  40. package/browser/fonts/macos-bundle/generated/Baskerville-BoldItalic.ttf +0 -0
  41. package/browser/fonts/macos-bundle/generated/Baskerville-Italic.ttf +0 -0
  42. package/browser/fonts/macos-bundle/generated/Baskerville-Regular.ttf +0 -0
  43. package/browser/fonts/macos-bundle/generated/BigCaslon-Bold.ttf +0 -0
  44. package/browser/fonts/macos-bundle/generated/BigCaslon-BoldItalic.ttf +0 -0
  45. package/browser/fonts/macos-bundle/generated/BigCaslon-Italic.ttf +0 -0
  46. package/browser/fonts/macos-bundle/generated/BigCaslon-Regular.ttf +0 -0
  47. package/browser/fonts/macos-bundle/generated/BlinkMacSystemFont-Bold.ttf +0 -0
  48. package/browser/fonts/macos-bundle/generated/BlinkMacSystemFont-BoldItalic.ttf +0 -0
  49. package/browser/fonts/macos-bundle/generated/BlinkMacSystemFont-Italic.ttf +0 -0
  50. package/browser/fonts/macos-bundle/generated/BlinkMacSystemFont-Regular.ttf +0 -0
  51. package/browser/fonts/macos-bundle/generated/Bodoni72-Bold.ttf +0 -0
  52. package/browser/fonts/macos-bundle/generated/Bodoni72-BoldItalic.ttf +0 -0
  53. package/browser/fonts/macos-bundle/generated/Bodoni72-Italic.ttf +0 -0
  54. package/browser/fonts/macos-bundle/generated/Bodoni72-Regular.ttf +0 -0
  55. package/browser/fonts/macos-bundle/generated/Bodoni72Oldstyle-Bold.ttf +0 -0
  56. package/browser/fonts/macos-bundle/generated/Bodoni72Oldstyle-BoldItalic.ttf +0 -0
  57. package/browser/fonts/macos-bundle/generated/Bodoni72Oldstyle-Italic.ttf +0 -0
  58. package/browser/fonts/macos-bundle/generated/Bodoni72Oldstyle-Regular.ttf +0 -0
  59. package/browser/fonts/macos-bundle/generated/Bodoni72Smallcaps-Bold.ttf +0 -0
  60. package/browser/fonts/macos-bundle/generated/Bodoni72Smallcaps-BoldItalic.ttf +0 -0
  61. package/browser/fonts/macos-bundle/generated/Bodoni72Smallcaps-Italic.ttf +0 -0
  62. package/browser/fonts/macos-bundle/generated/Bodoni72Smallcaps-Regular.ttf +0 -0
  63. package/browser/fonts/macos-bundle/generated/BradleyHand-Regular.ttf +0 -0
  64. package/browser/fonts/macos-bundle/generated/BrushScriptMT-Regular.ttf +0 -0
  65. package/browser/fonts/macos-bundle/generated/Chalkboard-Bold.ttf +0 -0
  66. package/browser/fonts/macos-bundle/generated/Chalkboard-BoldItalic.ttf +0 -0
  67. package/browser/fonts/macos-bundle/generated/Chalkboard-Italic.ttf +0 -0
  68. package/browser/fonts/macos-bundle/generated/Chalkboard-Regular.ttf +0 -0
  69. package/browser/fonts/macos-bundle/generated/ChalkboardSE-Bold.ttf +0 -0
  70. package/browser/fonts/macos-bundle/generated/ChalkboardSE-BoldItalic.ttf +0 -0
  71. package/browser/fonts/macos-bundle/generated/ChalkboardSE-Italic.ttf +0 -0
  72. package/browser/fonts/macos-bundle/generated/ChalkboardSE-Regular.ttf +0 -0
  73. package/browser/fonts/macos-bundle/generated/Chalkduster-Bold.ttf +0 -0
  74. package/browser/fonts/macos-bundle/generated/Chalkduster-BoldItalic.ttf +0 -0
  75. package/browser/fonts/macos-bundle/generated/Chalkduster-Italic.ttf +0 -0
  76. package/browser/fonts/macos-bundle/generated/Chalkduster-Regular.ttf +0 -0
  77. package/browser/fonts/macos-bundle/generated/Charter-Bold.ttf +0 -0
  78. package/browser/fonts/macos-bundle/generated/Charter-BoldItalic.ttf +0 -0
  79. package/browser/fonts/macos-bundle/generated/Charter-Italic.ttf +0 -0
  80. package/browser/fonts/macos-bundle/generated/Charter-Regular.ttf +0 -0
  81. package/browser/fonts/macos-bundle/generated/Cochin-Bold.ttf +0 -0
  82. package/browser/fonts/macos-bundle/generated/Cochin-BoldItalic.ttf +0 -0
  83. package/browser/fonts/macos-bundle/generated/Cochin-Italic.ttf +0 -0
  84. package/browser/fonts/macos-bundle/generated/Cochin-Regular.ttf +0 -0
  85. package/browser/fonts/macos-bundle/generated/ComicSansMS-Bold.ttf +0 -0
  86. package/browser/fonts/macos-bundle/generated/ComicSansMS-BoldItalic.ttf +0 -0
  87. package/browser/fonts/macos-bundle/generated/ComicSansMS-Italic.ttf +0 -0
  88. package/browser/fonts/macos-bundle/generated/ComicSansMS-Regular.ttf +0 -0
  89. package/browser/fonts/macos-bundle/generated/Copperplate-Bold.ttf +0 -0
  90. package/browser/fonts/macos-bundle/generated/Copperplate-Regular.ttf +0 -0
  91. package/browser/fonts/macos-bundle/generated/Courier-Bold.ttf +0 -0
  92. package/browser/fonts/macos-bundle/generated/Courier-BoldItalic.ttf +0 -0
  93. package/browser/fonts/macos-bundle/generated/Courier-Italic.ttf +0 -0
  94. package/browser/fonts/macos-bundle/generated/Courier-Regular.ttf +0 -0
  95. package/browser/fonts/macos-bundle/generated/CourierNew-Regular.ttf +0 -0
  96. package/browser/fonts/macos-bundle/generated/Didot-Bold.ttf +0 -0
  97. package/browser/fonts/macos-bundle/generated/Didot-BoldItalic.ttf +0 -0
  98. package/browser/fonts/macos-bundle/generated/Didot-Italic.ttf +0 -0
  99. package/browser/fonts/macos-bundle/generated/Didot-Regular.ttf +0 -0
  100. package/browser/fonts/macos-bundle/generated/Futura-Bold.ttf +0 -0
  101. package/browser/fonts/macos-bundle/generated/Futura-BoldItalic.ttf +0 -0
  102. package/browser/fonts/macos-bundle/generated/Futura-Italic.ttf +0 -0
  103. package/browser/fonts/macos-bundle/generated/Futura-Regular.ttf +0 -0
  104. package/browser/fonts/macos-bundle/generated/Geneva-Regular.ttf +0 -0
  105. package/browser/fonts/macos-bundle/generated/Georgia-Bold.ttf +0 -0
  106. package/browser/fonts/macos-bundle/generated/Georgia-BoldItalic.ttf +0 -0
  107. package/browser/fonts/macos-bundle/generated/Georgia-Italic.ttf +0 -0
  108. package/browser/fonts/macos-bundle/generated/Georgia-Regular.ttf +0 -0
  109. package/browser/fonts/macos-bundle/generated/GillSans-Bold.ttf +0 -0
  110. package/browser/fonts/macos-bundle/generated/GillSans-BoldItalic.ttf +0 -0
  111. package/browser/fonts/macos-bundle/generated/GillSans-Italic.ttf +0 -0
  112. package/browser/fonts/macos-bundle/generated/GillSans-Regular.ttf +0 -0
  113. package/browser/fonts/macos-bundle/generated/Helvetica-Bold.ttf +0 -0
  114. package/browser/fonts/macos-bundle/generated/Helvetica-BoldItalic.ttf +0 -0
  115. package/browser/fonts/macos-bundle/generated/Helvetica-Italic.ttf +0 -0
  116. package/browser/fonts/macos-bundle/generated/Helvetica-Regular.ttf +0 -0
  117. package/browser/fonts/macos-bundle/generated/HelveticaNeue-Bold.ttf +0 -0
  118. package/browser/fonts/macos-bundle/generated/HelveticaNeue-BoldItalic.ttf +0 -0
  119. package/browser/fonts/macos-bundle/generated/HelveticaNeue-Italic.ttf +0 -0
  120. package/browser/fonts/macos-bundle/generated/HelveticaNeue-Regular.ttf +0 -0
  121. package/browser/fonts/macos-bundle/generated/Herculanum-Bold.ttf +0 -0
  122. package/browser/fonts/macos-bundle/generated/Herculanum-BoldItalic.ttf +0 -0
  123. package/browser/fonts/macos-bundle/generated/Herculanum-Italic.ttf +0 -0
  124. package/browser/fonts/macos-bundle/generated/Herculanum-Regular.ttf +0 -0
  125. package/browser/fonts/macos-bundle/generated/HoeflerText-Bold.ttf +0 -0
  126. package/browser/fonts/macos-bundle/generated/HoeflerText-BoldItalic.ttf +0 -0
  127. package/browser/fonts/macos-bundle/generated/HoeflerText-Italic.ttf +0 -0
  128. package/browser/fonts/macos-bundle/generated/HoeflerText-Regular.ttf +0 -0
  129. package/browser/fonts/macos-bundle/generated/Impact-Bold.ttf +0 -0
  130. package/browser/fonts/macos-bundle/generated/Impact-BoldItalic.ttf +0 -0
  131. package/browser/fonts/macos-bundle/generated/Impact-Italic.ttf +0 -0
  132. package/browser/fonts/macos-bundle/generated/Impact-Regular.ttf +0 -0
  133. package/browser/fonts/macos-bundle/generated/LucidaGrande-Bold.ttf +0 -0
  134. package/browser/fonts/macos-bundle/generated/LucidaGrande-Regular.ttf +0 -0
  135. package/browser/fonts/macos-bundle/generated/MarkerFelt-Bold.ttf +0 -0
  136. package/browser/fonts/macos-bundle/generated/MarkerFelt-BoldItalic.ttf +0 -0
  137. package/browser/fonts/macos-bundle/generated/MarkerFelt-Italic.ttf +0 -0
  138. package/browser/fonts/macos-bundle/generated/MarkerFelt-Regular.ttf +0 -0
  139. package/browser/fonts/macos-bundle/generated/Menlo-Regular.ttf +0 -0
  140. package/browser/fonts/macos-bundle/generated/Monaco-Bold.ttf +0 -0
  141. package/browser/fonts/macos-bundle/generated/Monaco-BoldItalic.ttf +0 -0
  142. package/browser/fonts/macos-bundle/generated/Monaco-Italic.ttf +0 -0
  143. package/browser/fonts/macos-bundle/generated/Monaco-Regular.ttf +0 -0
  144. package/browser/fonts/macos-bundle/generated/Noteworthy-Bold.ttf +0 -0
  145. package/browser/fonts/macos-bundle/generated/Noteworthy-Regular.ttf +0 -0
  146. package/browser/fonts/macos-bundle/generated/Optima-Bold.ttf +0 -0
  147. package/browser/fonts/macos-bundle/generated/Optima-BoldItalic.ttf +0 -0
  148. package/browser/fonts/macos-bundle/generated/Optima-Italic.ttf +0 -0
  149. package/browser/fonts/macos-bundle/generated/Optima-Regular.ttf +0 -0
  150. package/browser/fonts/macos-bundle/generated/Palatino-Bold.ttf +0 -0
  151. package/browser/fonts/macos-bundle/generated/Palatino-BoldItalic.ttf +0 -0
  152. package/browser/fonts/macos-bundle/generated/Palatino-Italic.ttf +0 -0
  153. package/browser/fonts/macos-bundle/generated/Palatino-Regular.ttf +0 -0
  154. package/browser/fonts/macos-bundle/generated/Papyrus-Bold.ttf +0 -0
  155. package/browser/fonts/macos-bundle/generated/Papyrus-BoldItalic.ttf +0 -0
  156. package/browser/fonts/macos-bundle/generated/Papyrus-Italic.ttf +0 -0
  157. package/browser/fonts/macos-bundle/generated/Papyrus-Regular.ttf +0 -0
  158. package/browser/fonts/macos-bundle/generated/PartyLET-Bold.ttf +0 -0
  159. package/browser/fonts/macos-bundle/generated/PartyLET-BoldItalic.ttf +0 -0
  160. package/browser/fonts/macos-bundle/generated/PartyLET-Italic.ttf +0 -0
  161. package/browser/fonts/macos-bundle/generated/PartyLET-Regular.ttf +0 -0
  162. package/browser/fonts/macos-bundle/generated/Phosphate-Regular.ttf +0 -0
  163. package/browser/fonts/macos-bundle/generated/README.md +132 -0
  164. package/browser/fonts/macos-bundle/generated/Rockwell-Bold.ttf +0 -0
  165. package/browser/fonts/macos-bundle/generated/Rockwell-BoldItalic.ttf +0 -0
  166. package/browser/fonts/macos-bundle/generated/Rockwell-Italic.ttf +0 -0
  167. package/browser/fonts/macos-bundle/generated/Rockwell-Regular.ttf +0 -0
  168. package/browser/fonts/macos-bundle/generated/SavoyeLET-Bold.ttf +0 -0
  169. package/browser/fonts/macos-bundle/generated/SavoyeLET-BoldItalic.ttf +0 -0
  170. package/browser/fonts/macos-bundle/generated/SavoyeLET-Italic.ttf +0 -0
  171. package/browser/fonts/macos-bundle/generated/SavoyeLET-Regular.ttf +0 -0
  172. package/browser/fonts/macos-bundle/generated/Seravek-Bold.ttf +0 -0
  173. package/browser/fonts/macos-bundle/generated/Seravek-BoldItalic.ttf +0 -0
  174. package/browser/fonts/macos-bundle/generated/Seravek-Italic.ttf +0 -0
  175. package/browser/fonts/macos-bundle/generated/Seravek-Regular.ttf +0 -0
  176. package/browser/fonts/macos-bundle/generated/SignPainter-Bold.ttf +0 -0
  177. package/browser/fonts/macos-bundle/generated/SignPainter-Regular.ttf +0 -0
  178. package/browser/fonts/macos-bundle/generated/Skia-Bold.ttf +0 -0
  179. package/browser/fonts/macos-bundle/generated/Skia-BoldItalic.ttf +0 -0
  180. package/browser/fonts/macos-bundle/generated/Skia-Italic.ttf +0 -0
  181. package/browser/fonts/macos-bundle/generated/Skia-Regular.ttf +0 -0
  182. package/browser/fonts/macos-bundle/generated/SnellRoundhand-Bold.ttf +0 -0
  183. package/browser/fonts/macos-bundle/generated/SnellRoundhand-Regular.ttf +0 -0
  184. package/browser/fonts/macos-bundle/generated/Tahoma-Bold.ttf +0 -0
  185. package/browser/fonts/macos-bundle/generated/Tahoma-Regular.ttf +0 -0
  186. package/browser/fonts/macos-bundle/generated/Times-Bold.ttf +0 -0
  187. package/browser/fonts/macos-bundle/generated/Times-BoldItalic.ttf +0 -0
  188. package/browser/fonts/macos-bundle/generated/Times-Italic.ttf +0 -0
  189. package/browser/fonts/macos-bundle/generated/Times-Regular.ttf +0 -0
  190. package/browser/fonts/macos-bundle/generated/TimesNewRoman-Bold.ttf +0 -0
  191. package/browser/fonts/macos-bundle/generated/TimesNewRoman-BoldItalic.ttf +0 -0
  192. package/browser/fonts/macos-bundle/generated/TimesNewRoman-Italic.ttf +0 -0
  193. package/browser/fonts/macos-bundle/generated/TimesNewRoman-Regular.ttf +0 -0
  194. package/browser/fonts/macos-bundle/generated/Trattatello-Regular.ttf +0 -0
  195. package/browser/fonts/macos-bundle/generated/TrebuchetMS-Bold.ttf +0 -0
  196. package/browser/fonts/macos-bundle/generated/TrebuchetMS-BoldItalic.ttf +0 -0
  197. package/browser/fonts/macos-bundle/generated/TrebuchetMS-Italic.ttf +0 -0
  198. package/browser/fonts/macos-bundle/generated/TrebuchetMS-Regular.ttf +0 -0
  199. package/browser/fonts/macos-bundle/generated/Verdana-Bold.ttf +0 -0
  200. package/browser/fonts/macos-bundle/generated/Verdana-BoldItalic.ttf +0 -0
  201. package/browser/fonts/macos-bundle/generated/Verdana-Italic.ttf +0 -0
  202. package/browser/fonts/macos-bundle/generated/Verdana-Regular.ttf +0 -0
  203. package/browser/fonts/macos-bundle/generated/Webdings-Bold.ttf +0 -0
  204. package/browser/fonts/macos-bundle/generated/Webdings-BoldItalic.ttf +0 -0
  205. package/browser/fonts/macos-bundle/generated/Webdings-Italic.ttf +0 -0
  206. package/browser/fonts/macos-bundle/generated/Webdings-Regular.ttf +0 -0
  207. package/browser/fonts/macos-bundle/generated/Zapfino-Bold.ttf +0 -0
  208. package/browser/fonts/macos-bundle/generated/Zapfino-BoldItalic.ttf +0 -0
  209. package/browser/fonts/macos-bundle/generated/Zapfino-Italic.ttf +0 -0
  210. package/browser/fonts/macos-bundle/generated/Zapfino-Regular.ttf +0 -0
  211. package/browser/fonts/macos-bundle/generated/manifest.json +2928 -0
  212. package/browser/fonts/macos-bundle/generated/systemui-Bold.ttf +0 -0
  213. package/browser/fonts/macos-bundle/generated/systemui-BoldItalic.ttf +0 -0
  214. package/browser/fonts/macos-bundle/generated/systemui-Italic.ttf +0 -0
  215. package/browser/fonts/macos-bundle/generated/systemui-Regular.ttf +0 -0
  216. package/browser/fonts/macos-bundle/install.sh +136 -0
  217. package/browser/fonts/macos-bundle/vendor/README.md +30 -0
  218. package/browser/fonts/macos-bundle/vendor/anton/Anton-Regular.ttf +0 -0
  219. package/browser/fonts/macos-bundle/vendor/anton/OFL.txt +93 -0
  220. package/browser/fonts/macos-bundle/vendor/gelasio/Gelasio-Italic-VariableFont_wght.ttf +0 -0
  221. package/browser/fonts/macos-bundle/vendor/gelasio/Gelasio-VariableFont_wght.ttf +0 -0
  222. package/browser/fonts/macos-bundle/vendor/gelasio/OFL.txt +93 -0
  223. package/browser/fonts/macos-bundle/verify-metric-fonts.py +171 -0
  224. package/dist/browser-controller.d.ts +47 -4
  225. package/dist/browser-controller.d.ts.map +1 -1
  226. package/dist/browser-controller.js +219 -278
  227. package/dist/browser-controller.js.map +1 -1
  228. package/dist/browser-plugin.d.ts +82 -110
  229. package/dist/browser-plugin.d.ts.map +1 -1
  230. package/dist/browser-plugin.js +405 -379
  231. package/dist/browser-plugin.js.map +1 -1
  232. package/dist/browser-process/align-fingerprint-config.d.ts +36 -0
  233. package/dist/browser-process/align-fingerprint-config.d.ts.map +1 -0
  234. package/dist/browser-process/align-fingerprint-config.js +74 -0
  235. package/dist/browser-process/align-fingerprint-config.js.map +1 -0
  236. package/dist/browser-process/anti-detect-browser.d.ts +2 -2
  237. package/dist/browser-process/anti-detect-browser.js +7 -7
  238. package/dist/browser-process/anti-detect-config.d.ts +146 -2
  239. package/dist/browser-process/anti-detect-config.d.ts.map +1 -1
  240. package/dist/browser-process/anti-detect-config.js +432 -127
  241. package/dist/browser-process/anti-detect-config.js.map +1 -1
  242. package/dist/browser-process/browser.d.ts +25 -92
  243. package/dist/browser-process/browser.d.ts.map +1 -1
  244. package/dist/browser-process/browser.js +467 -79
  245. package/dist/browser-process/browser.js.map +1 -1
  246. package/dist/browser-process/fingerprint-config.d.ts +146 -0
  247. package/dist/browser-process/fingerprint-config.d.ts.map +1 -0
  248. package/dist/browser-process/fingerprint-config.js +351 -0
  249. package/dist/browser-process/fingerprint-config.js.map +1 -0
  250. package/dist/browser-process/get-chrome-executable.d.ts +6 -0
  251. package/dist/browser-process/get-chrome-executable.d.ts.map +1 -1
  252. package/dist/browser-process/get-chrome-executable.js +79 -4
  253. package/dist/browser-process/get-chrome-executable.js.map +1 -1
  254. package/dist/browser-process/gpu-family-profiles.d.ts +58 -0
  255. package/dist/browser-process/gpu-family-profiles.d.ts.map +1 -0
  256. package/dist/browser-process/gpu-family-profiles.js +480 -0
  257. package/dist/browser-process/gpu-family-profiles.js.map +1 -0
  258. package/dist/browser-process/launch-options.d.ts +301 -0
  259. package/dist/browser-process/launch-options.d.ts.map +1 -0
  260. package/dist/browser-process/launch-options.js +2 -0
  261. package/dist/browser-process/launch-options.js.map +1 -0
  262. package/dist/browser-process/port-allocator.d.ts +64 -0
  263. package/dist/browser-process/port-allocator.d.ts.map +1 -0
  264. package/dist/browser-process/port-allocator.js +198 -0
  265. package/dist/browser-process/port-allocator.js.map +1 -0
  266. package/dist/browser-process/process.d.ts +85 -0
  267. package/dist/browser-process/process.d.ts.map +1 -1
  268. package/dist/browser-process/process.js +235 -19
  269. package/dist/browser-process/process.js.map +1 -1
  270. package/dist/browser-process/signal-cleanup.d.ts +40 -0
  271. package/dist/browser-process/signal-cleanup.d.ts.map +1 -0
  272. package/dist/browser-process/signal-cleanup.js +105 -0
  273. package/dist/browser-process/signal-cleanup.js.map +1 -0
  274. package/dist/browser-process/widevine-cdm.d.ts +144 -0
  275. package/dist/browser-process/widevine-cdm.d.ts.map +1 -0
  276. package/dist/browser-process/widevine-cdm.js +298 -0
  277. package/dist/browser-process/widevine-cdm.js.map +1 -0
  278. package/dist/browser-profiles/chrome/populate-profile.d.ts.map +1 -1
  279. package/dist/browser-profiles/chrome/populate-profile.js +21 -22
  280. package/dist/browser-profiles/chrome/populate-profile.js.map +1 -1
  281. package/dist/connection/cdp-reconnection.d.ts +50 -0
  282. package/dist/connection/cdp-reconnection.d.ts.map +1 -0
  283. package/dist/connection/cdp-reconnection.js +75 -0
  284. package/dist/connection/cdp-reconnection.js.map +1 -0
  285. package/dist/connection/page-session.d.ts +114 -0
  286. package/dist/connection/page-session.d.ts.map +1 -0
  287. package/dist/connection/page-session.js +237 -0
  288. package/dist/connection/page-session.js.map +1 -0
  289. package/dist/connection/session-client.d.ts +34 -0
  290. package/dist/connection/session-client.d.ts.map +1 -0
  291. package/dist/connection/session-client.js +129 -0
  292. package/dist/connection/session-client.js.map +1 -0
  293. package/dist/crawler.d.ts +9 -88
  294. package/dist/crawler.d.ts.map +1 -1
  295. package/dist/crawler.js +157 -8
  296. package/dist/crawler.js.map +1 -1
  297. package/dist/fingerprinting/fingerprint-injector.d.ts +24 -114
  298. package/dist/fingerprinting/fingerprint-injector.d.ts.map +1 -1
  299. package/dist/fingerprinting/fingerprint-injector.js +305 -611
  300. package/dist/fingerprinting/fingerprint-injector.js.map +1 -1
  301. package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.d.ts +1 -1
  302. package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.d.ts.map +1 -1
  303. package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.js +16 -14
  304. package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.js.map +1 -1
  305. package/dist/fingerprinting/fingerprint-overrides/index.d.ts +6 -2
  306. package/dist/fingerprinting/fingerprint-overrides/index.d.ts.map +1 -1
  307. package/dist/fingerprinting/fingerprint-overrides/index.js +6 -2
  308. package/dist/fingerprinting/fingerprint-overrides/index.js.map +1 -1
  309. package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.d.ts +1 -1
  310. package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.js +4 -4
  311. package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.js.map +1 -1
  312. package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.js +4 -4
  313. package/dist/fingerprinting/fingerprint-overrides/navigator-override.d.ts +18 -0
  314. package/dist/fingerprinting/fingerprint-overrides/navigator-override.d.ts.map +1 -0
  315. package/dist/fingerprinting/fingerprint-overrides/navigator-override.js +136 -0
  316. package/dist/fingerprinting/fingerprint-overrides/navigator-override.js.map +1 -0
  317. package/dist/fingerprinting/fingerprint-overrides/override.d.ts +151 -0
  318. package/dist/fingerprinting/fingerprint-overrides/override.d.ts.map +1 -0
  319. package/dist/fingerprinting/fingerprint-overrides/override.js +14 -0
  320. package/dist/fingerprinting/fingerprint-overrides/override.js.map +1 -0
  321. package/dist/fingerprinting/fingerprint-overrides/platform-consistency.d.ts.map +1 -1
  322. package/dist/fingerprinting/fingerprint-overrides/platform-consistency.js +46 -15
  323. package/dist/fingerprinting/fingerprint-overrides/platform-consistency.js.map +1 -1
  324. package/dist/fingerprinting/fingerprint-overrides/registry.d.ts +43 -0
  325. package/dist/fingerprinting/fingerprint-overrides/registry.d.ts.map +1 -0
  326. package/dist/fingerprinting/fingerprint-overrides/registry.js +342 -0
  327. package/dist/fingerprinting/fingerprint-overrides/registry.js.map +1 -0
  328. package/dist/fingerprinting/fingerprint-overrides/screen-override.d.ts +16 -0
  329. package/dist/fingerprinting/fingerprint-overrides/screen-override.d.ts.map +1 -0
  330. package/dist/fingerprinting/fingerprint-overrides/screen-override.js +175 -0
  331. package/dist/fingerprinting/fingerprint-overrides/screen-override.js.map +1 -0
  332. package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.d.ts +1 -1
  333. package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.js +4 -4
  334. package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.js.map +1 -1
  335. package/dist/fingerprinting/fingerprint-overrides/stealth-script.d.ts.map +1 -1
  336. package/dist/fingerprinting/fingerprint-overrides/stealth-script.js +75 -9
  337. package/dist/fingerprinting/fingerprint-overrides/stealth-script.js.map +1 -1
  338. package/dist/fingerprinting/fingerprint-overrides/ua-ch.d.ts +1 -1
  339. package/dist/fingerprinting/fingerprint-overrides/ua-ch.d.ts.map +1 -1
  340. package/dist/fingerprinting/fingerprint-overrides/ua-ch.js +34 -20
  341. package/dist/fingerprinting/fingerprint-overrides/ua-ch.js.map +1 -1
  342. package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.d.ts.map +1 -1
  343. package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.js +28 -9
  344. package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.js.map +1 -1
  345. package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.js +1 -1
  346. package/dist/fingerprinting/hardware-realism.d.ts +74 -0
  347. package/dist/fingerprinting/hardware-realism.d.ts.map +1 -0
  348. package/dist/fingerprinting/hardware-realism.js +155 -0
  349. package/dist/fingerprinting/hardware-realism.js.map +1 -0
  350. package/dist/fingerprinting/injection-planner.d.ts +133 -0
  351. package/dist/fingerprinting/injection-planner.d.ts.map +1 -0
  352. package/dist/fingerprinting/injection-planner.js +497 -0
  353. package/dist/fingerprinting/injection-planner.js.map +1 -0
  354. package/dist/fingerprinting/locale-resolver.d.ts +8 -1
  355. package/dist/fingerprinting/locale-resolver.d.ts.map +1 -1
  356. package/dist/fingerprinting/locale-resolver.js +26 -3
  357. package/dist/fingerprinting/locale-resolver.js.map +1 -1
  358. package/dist/fingerprinting/non-apify-fingerprint-generator.d.ts +4 -4
  359. package/dist/fingerprinting/non-apify-fingerprint-generator.d.ts.map +1 -1
  360. package/dist/fingerprinting/non-apify-fingerprint-generator.js +35 -69
  361. package/dist/fingerprinting/non-apify-fingerprint-generator.js.map +1 -1
  362. package/dist/fingerprinting/non-apify-profiles.json +10515 -8494
  363. package/dist/fingerprinting/os-consistency.d.ts +28 -0
  364. package/dist/fingerprinting/os-consistency.d.ts.map +1 -0
  365. package/dist/fingerprinting/os-consistency.js +45 -0
  366. package/dist/fingerprinting/os-consistency.js.map +1 -0
  367. package/dist/fingerprinting/profile-quality.d.ts +25 -0
  368. package/dist/fingerprinting/profile-quality.d.ts.map +1 -0
  369. package/dist/fingerprinting/profile-quality.js +310 -0
  370. package/dist/fingerprinting/profile-quality.js.map +1 -0
  371. package/dist/fingerprinting/profile-selector.d.ts +102 -0
  372. package/dist/fingerprinting/profile-selector.d.ts.map +1 -0
  373. package/dist/fingerprinting/profile-selector.js +168 -0
  374. package/dist/fingerprinting/profile-selector.js.map +1 -0
  375. package/dist/fingerprinting/ua-alignment.d.ts +83 -0
  376. package/dist/fingerprinting/ua-alignment.d.ts.map +1 -0
  377. package/dist/fingerprinting/ua-alignment.js +197 -0
  378. package/dist/fingerprinting/ua-alignment.js.map +1 -0
  379. package/dist/fingerprinting/ua-ch-brands.d.ts +88 -0
  380. package/dist/fingerprinting/ua-ch-brands.d.ts.map +1 -0
  381. package/dist/fingerprinting/ua-ch-brands.js +174 -0
  382. package/dist/fingerprinting/ua-ch-brands.js.map +1 -0
  383. package/dist/index.d.ts +5 -0
  384. package/dist/index.d.ts.map +1 -1
  385. package/dist/index.js +6 -0
  386. package/dist/index.js.map +1 -1
  387. package/dist/input/dropdown-selector.d.ts +90 -0
  388. package/dist/input/dropdown-selector.d.ts.map +1 -0
  389. package/dist/input/dropdown-selector.js +394 -0
  390. package/dist/input/dropdown-selector.js.map +1 -0
  391. package/dist/input/element-target.d.ts +152 -0
  392. package/dist/input/element-target.d.ts.map +1 -0
  393. package/dist/input/element-target.js +461 -0
  394. package/dist/input/element-target.js.map +1 -0
  395. package/dist/input/input-emulator.d.ts +85 -0
  396. package/dist/input/input-emulator.d.ts.map +1 -0
  397. package/dist/input/input-emulator.js +325 -0
  398. package/dist/input/input-emulator.js.map +1 -0
  399. package/dist/input/input-transport.d.ts +60 -0
  400. package/dist/input/input-transport.d.ts.map +1 -0
  401. package/dist/input/input-transport.js +28 -0
  402. package/dist/input/input-transport.js.map +1 -0
  403. package/dist/input/recording-transport.d.ts +32 -0
  404. package/dist/input/recording-transport.d.ts.map +1 -0
  405. package/dist/input/recording-transport.js +43 -0
  406. package/dist/input/recording-transport.js.map +1 -0
  407. package/dist/keyboard-layout.d.ts +2 -2
  408. package/dist/keyboard-layout.js +2 -2
  409. package/dist/navigation/page-navigation.d.ts +67 -0
  410. package/dist/navigation/page-navigation.d.ts.map +1 -0
  411. package/dist/navigation/page-navigation.js +122 -0
  412. package/dist/navigation/page-navigation.js.map +1 -0
  413. package/dist/network/network-watch.d.ts +110 -0
  414. package/dist/network/network-watch.d.ts.map +1 -0
  415. package/dist/network/network-watch.js +223 -0
  416. package/dist/network/network-watch.js.map +1 -0
  417. package/dist/page.d.ts +123 -104
  418. package/dist/page.d.ts.map +1 -1
  419. package/dist/page.js +348 -1129
  420. package/dist/page.js.map +1 -1
  421. package/dist/session/inject-hook.d.ts +24 -0
  422. package/dist/session/inject-hook.d.ts.map +1 -0
  423. package/dist/session/inject-hook.js +80 -0
  424. package/dist/session/inject-hook.js.map +1 -0
  425. package/dist/session/save.d.ts +21 -0
  426. package/dist/session/save.d.ts.map +1 -0
  427. package/dist/session/save.js +163 -0
  428. package/dist/session/save.js.map +1 -0
  429. package/dist/session/tar-data-dir.d.ts +18 -0
  430. package/dist/session/tar-data-dir.d.ts.map +1 -0
  431. package/dist/session/tar-data-dir.js +105 -0
  432. package/dist/session/tar-data-dir.js.map +1 -0
  433. package/dist/session/types.d.ts +80 -0
  434. package/dist/session/types.d.ts.map +1 -0
  435. package/dist/session/types.js +29 -0
  436. package/dist/session/types.js.map +1 -0
  437. package/dist/session-profile.d.ts +102 -0
  438. package/dist/session-profile.d.ts.map +1 -0
  439. package/dist/session-profile.js +163 -0
  440. package/dist/session-profile.js.map +1 -0
  441. package/dist/tsconfig.build.tsbuildinfo +1 -1
  442. package/package.json +15 -6
  443. package/dist/fingerprinting/custom-fingerprint-injector.d.ts +0 -87
  444. package/dist/fingerprinting/custom-fingerprint-injector.d.ts.map +0 -1
  445. package/dist/fingerprinting/custom-fingerprint-injector.js +0 -342
  446. package/dist/fingerprinting/custom-fingerprint-injector.js.map +0 -1
  447. package/dist/launcher-wrap.d.ts +0 -10
  448. package/dist/launcher-wrap.d.ts.map +0 -1
  449. package/dist/launcher-wrap.js +0 -11
  450. package/dist/launcher-wrap.js.map +0 -1
@@ -1,28 +1,68 @@
1
1
  /**
2
- * anti-detect-config.ts — Generate and manage FingerprintConfig JSON for the anti-detect browser
2
+ * anti-detect-config.ts - Generate and manage FingerprintConfig JSON for the anti-detect browser
3
3
  *
4
4
  * Called by browser.ts before launching the browser when useNativeStealth is enabled.
5
5
  * Translates the fingerprint-generator BrowserFingerprintWithHeaders output into
6
- * the --fingerprint-config JSON schema consumed by the C++ FingerprintConfig class.
6
+ * the --blink-platform-overrides-file JSON schema consumed by the C++ override singleton.
7
7
  */
8
+ import crypto from 'crypto';
8
9
  import fs from 'fs/promises';
9
10
  import os from 'os';
10
11
  import path from 'path';
11
- import crypto from 'crypto';
12
+ import { log } from 'crawlee';
13
+ import { deriveWebglFamilyProfile } from './gpu-family-profiles.js';
14
+ import { deriveRealisticDeviceMemory, deriveStorageQuota, normalizePlatformVersion, } from '../fingerprinting/hardware-realism.js';
15
+ import { alignBrandList } from '../fingerprinting/ua-ch-brands.js';
16
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
17
+ /**
18
+ * Pick deterministic, plausible navigator.connection values for a given session.
19
+ * Real residential broadband: rtt 25-150ms (Chrome rounds to 25ms steps),
20
+ * downlink 5-50 Mbps. Datacenters report rtt<5ms and downlink>500 Mbps which
21
+ * is an obvious bot signal. Same seed → same values, so a Mac harvest and a
22
+ * Linux-Docker-spoof harvest produce identical readouts.
23
+ */
24
+ function deriveNetwork(seed) {
25
+ // rtt in [50, 150] ms, in 25ms steps (so 50, 75, 100, 125, 150).
26
+ const rttSteps = [50, 75, 100, 125, 150];
27
+ const rttIdx = (seed >>> 16) % rttSteps.length;
28
+ const rtt = rttSteps[rttIdx];
29
+ // downlink in [5, 25] Mbps, rounded to one decimal - Chrome rounds to ~1.5
30
+ // significant figures. Use a stable hash of the seed so the choice is
31
+ // reproducible.
32
+ const downlinkBucket = (seed >>> 24) & 0xFF; // 0..255
33
+ const downlink = Math.round((5 + (downlinkBucket / 255) * 20) * 10) / 10;
34
+ return { rtt, downlink, effectiveType: '4g', saveData: false };
35
+ }
36
+ /**
37
+ * Pick the AudioContext sampleRate the claimed machine's output runs at.
38
+ * Pinning it here makes the JS-visible value match the OS we claim rather than
39
+ * the container we run in.
40
+ */
41
+ function deriveAudioSampleRate(platform) {
42
+ // 48000 everywhere, including Mac. This used to return 44100 for Mac on the
43
+ // widely-repeated "CoreAudio defaults to 44.1 kHz" claim, which is stale:
44
+ // measured 2026-08-12 against real Google Chrome 151.0.7922.108 on macOS
45
+ // 26.5.2 (M4 Pro), `new AudioContext().sampleRate` is 48000. Apple Silicon
46
+ // Macs run their built-in output at 48 kHz; 44100 is an Intel-era value.
47
+ //
48
+ // The old branch did not merely miss - it was actively harmful. A Linux
49
+ // container's default output reports 44100, so forcing 44100 under a Mac
50
+ // claim PRESERVED the container's value and moved the session away from the
51
+ // Mac it claims to be. Doing nothing would have been closer.
52
+ //
53
+ // Non-Mac claims land on 48000 too (WASAPI and PulseAudio both default
54
+ // there), so the platform argument no longer changes the answer; it stays in
55
+ // the signature because an Intel-Mac measurement could reintroduce a branch.
56
+ void platform;
57
+ return 48000;
58
+ }
12
59
  // ─── Generation ───────────────────────────────────────────────────────────────
13
60
  /**
14
- * Generate a FingerprintConfig JSON object from fingerprint-generator output.
15
- *
16
- * @param fingerprint - BrowserFingerprintWithHeaders from fingerprint-generator
17
- * @param sessionId - Session identifier used to derive the seed (proxy session ID, etc.)
18
- * @param resolvedLocale - Pre-resolved locale/languages/timezone triple. When provided,
19
- * these values win over anything derived from fingerprint-generator headers so that a
20
- * user-supplied `locale: 'ko-KR'` coherently propagates to every locale surface
21
- * (Accept-Language, navigator.language, Intl defaults, timezone).
61
+ * Derive the 53-bit session seed from the proxy session tag (or a per-process
62
+ * random source when none is supplied) and the UA. See `generateFingerprintConfig`
63
+ * for the determinism rationale.
22
64
  */
23
- export function generateFingerprintConfig(fingerprint, sessionId, resolvedLocale) {
24
- const fp = fingerprint.fingerprint;
25
- const headers = fingerprint.headers;
65
+ function deriveSeed(sessionId, userAgent) {
26
66
  // Seed derivation:
27
67
  // - With a sessionId (proxy session tag) → deterministic: same session ID
28
68
  // always yields the same seed so cookies/IP/canvas/audio stay coherent
@@ -31,20 +71,25 @@ export function generateFingerprintConfig(fingerprint, sessionId, resolvedLocale
31
71
  // random. Without this, the fingerprint-generator macOS/Chrome pool
32
72
  // emits exactly one UA across many runs, so sessionId-less calls would
33
73
  // all produce the same seed and therefore the same canvas/audio noise
34
- // hash across every session — a cross-session correlation signal.
74
+ // hash across every session - a cross-session correlation signal.
35
75
  const seedSource = sessionId
36
- ? `${sessionId}|${fp.navigator?.userAgent ?? ''}`
37
- : `${crypto.randomBytes(16).toString('hex')}|${fp.navigator?.userAgent ?? ''}`;
76
+ ? `${sessionId}|${userAgent}`
77
+ : `${crypto.randomBytes(16).toString('hex')}|${userAgent}`;
38
78
  const seedHash = crypto.createHash('sha256').update(seedSource).digest();
39
79
  // Take first 8 bytes as a number (JavaScript number precision is sufficient for 53-bit ints)
40
- const seed = seedHash.readUInt32BE(0) * 0x100000000 + seedHash.readUInt32BE(4);
41
- // Navigator platform
80
+ return seedHash.readUInt32BE(0) * 0x100000000 + seedHash.readUInt32BE(4);
81
+ }
82
+ /**
83
+ * Build the navigator surface: legacy + UA-CH platform split, UA-CH brands,
84
+ * user agent, deviceMemory resampling, and storage-quota pinning. Pure.
85
+ */
86
+ function buildNavigatorSurface(fp, headers, seed, locale) {
42
87
  // navigator.platform (legacy) and navigator.userAgentData.platform (UA-CH)
43
88
  // are DIFFERENT APIs with DIFFERENT values:
44
89
  // navigator.platform → 'MacIntel' | 'Win32' | 'Linux x86_64'
45
90
  // navigator.userAgentData.platform → 'macOS' | 'Windows' | 'Linux'
46
91
  // Previously this code collapsed both to the UA-CH form, which made
47
- // navigator.platform report "macOS" in both the main frame and workers —
92
+ // navigator.platform report "macOS" in both the main frame and workers -
48
93
  // that is a Chrome invariant violation (real Chrome always returns
49
94
  // "MacIntel" from navigator.platform regardless of architecture).
50
95
  //
@@ -59,103 +104,385 @@ export function generateFingerprintConfig(fingerprint, sessionId, resolvedLocale
59
104
  'Linux x86_64': 'Linux',
60
105
  };
61
106
  const uaChPlatform = legacyToUaCH[platform] ?? platform;
62
- // UA-CH brands from fingerprint
107
+ // User agent from headers (most accurate source)
108
+ const userAgent = headers['user-agent']
109
+ ?? fp.navigator?.userAgent
110
+ ?? '';
111
+ // UA-CH brands from fingerprint. Rebuilt rather than copied: Chromium
112
+ // derives the GREASE token, its fake version and the ORDER of the
113
+ // three-entry list from the major alone (see ua-ch-brands.ts). Pool
114
+ // profiles occasionally carry a GREASE token harvested from a different
115
+ // major, and `alignFingerprintConfigWithBinary` only runs when the binary
116
+ // version can be read - so the C++ FingerprintConfig has to be coherent at
117
+ // construction, or the binary faithfully emits a `sec-ch-ua` no Chromium
118
+ // ever sent (challenge-free HTTP 418 on Naver - issue #131).
63
119
  const uaData = fp.navigator?.userAgentData;
64
120
  const brands = uaData?.brands ?? [];
65
- const fullVersionList = uaData?.fullVersionList ?? brands;
66
- const uaBrands = brands.map((b, i) => ({
121
+ // Same rule on the native path: UA-CH carries the real build even though UA
122
+ // Reduction froze the UA string to MAJOR.0.0.0, so the UA is the LAST resort
123
+ // for this value. `alignFingerprintConfigWithBinary` normally replaces it
124
+ // with the binary's own build; when the version probe failed AND the profile
125
+ // has no build number, the config would emit "147.0.0.0" in
126
+ // sec-ch-ua-full-version(-list) - a shape no Chrome sends (issue #131).
127
+ const uaFullVersion = uaData?.uaFullVersion ?? extractFullVersion(userAgent);
128
+ if (/^\d+\.0\.0\.0$/.test(uaFullVersion)) {
129
+ log.warning('[AntiDetect] Profile has no UA-CH build version; falling back to the UA-reduced '
130
+ + 'MAJOR.0.0.0 shape. Origins that request high-entropy hints reject it - the binary '
131
+ + 'version probe must succeed for alignFingerprintConfigWithBinary to repair this.', { uaFullVersion });
132
+ }
133
+ const majorBrands = alignBrandList(brands, uaFullVersion.split('.')[0]);
134
+ const fullBrands = alignBrandList(brands, uaFullVersion);
135
+ const uaBrands = brands.length === 0 ? [] : majorBrands.map((b, i) => ({
67
136
  brand: b.brand,
68
137
  version: b.version,
69
- full_version: fullVersionList[i]?.version ?? b.version,
138
+ full_version: fullBrands[i]?.version ?? b.version,
70
139
  }));
140
+ const brandName = extractBrandName(uaBrands, userAgent);
141
+ // deviceMemory: the W3C 2018 spec defined {0.25, 0.5, 1, 2, 4, 8} buckets,
142
+ // but real Chrome 147 on desktop now returns the raw host RAM in GB
143
+ // (verified by harvest 2026-05-11: 32 GB Apple Silicon Mac reports
144
+ // `navigator.deviceMemory === 32`). Reporting the legacy spec-bucketed 8
145
+ // is now a population minority (<15% of real Mac traffic) and an
146
+ // instant detection vector. Sample from a realistic 2026 Mac RAM
147
+ // distribution (8/16/24/32/48/64/128 GB), keyed off the session seed
148
+ // so Mac-on-Mac and Mac-on-Linux runs of the same seed agree.
149
+ const rawDeviceMemory = fp.navigator?.deviceMemory ?? 8;
150
+ const deviceMemory = deriveRealisticDeviceMemory(seed, rawDeviceMemory);
151
+ // navigator.storage.estimate().quota - pinned per-session so the same profile
152
+ // reports the same quota on Mac and Linux (without this, real disk leaks
153
+ // through). Derived from seed+deviceMemory to land in a plausible Mac-SSD
154
+ // distribution: 8 GB RAM ↔ 256/512 GB SSD, 16 GB ↔ 512/1024 GB, 24/32 GB ↔
155
+ // 1024/2048 GB. Chrome's StorageManager normally reports ~60% of total disk
156
+ // space; we mirror that range with ±10% seed-driven jitter so different
157
+ // profiles get different (but plausible) values.
158
+ const storageQuota = deriveStorageQuota(seed, deviceMemory);
159
+ const navigator = {
160
+ platform, // legacy form: 'MacIntel' | 'Win32' | 'Linux x86_64'
161
+ ...(locale.language && { language: locale.language }),
162
+ ...(locale.languages && { languages: locale.languages }),
163
+ hardwareConcurrency: fp.navigator?.hardwareConcurrency ?? 8,
164
+ deviceMemory,
165
+ storageQuota,
166
+ userAgent,
167
+ ...(uaBrands.length > 0 && {
168
+ userAgentData: {
169
+ brands: uaBrands,
170
+ mobile: uaData?.mobile ?? false,
171
+ platform: uaData?.platform ?? uaChPlatform,
172
+ platformVersion: normalizePlatformVersion(platform, uaData?.platformVersion, seed),
173
+ architecture: uaData?.architecture ?? 'x86',
174
+ bitness: uaData?.bitness ?? '64',
175
+ model: uaData?.model ?? '',
176
+ uaFullVersion,
177
+ fullVersionList: uaBrands,
178
+ },
179
+ }),
180
+ };
181
+ return { navigator, brandName, uaChPlatform, platform };
182
+ }
183
+ /**
184
+ * Build the WebGL surface: vendor/renderer passthrough, family classification,
185
+ * texture-size cap matched to the renderer, and the per-family pname block. Pure.
186
+ */
187
+ function buildWebglSurface(fp) {
71
188
  // WebGL from fingerprint. Real Chrome 147 on Apple Silicon leaks the
72
189
  // exact chip variant verbatim ("ANGLE (Apple, ANGLE Metal Renderer:
73
190
  // Apple M4 Pro, Unspecified Version)"), confirmed against a user's
74
191
  // shipping Chrome + CreepJS verdict. Matching that behavior is safer than
75
- // sanitizing to a generic M1 — anti-bot ML models expect the raw string,
192
+ // sanitizing to a generic M1 - anti-bot ML models expect the raw string,
76
193
  // and the hardware leak is not a Chrome-level invariant violation.
77
194
  const videoCard = fp.videoCard;
78
195
  const webglVendor = videoCard?.vendor ?? 'Google Inc. (NVIDIA)';
79
196
  const webglRenderer = videoCard?.renderer
80
197
  ?? 'ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 Direct3D11 vs_5_0 ps_5_0, D3D11)';
81
- // Screen
198
+ // GL_MAX_TEXTURE_SIZE override. SwiftShader (--use-angle=swiftshader) returns
199
+ // 8192; real Apple Silicon (Metal), modern NVIDIA / AMD discrete GPUs, and
200
+ // most Intel iGPUs return 16384. Pair the spoofed renderer with its real
201
+ // texture-size cap; mismatch is an instant CreepJS catch.
202
+ //
203
+ // M1 - also classify the renderer into a GPU family (apple_metal,
204
+ // linux_mesa_*, windows_d3d_*) so we can populate the rest of the
205
+ // platform-divergent WebGL pnames (max_draw_buffers, aliased_*_range, ...)
206
+ // from the per-family PLATFORM_GPU_TABLE. The C++ binary ignores the new
207
+ // keys until M2 lands the parser additions; once it does, the JSON shape
208
+ // is already correct.
209
+ const rendererLower = webglRenderer.toLowerCase();
210
+ // Thread navigator.platform so an unclassifiable renderer (SwiftShader,
211
+ // exotic strings) on a known OS falls back to that OS's family params
212
+ // instead of Apple-Silicon defaults - keeps the param block OS-coherent.
213
+ const navPlatform = fp.navigator?.platform;
214
+ const { family: webglFamily, profile: webglFamilyProfile } = deriveWebglFamilyProfile(webglRenderer, navPlatform);
215
+ const webglMaxTextureSize = (() => {
216
+ if (/apple|metal|m[123]\b|intel.*iris.*xe|nvidia geforce rtx 40|nvidia geforce rtx 30|nvidia geforce rtx 20|amd radeon (rx [56789]|pro)/i.test(rendererLower)) {
217
+ return 16384;
218
+ }
219
+ if (/nvidia geforce (gtx 1[06]|rtx 50|rtx 60)|amd radeon rx 7|nvidia rtx (a|h)/i.test(rendererLower)) {
220
+ return 32768; // newest cards / workstation
221
+ }
222
+ if (/swiftshader|llvmpipe|mesa offscreen/i.test(rendererLower)) {
223
+ return 8192; // honest SwiftShader claim
224
+ }
225
+ return webglFamilyProfile.maxTextureSize; // family-table default
226
+ })();
227
+ const webgl = {
228
+ vendor: webglVendor,
229
+ renderer: webglRenderer,
230
+ maxTextureSize: webglMaxTextureSize,
231
+ maxViewportDim: webglFamilyProfile.maxViewportDim,
232
+ extensions: webglFamilyProfile.extensions,
233
+ ...(webglFamily && { familyHint: webglFamily }),
234
+ maxDrawBuffers: webglFamilyProfile.maxDrawBuffers,
235
+ maxSamples: webglFamilyProfile.maxSamples,
236
+ max3dTextureSize: webglFamilyProfile.max3dTextureSize,
237
+ maxArrayTextureLayers: webglFamilyProfile.maxArrayTextureLayers,
238
+ subpixelBits: webglFamilyProfile.subpixelBits,
239
+ maxTransformFeedbackInterleavedComponents: webglFamilyProfile.maxTransformFeedbackInterleavedComponents,
240
+ aliasedLineWidthRange: webglFamilyProfile.aliasedLineWidthRange,
241
+ aliasedPointSizeRange: webglFamilyProfile.aliasedPointSizeRange,
242
+ };
243
+ return { webgl, family: webglFamily, vendor: webglVendor };
244
+ }
245
+ /**
246
+ * The WebGPU adapter surface of a real Apple Silicon Mac, captured from Google
247
+ * Chrome 151.0.7922.108 on macOS 26.5.2 (M4 Pro), 2026-08-12.
248
+ *
249
+ * On a GPU-less container Dawn hands us a SwiftShader adapter, and spoofing only
250
+ * its vendor/architecture leaves a page reading Apple identity strings against
251
+ * software-renderer capabilities: 8192 max texture dimension instead of 16384,
252
+ * 256 compute invocations instead of 1024, subgroups of 4 instead of 32, and a
253
+ * feature list missing shader-f16 / dual-source-blending / primitive-index /
254
+ * texture-formats-tier1+2 while carrying two SwiftShader-only entries. Each is a
255
+ * table lookup away from "this is not an Apple GPU".
256
+ */
257
+ const APPLE_WEBGPU_ADAPTER = {
258
+ subgroupMinSize: 32,
259
+ subgroupMaxSize: 32,
260
+ features: [
261
+ 'bgra8unorm-storage', 'clip-distances', 'core-features-and-limits', 'depth-clip-control',
262
+ 'depth32float-stencil8', 'dual-source-blending', 'float32-blendable', 'float32-filterable',
263
+ 'indirect-first-instance', 'primitive-index', 'rg11b10ufloat-renderable', 'shader-f16',
264
+ 'subgroups', 'texture-component-swizzle', 'texture-compression-astc',
265
+ 'texture-compression-astc-sliced-3d', 'texture-compression-bc',
266
+ 'texture-compression-bc-sliced-3d', 'texture-compression-etc2', 'texture-formats-tier1',
267
+ 'texture-formats-tier2', 'timestamp-query',
268
+ ],
269
+ limits: {
270
+ maxBufferSize: 4294967292,
271
+ maxComputeInvocationsPerWorkgroup: 1024,
272
+ maxComputeWorkgroupSizeX: 1024,
273
+ maxComputeWorkgroupSizeY: 1024,
274
+ maxDynamicStorageBuffersPerPipelineLayout: 8,
275
+ maxDynamicUniformBuffersPerPipelineLayout: 10,
276
+ maxSampledTexturesPerShaderStage: 48,
277
+ maxStorageBufferBindingSize: 4294967292,
278
+ maxStorageTexturesInFragmentStage: 8,
279
+ maxStorageTexturesInVertexStage: 8,
280
+ maxStorageTexturesPerShaderStage: 8,
281
+ maxTextureArrayLayers: 2048,
282
+ maxTextureDimension1D: 16384,
283
+ maxTextureDimension2D: 16384,
284
+ maxVertexAttributes: 30,
285
+ },
286
+ };
287
+ /** Build the WebGPU surface from explicit fingerprint data or the WebGL vendor. Pure. */
288
+ function buildWebgpuSurface(fp, webglVendor) {
289
+ // WebGPU - from explicit webgpu field on fingerprint (non-Apify profiles), or
290
+ // derived from WebGL vendor as a fallback (Apify fingerprints have no webgpu data).
291
+ const webgpuData = fp.webgpu;
292
+ const derivedWebGPUVendor = webgpuData?.vendor ?? deriveWebGPUVendorFromWebGL(webglVendor);
293
+ if (!derivedWebGPUVendor)
294
+ return undefined;
295
+ const surface = {
296
+ vendor: derivedWebGPUVendor,
297
+ // An Apple vendor with an EMPTY architecture is not what any Mac
298
+ // reports, and that is what the synthetic pool produces (it carries no
299
+ // WebGPU data at all, so the vendor is derived from WebGL and the rest
300
+ // defaults blank). Chrome 151 on Metal-3-capable Apple hardware - every
301
+ // Apple Silicon Mac on a current macOS - reports metal-3; measured
302
+ // 2026-08-12 on an M4 Pro.
303
+ architecture: webgpuData?.architecture
304
+ || (derivedWebGPUVendor === 'apple' ? 'metal-3' : ''),
305
+ device: webgpuData?.device ?? '',
306
+ // Real macOS Chrome reports an EMPTY description. Naming the chip here
307
+ // would contradict the Mac it claims to be as directly as naming
308
+ // SwiftShader would.
309
+ description: webgpuData?.description ?? '',
310
+ };
311
+ if (derivedWebGPUVendor === 'apple') {
312
+ surface.subgroupMinSize = APPLE_WEBGPU_ADAPTER.subgroupMinSize;
313
+ surface.subgroupMaxSize = APPLE_WEBGPU_ADAPTER.subgroupMaxSize;
314
+ surface.features = [...APPLE_WEBGPU_ADAPTER.features];
315
+ surface.limits = { ...APPLE_WEBGPU_ADAPTER.limits };
316
+ }
317
+ return surface;
318
+ }
319
+ /** Build the screen surface, keeping it coherent with the claimed platform. Pure. */
320
+ function buildScreenSurface(fp) {
82
321
  const screen = fp.screen;
83
- // User agent from headers (most accurate source)
84
- const userAgent = headers['user-agent']
85
- ?? fp.navigator?.userAgent
86
- ?? '';
322
+ const isMac = /Mac/i.test(fp.navigator?.platform ?? '');
323
+ // colorDepth is NOT capped at 24. The previous cap carried the comment
324
+ // "real Chrome privacy-reduces to 24 regardless of display HDR capability".
325
+ // Measured 2026-08-10 against real Google Chrome 151.0.7922.108 on macOS
326
+ // 26.5.2: it reports 30, on colorDepth and pixelDepth alike. Capping made
327
+ // it impossible for a profile claiming a modern wide-gamut Mac to report
328
+ // what such a Mac reports, while every other screen field said Mac.
329
+ const colorDepth = screen?.colorDepth ?? (isMac ? 30 : 24);
330
+ // Every Apple Silicon Mac is Retina: devicePixelRatio is 2. A MacIntel
331
+ // platform with an Apple Metal renderer and devicePixelRatio 1 is a
332
+ // combination no real machine produces, and it is one line to check.
333
+ const rawRatio = screen?.devicePixelRatio;
334
+ const pixelRatio = isMac ? Math.max(rawRatio ?? 2, 2) : (rawRatio ?? 1);
335
+ // macOS always reserves the menu bar, so availHeight is strictly less than
336
+ // height. Measured 33px on a real Mac; the old blanket -40 is a Windows
337
+ // taskbar shape.
338
+ const height = screen?.height ?? (isMac ? 1117 : 1080);
339
+ const reserved = isMac ? 33 : 40;
340
+ // The reserve is enforced, not merely defaulted. A pool profile that reports
341
+ // availHeight EQUAL to height used to pass straight through, and a session
342
+ // claiming macOS then said its screen has no menu bar - which no Mac does,
343
+ // and which is one comparison to check. Measured on the platform 2026-08-12:
344
+ // screen 1680x1050 with availHeight 1050 against a MacIntel platform.
345
+ const providedAvailHeight = screen?.availHeight;
346
+ const availHeight = isMac
347
+ ? Math.min(providedAvailHeight ?? height - reserved, height - reserved)
348
+ : providedAvailHeight ?? height - reserved;
349
+ return {
350
+ width: screen?.width ?? (isMac ? 1728 : 1920),
351
+ height,
352
+ availWidth: screen?.availWidth ?? screen?.width ?? (isMac ? 1728 : 1920),
353
+ availHeight,
354
+ colorDepth,
355
+ pixelRatio,
356
+ };
357
+ }
358
+ /**
359
+ * Resolve the (navigator.language, navigator.languages, timezone) triple the
360
+ * config advertises. Prefers the pre-resolved locale (explicit-intent path),
361
+ * else a seeded plausible default. Pure.
362
+ */
363
+ function buildLocaleSurface(headers, resolvedLocale, seed) {
87
364
  // Accept-language: prefer the pre-resolved triple (so a user-supplied locale wins)
88
365
  // and fall back to fingerprint headers when no resolution happened.
89
366
  //
90
367
  // Important: the C++ FingerprintConfig reader splits this string on commas and
91
368
  // feeds each entry verbatim into `navigator.languages` (the JS array). Real Chrome's
92
- // navigator.languages never carries q-values — those are HTTP Accept-Language
369
+ // navigator.languages never carries q-values - those are HTTP Accept-Language
93
370
  // semantics only. If we leave `"en-US,en;q=0.9"` in the config, the JS array leaks
94
371
  // `"en;q=0.9"` which is an instant detectable anomaly. Strip q-values here so the
95
372
  // config field is the clean list; the HTTP header flows from the same field and
96
373
  // will also be q-less, which is a valid (if less common) real-browser pattern.
97
- const rawAcceptLanguage = resolvedLocale?.languages
98
- ?? headers['accept-language']
99
- ?? headers['Accept-Language'];
100
- const acceptLanguage = rawAcceptLanguage
101
- ? rawAcceptLanguage.split(',').map((l) => l.split(';')[0].trim()).filter(Boolean).join(',')
102
- : undefined;
103
- const navLanguage = resolvedLocale?.locale;
104
- const timezone = resolvedLocale?.timezone;
105
- // Primary brand name — extract from UA-CH brands or derive from User-Agent
106
- const brandName = extractBrandName(uaBrands, userAgent);
107
- // Battery — generate realistic values based on target platform.
108
- // Uses UA-CH platform names ('Windows'|'macOS'|'Linux') for the desktop/mac checks.
109
- const battery = generateBatteryConfig(uaChPlatform, seed);
110
- // deviceMemory: spec requires the value be one of {0.25, 0.5, 1, 2, 4, 8}
111
- // (https://www.w3.org/TR/device-memory/#sec-device-memory-js-api). Exposing
112
- // anything outside this set — in particular the real 32 on a 32 GB machine —
113
- // is an immediate "bot" signal for any vendor that checks.
114
- const rawDeviceMemory = fp.navigator?.deviceMemory ?? 8;
115
- const deviceMemory = clampDeviceMemoryToSpecBuckets(rawDeviceMemory);
116
- // colorDepth: real Chrome privacy-reduces to 24 regardless of display HDR
117
- // capability. 30 is the raw macOS value that leaks through when we don't cap.
118
- const rawColorDepth = screen?.colorDepth ?? 24;
119
- const colorDepth = Math.min(rawColorDepth, 24);
374
+ if (resolvedLocale) {
375
+ // User specified a locale (fingerprintOptions.locale) or one was derived
376
+ // from the proxy session. Honour it verbatim - this is the explicit-intent
377
+ // path and the source of truth for navigator.language / Accept-Language /
378
+ // timezone propagation.
379
+ const raw = resolvedLocale.languages
380
+ ?? headers['accept-language']
381
+ ?? headers['Accept-Language'];
382
+ const languages = raw
383
+ ? raw.split(',').map((l) => l.split(';')[0].trim()).filter(Boolean).join(',')
384
+ : undefined;
385
+ return { language: resolvedLocale.locale, languages, timezone: resolvedLocale.timezone };
386
+ }
387
+ // ─── No-intent fallback ─────────────────────────────────────────────
388
+ // Without a resolvedLocale, the fingerprint-generator's Accept-Language
389
+ // header reflects the HOST machine (Mac dev box in Prague → cs-CZ
390
+ // header). Using it would leak the host locale through navigator.languages
391
+ // and the Worker's Intl/Date paths regardless of what UA the spoof
392
+ // claims. CreepJS Worker probe flags this as "lang/timezone confidence:
393
+ // high" on the host's value - instant detection.
394
+ //
395
+ // Pin a seeded-but-plausible default so the seed deterministically picks
396
+ // a coherent (locale, languages, timezone) triple. Pool entries are
397
+ // common English-speaking combos that match the macOS UA-Reduction
398
+ // freeze; identical seed → identical triple, so Mac-on-Mac and
399
+ // Mac-on-Linux runs are diff-stable.
400
+ const FALLBACK_POOL = [
401
+ { locale: 'en-US', languages: 'en-US,en', timezone: 'America/Los_Angeles' },
402
+ { locale: 'en-US', languages: 'en-US,en', timezone: 'America/New_York' },
403
+ { locale: 'en-US', languages: 'en-US,en', timezone: 'America/Chicago' },
404
+ { locale: 'en-US', languages: 'en-US,en', timezone: 'America/Denver' },
405
+ { locale: 'en-GB', languages: 'en-GB,en', timezone: 'Europe/London' },
406
+ { locale: 'en-CA', languages: 'en-CA,en', timezone: 'America/Toronto' },
407
+ { locale: 'en-AU', languages: 'en-AU,en', timezone: 'Australia/Sydney' },
408
+ ];
409
+ const idx = Math.abs(Math.trunc(seed)) % FALLBACK_POOL.length;
410
+ const fb = FALLBACK_POOL[idx];
411
+ return { language: fb.locale, languages: fb.languages, timezone: fb.timezone };
412
+ }
413
+ /**
414
+ * Derive the canvas text-rendering-mode hint from the WebGL family so canvas2D
415
+ * text rasterisation matches the OS we claim. Pure.
416
+ */
417
+ function buildCanvasSurface(family) {
418
+ // M6: the C++ FingerprintConfig parser ALSO derives the same default when
419
+ // canvas is omitted entirely, so this is belt-and-suspenders - but writing
420
+ // it from here means the JSON config is self-describing and a reader can
421
+ // see exactly which mode + font allowlist the session ships with.
422
+ if (!family)
423
+ return undefined;
424
+ const textRenderingMode = (() => {
425
+ switch (family) {
426
+ // Grayscale, not LCD striped, and matching the C++ default for this
427
+ // family rather than contradicting it. macOS has not used subpixel
428
+ // antialiasing since 10.14 Mojave, so a 2026 Mac claim asking for
429
+ // striped edges describes a machine that stopped existing in 2018.
430
+ //
431
+ // Measured before changing: for canvas2D specifically this is inert,
432
+ // because Chromium never takes the LCD path on a canvas surface - the
433
+ // container returned grayscale edges (max channel delta 1, which is
434
+ // the pixel noise) under both modes. It is page text rasterisation
435
+ // and any screenshot of it that the striped mode would have reached.
436
+ // Corrected regardless: the JSON is read by operators as the
437
+ // description of the identity, and this half of it said pre-Mojave.
438
+ case 'apple_metal': return 'grayscale_aa_no_hinting';
439
+ case 'windows_d3d_nvidia':
440
+ case 'windows_d3d_amd':
441
+ case 'windows_d3d_intel':
442
+ return 'lcd_subpixel_full_hinting';
443
+ case 'linux_mesa_amd':
444
+ case 'linux_mesa_nvidia':
445
+ case 'linux_mesa_intel':
446
+ return 'rgb_subpixel_slight_hinting';
447
+ default:
448
+ return undefined;
449
+ }
450
+ })();
451
+ return textRenderingMode ? { textRenderingMode } : undefined;
452
+ }
453
+ /**
454
+ * Generate a FingerprintConfig JSON object from fingerprint-generator output.
455
+ *
456
+ * Composed from per-surface pure builders (navigator / webgl / webgpu / screen /
457
+ * locale / battery / network / audio / canvas). The narrow public signature is
458
+ * the module interface - the builders stay private so callers assemble the whole
459
+ * config in one call.
460
+ *
461
+ * @param fingerprint - BrowserFingerprintWithHeaders from fingerprint-generator
462
+ * @param sessionId - Session identifier used to derive the seed (proxy session ID, etc.)
463
+ * @param resolvedLocale - Pre-resolved locale/languages/timezone triple. When provided,
464
+ * these values win over anything derived from fingerprint-generator headers so that a
465
+ * user-supplied `locale: 'ko-KR'` coherently propagates to every locale surface
466
+ * (Accept-Language, navigator.language, Intl defaults, timezone).
467
+ */
468
+ export function generateFingerprintConfig(fingerprint, sessionId, resolvedLocale) {
469
+ const fp = fingerprint.fingerprint;
470
+ const { headers } = fingerprint;
471
+ const seed = deriveSeed(sessionId, fp.navigator?.userAgent ?? '');
472
+ const locale = buildLocaleSurface(headers, resolvedLocale, seed);
473
+ const nav = buildNavigatorSurface(fp, headers, seed, locale);
474
+ const webglSurface = buildWebglSurface(fp);
120
475
  const config = {
121
476
  version: 1,
122
477
  seed,
123
- brandName,
124
- ...(timezone && { timezone }),
125
- navigator: {
126
- platform, // legacy form: 'MacIntel' | 'Win32' | 'Linux x86_64'
127
- ...(navLanguage && { language: navLanguage }),
128
- ...(acceptLanguage && { languages: acceptLanguage }),
129
- hardwareConcurrency: fp.navigator?.hardwareConcurrency ?? 8,
130
- deviceMemory,
131
- userAgent,
132
- ...(uaBrands.length > 0 && {
133
- userAgentData: {
134
- brands: uaBrands,
135
- mobile: uaData?.mobile ?? false,
136
- platform: uaData?.platform ?? uaChPlatform,
137
- platformVersion: uaData?.platformVersion ?? '15.0.0',
138
- architecture: uaData?.architecture ?? 'x86',
139
- bitness: uaData?.bitness ?? '64',
140
- model: uaData?.model ?? '',
141
- uaFullVersion: uaData?.uaFullVersion ?? extractFullVersion(userAgent),
142
- fullVersionList: uaBrands,
143
- },
144
- }),
145
- },
146
- webgl: {
147
- vendor: webglVendor,
148
- renderer: webglRenderer,
149
- },
150
- screen: {
151
- width: screen?.width ?? 1920,
152
- height: screen?.height ?? 1080,
153
- availWidth: screen?.availWidth ?? screen?.width ?? 1920,
154
- availHeight: screen?.availHeight ?? (screen?.height ? screen.height - 40 : 1040),
155
- colorDepth,
156
- pixelRatio: screen?.devicePixelRatio ?? 1,
157
- },
158
- battery,
478
+ brandName: nav.brandName,
479
+ ...(locale.timezone && { timezone: locale.timezone }),
480
+ navigator: nav.navigator,
481
+ webgl: webglSurface.webgl,
482
+ screen: buildScreenSurface(fp),
483
+ // Battery - generate realistic values based on target platform.
484
+ // Uses UA-CH platform names ('Windows'|'macOS'|'Linux') for the desktop/mac checks.
485
+ battery: generateBatteryConfig(nav.uaChPlatform, seed),
159
486
  noise: {
160
487
  canvas: true,
161
488
  audio: true,
@@ -166,18 +493,19 @@ export function generateFingerprintConfig(fingerprint, sessionId, resolvedLocale
166
493
  performanceNowResolutionMs: 1,
167
494
  },
168
495
  };
169
- // WebGPU — from explicit webgpu field on fingerprint (non-Apify profiles), or
170
- // derived from WebGL vendor as a fallback (Apify fingerprints have no webgpu data).
171
- const webgpuData = fp.webgpu;
172
- const derivedWebGPUVendor = webgpuData?.vendor ?? deriveWebGPUVendorFromWebGL(webglVendor);
173
- if (derivedWebGPUVendor) {
174
- config.webgpu = {
175
- vendor: derivedWebGPUVendor,
176
- architecture: webgpuData?.architecture ?? '',
177
- device: webgpuData?.device ?? '',
178
- description: webgpuData?.description ?? '',
179
- };
180
- }
496
+ const webgpu = buildWebgpuSurface(fp, webglSurface.vendor);
497
+ if (webgpu)
498
+ config.webgpu = webgpu;
499
+ // navigator.connection - prevent datacenter rtt/downlink leak. Same seed
500
+ // → same values, so Mac and Linux Docker hosts running the same profile
501
+ // report the same connection metrics.
502
+ config.network = deriveNetwork(seed);
503
+ // AudioContext.sampleRate hint matched to platform. Consumed by the C++
504
+ // base_audio_context.h getter when the binding-layer override lands.
505
+ config.audio = { sampleRate: deriveAudioSampleRate(nav.platform) };
506
+ const canvas = buildCanvasSurface(webglSurface.family);
507
+ if (canvas)
508
+ config.canvas = canvas;
181
509
  return config;
182
510
  }
183
511
  /**
@@ -199,33 +527,10 @@ export async function cleanupTempFingerprintConfig(filePath) {
199
527
  await fs.unlink(filePath);
200
528
  }
201
529
  catch {
202
- // Non-fatal — temp file will be cleaned by OS eventually
530
+ // Non-fatal - temp file will be cleaned by OS eventually
203
531
  }
204
532
  }
205
533
  // ─── Helpers ──────────────────────────────────────────────────────────────────
206
- /**
207
- * Clamp a raw device-memory-in-GB value to the buckets required by the
208
- * Device Memory API spec (https://www.w3.org/TR/device-memory/). Chrome
209
- * always quantizes to {0.25, 0.5, 1, 2, 4, 8}. Returning anything outside
210
- * this set — especially the real value on >8 GB machines — is an instant
211
- * anti-bot detection signal.
212
- *
213
- * Rule (per spec): the returned value is the closest bucket that is less
214
- * than or equal to the actual value, capped at 8.
215
- */
216
- function clampDeviceMemoryToSpecBuckets(raw) {
217
- const buckets = [0.25, 0.5, 1, 2, 4, 8];
218
- if (!Number.isFinite(raw) || raw <= 0)
219
- return 8;
220
- if (raw >= 8)
221
- return 8;
222
- let bucket = buckets[0];
223
- for (const b of buckets) {
224
- if (b <= raw)
225
- bucket = b;
226
- }
227
- return bucket;
228
- }
229
534
  /** Extract full Chrome version string from User-Agent (e.g. "Chrome/136.0.7103.0") */
230
535
  function extractFullVersion(userAgent) {
231
536
  const match = userAgent.match(/Chrome\/(\d+\.\d+\.\d+\.\d+)/);
@@ -304,7 +609,7 @@ function seedRng(seed) {
304
609
  return () => {
305
610
  s = (s + 0x6D2B79F5) | 0;
306
611
  let t = Math.imul(s ^ (s >>> 15), 1 | s);
307
- t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
612
+ t ^= t + Math.imul(t ^ (t >>> 7), 61 | t);
308
613
  return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
309
614
  };
310
615
  }