@mercuryo-ai/agentbrowse 0.2.50

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 (301) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +335 -0
  3. package/dist/assistive-runtime.d.ts +110 -0
  4. package/dist/assistive-runtime.d.ts.map +1 -0
  5. package/dist/assistive-runtime.js +79 -0
  6. package/dist/assistive-runtime.test-support.d.ts +7 -0
  7. package/dist/assistive-runtime.test-support.d.ts.map +1 -0
  8. package/dist/assistive-runtime.test-support.js +106 -0
  9. package/dist/assistive-stagehand.d.ts +12 -0
  10. package/dist/assistive-stagehand.d.ts.map +1 -0
  11. package/dist/assistive-stagehand.js +10 -0
  12. package/dist/browser-session-state.d.ts +95 -0
  13. package/dist/browser-session-state.d.ts.map +1 -0
  14. package/dist/browser-session-state.js +279 -0
  15. package/dist/client-bindings.d.ts +10 -0
  16. package/dist/client-bindings.d.ts.map +1 -0
  17. package/dist/client-bindings.js +18 -0
  18. package/dist/client.d.ts +49 -0
  19. package/dist/client.d.ts.map +1 -0
  20. package/dist/client.js +63 -0
  21. package/dist/command-api-tracing.d.ts +20 -0
  22. package/dist/command-api-tracing.d.ts.map +1 -0
  23. package/dist/command-api-tracing.js +149 -0
  24. package/dist/command-name.d.ts +3 -0
  25. package/dist/command-name.d.ts.map +1 -0
  26. package/dist/command-name.js +11 -0
  27. package/dist/commands/act.d.ts +43 -0
  28. package/dist/commands/act.d.ts.map +1 -0
  29. package/dist/commands/act.js +1107 -0
  30. package/dist/commands/action-acceptance.d.ts +93 -0
  31. package/dist/commands/action-acceptance.d.ts.map +1 -0
  32. package/dist/commands/action-acceptance.js +1938 -0
  33. package/dist/commands/action-artifacts.d.ts +33 -0
  34. package/dist/commands/action-artifacts.d.ts.map +1 -0
  35. package/dist/commands/action-artifacts.js +104 -0
  36. package/dist/commands/action-execution-guards.d.ts +5 -0
  37. package/dist/commands/action-execution-guards.d.ts.map +1 -0
  38. package/dist/commands/action-execution-guards.js +3 -0
  39. package/dist/commands/action-executor-helpers.d.ts +21 -0
  40. package/dist/commands/action-executor-helpers.d.ts.map +1 -0
  41. package/dist/commands/action-executor-helpers.js +265 -0
  42. package/dist/commands/action-executor.d.ts +14 -0
  43. package/dist/commands/action-executor.d.ts.map +1 -0
  44. package/dist/commands/action-executor.js +46 -0
  45. package/dist/commands/action-fallbacks.d.ts +6 -0
  46. package/dist/commands/action-fallbacks.d.ts.map +1 -0
  47. package/dist/commands/action-fallbacks.js +43 -0
  48. package/dist/commands/action-result-resolution.d.ts +17 -0
  49. package/dist/commands/action-result-resolution.d.ts.map +1 -0
  50. package/dist/commands/action-result-resolution.js +132 -0
  51. package/dist/commands/action-value-projection.d.ts +32 -0
  52. package/dist/commands/action-value-projection.d.ts.map +1 -0
  53. package/dist/commands/action-value-projection.js +151 -0
  54. package/dist/commands/attach.d.ts +41 -0
  55. package/dist/commands/attach.d.ts.map +1 -0
  56. package/dist/commands/attach.js +103 -0
  57. package/dist/commands/browse-actions.d.ts +4 -0
  58. package/dist/commands/browse-actions.d.ts.map +1 -0
  59. package/dist/commands/browse-actions.js +4 -0
  60. package/dist/commands/browser-status.d.ts +57 -0
  61. package/dist/commands/browser-status.d.ts.map +1 -0
  62. package/dist/commands/browser-status.js +243 -0
  63. package/dist/commands/click-action-executor.d.ts +12 -0
  64. package/dist/commands/click-action-executor.d.ts.map +1 -0
  65. package/dist/commands/click-action-executor.js +111 -0
  66. package/dist/commands/click-activation-policy.d.ts +5 -0
  67. package/dist/commands/click-activation-policy.d.ts.map +1 -0
  68. package/dist/commands/click-activation-policy.js +13 -0
  69. package/dist/commands/close.d.ts +26 -0
  70. package/dist/commands/close.d.ts.map +1 -0
  71. package/dist/commands/close.js +124 -0
  72. package/dist/commands/datepicker-action-executor.d.ts +12 -0
  73. package/dist/commands/datepicker-action-executor.d.ts.map +1 -0
  74. package/dist/commands/datepicker-action-executor.js +218 -0
  75. package/dist/commands/descriptor-validation.d.ts +27 -0
  76. package/dist/commands/descriptor-validation.d.ts.map +1 -0
  77. package/dist/commands/descriptor-validation.js +192 -0
  78. package/dist/commands/extract-scope-resolution.d.ts +20 -0
  79. package/dist/commands/extract-scope-resolution.d.ts.map +1 -0
  80. package/dist/commands/extract-scope-resolution.js +109 -0
  81. package/dist/commands/extract-scoped-dialog-text.d.ts +3 -0
  82. package/dist/commands/extract-scoped-dialog-text.d.ts.map +1 -0
  83. package/dist/commands/extract-scoped-dialog-text.js +210 -0
  84. package/dist/commands/extract-snapshot-sanitizer.d.ts +5 -0
  85. package/dist/commands/extract-snapshot-sanitizer.d.ts.map +1 -0
  86. package/dist/commands/extract-snapshot-sanitizer.js +98 -0
  87. package/dist/commands/extract-stagehand-executor.d.ts +17 -0
  88. package/dist/commands/extract-stagehand-executor.d.ts.map +1 -0
  89. package/dist/commands/extract-stagehand-executor.js +112 -0
  90. package/dist/commands/extract.d.ts +57 -0
  91. package/dist/commands/extract.d.ts.map +1 -0
  92. package/dist/commands/extract.js +668 -0
  93. package/dist/commands/interaction-kernel.d.ts +46 -0
  94. package/dist/commands/interaction-kernel.d.ts.map +1 -0
  95. package/dist/commands/interaction-kernel.js +215 -0
  96. package/dist/commands/launch.d.ts +41 -0
  97. package/dist/commands/launch.d.ts.map +1 -0
  98. package/dist/commands/launch.js +182 -0
  99. package/dist/commands/navigate.d.ts +31 -0
  100. package/dist/commands/navigate.d.ts.map +1 -0
  101. package/dist/commands/navigate.js +202 -0
  102. package/dist/commands/observe-accessibility.d.ts +22 -0
  103. package/dist/commands/observe-accessibility.d.ts.map +1 -0
  104. package/dist/commands/observe-accessibility.js +566 -0
  105. package/dist/commands/observe-display-label.d.ts +4 -0
  106. package/dist/commands/observe-display-label.d.ts.map +1 -0
  107. package/dist/commands/observe-display-label.js +26 -0
  108. package/dist/commands/observe-dom-label-contract.d.ts +2 -0
  109. package/dist/commands/observe-dom-label-contract.d.ts.map +1 -0
  110. package/dist/commands/observe-dom-label-contract.js +564 -0
  111. package/dist/commands/observe-fallback-semantics.d.ts +6 -0
  112. package/dist/commands/observe-fallback-semantics.d.ts.map +1 -0
  113. package/dist/commands/observe-fallback-semantics.js +86 -0
  114. package/dist/commands/observe-inventory.d.ts +149 -0
  115. package/dist/commands/observe-inventory.d.ts.map +1 -0
  116. package/dist/commands/observe-inventory.js +3545 -0
  117. package/dist/commands/observe-label-policy.d.ts +8 -0
  118. package/dist/commands/observe-label-policy.d.ts.map +1 -0
  119. package/dist/commands/observe-label-policy.js +21 -0
  120. package/dist/commands/observe-page-state.d.ts +11 -0
  121. package/dist/commands/observe-page-state.d.ts.map +1 -0
  122. package/dist/commands/observe-page-state.js +89 -0
  123. package/dist/commands/observe-persistence.d.ts +15 -0
  124. package/dist/commands/observe-persistence.d.ts.map +1 -0
  125. package/dist/commands/observe-persistence.js +238 -0
  126. package/dist/commands/observe-projection.d.ts +119 -0
  127. package/dist/commands/observe-projection.d.ts.map +1 -0
  128. package/dist/commands/observe-projection.js +726 -0
  129. package/dist/commands/observe-protected.d.ts +6 -0
  130. package/dist/commands/observe-protected.d.ts.map +1 -0
  131. package/dist/commands/observe-protected.js +31 -0
  132. package/dist/commands/observe-semantics.d.ts +10 -0
  133. package/dist/commands/observe-semantics.d.ts.map +1 -0
  134. package/dist/commands/observe-semantics.js +535 -0
  135. package/dist/commands/observe-signals.d.ts +48 -0
  136. package/dist/commands/observe-signals.d.ts.map +1 -0
  137. package/dist/commands/observe-signals.js +461 -0
  138. package/dist/commands/observe-stagehand.d.ts +49 -0
  139. package/dist/commands/observe-stagehand.d.ts.map +1 -0
  140. package/dist/commands/observe-stagehand.js +94 -0
  141. package/dist/commands/observe-surfaces.d.ts +11 -0
  142. package/dist/commands/observe-surfaces.d.ts.map +1 -0
  143. package/dist/commands/observe-surfaces.js +290 -0
  144. package/dist/commands/observe.d.ts +113 -0
  145. package/dist/commands/observe.d.ts.map +1 -0
  146. package/dist/commands/observe.js +556 -0
  147. package/dist/commands/screenshot.d.ts +37 -0
  148. package/dist/commands/screenshot.d.ts.map +1 -0
  149. package/dist/commands/screenshot.js +269 -0
  150. package/dist/commands/select-action-executor.d.ts +10 -0
  151. package/dist/commands/select-action-executor.d.ts.map +1 -0
  152. package/dist/commands/select-action-executor.js +156 -0
  153. package/dist/commands/semantic-observe-lexical.d.ts +31 -0
  154. package/dist/commands/semantic-observe-lexical.d.ts.map +1 -0
  155. package/dist/commands/semantic-observe-lexical.js +186 -0
  156. package/dist/commands/semantic-observe.d.ts +37 -0
  157. package/dist/commands/semantic-observe.d.ts.map +1 -0
  158. package/dist/commands/semantic-observe.js +1339 -0
  159. package/dist/commands/structured-grid-action-executor.d.ts +3 -0
  160. package/dist/commands/structured-grid-action-executor.d.ts.map +1 -0
  161. package/dist/commands/structured-grid-action-executor.js +4 -0
  162. package/dist/commands/target-resolution.d.ts +4 -0
  163. package/dist/commands/target-resolution.d.ts.map +1 -0
  164. package/dist/commands/target-resolution.js +33 -0
  165. package/dist/commands/text-input-action-executor.d.ts +5 -0
  166. package/dist/commands/text-input-action-executor.d.ts.map +1 -0
  167. package/dist/commands/text-input-action-executor.js +116 -0
  168. package/dist/commands/user-actionable.d.ts +4 -0
  169. package/dist/commands/user-actionable.d.ts.map +1 -0
  170. package/dist/commands/user-actionable.js +216 -0
  171. package/dist/control-semantics.d.ts +30 -0
  172. package/dist/control-semantics.d.ts.map +1 -0
  173. package/dist/control-semantics.js +419 -0
  174. package/dist/diagnostics.d.ts +132 -0
  175. package/dist/diagnostics.d.ts.map +1 -0
  176. package/dist/diagnostics.js +120 -0
  177. package/dist/index.d.ts +5 -0
  178. package/dist/index.d.ts.map +1 -0
  179. package/dist/index.js +350 -0
  180. package/dist/library.d.ts +17 -0
  181. package/dist/library.d.ts.map +1 -0
  182. package/dist/library.js +14 -0
  183. package/dist/output.d.ts +32 -0
  184. package/dist/output.d.ts.map +1 -0
  185. package/dist/output.js +33 -0
  186. package/dist/owned-browser.d.ts +12 -0
  187. package/dist/owned-browser.d.ts.map +1 -0
  188. package/dist/owned-browser.js +69 -0
  189. package/dist/owned-process.d.ts +19 -0
  190. package/dist/owned-process.d.ts.map +1 -0
  191. package/dist/owned-process.js +145 -0
  192. package/dist/playwright-runtime.d.ts +43 -0
  193. package/dist/playwright-runtime.d.ts.map +1 -0
  194. package/dist/playwright-runtime.js +339 -0
  195. package/dist/protected-fill-browser.d.ts +22 -0
  196. package/dist/protected-fill-browser.d.ts.map +1 -0
  197. package/dist/protected-fill-browser.js +52 -0
  198. package/dist/protected-fill.d.ts +82 -0
  199. package/dist/protected-fill.d.ts.map +1 -0
  200. package/dist/protected-fill.js +20 -0
  201. package/dist/runtime-metrics.d.ts +27 -0
  202. package/dist/runtime-metrics.d.ts.map +1 -0
  203. package/dist/runtime-metrics.js +66 -0
  204. package/dist/runtime-page-state.d.ts +11 -0
  205. package/dist/runtime-page-state.d.ts.map +1 -0
  206. package/dist/runtime-page-state.js +62 -0
  207. package/dist/runtime-protected-state.d.ts +14 -0
  208. package/dist/runtime-protected-state.d.ts.map +1 -0
  209. package/dist/runtime-protected-state.js +148 -0
  210. package/dist/runtime-resolution.d.ts +9 -0
  211. package/dist/runtime-resolution.d.ts.map +1 -0
  212. package/dist/runtime-resolution.js +19 -0
  213. package/dist/runtime-state.d.ts +251 -0
  214. package/dist/runtime-state.d.ts.map +1 -0
  215. package/dist/runtime-state.js +599 -0
  216. package/dist/secrets/catalog-applicability.d.ts +5 -0
  217. package/dist/secrets/catalog-applicability.d.ts.map +1 -0
  218. package/dist/secrets/catalog-applicability.js +59 -0
  219. package/dist/secrets/field-policy.d.ts +3 -0
  220. package/dist/secrets/field-policy.d.ts.map +1 -0
  221. package/dist/secrets/field-policy.js +3 -0
  222. package/dist/secrets/fill-ordering.d.ts +10 -0
  223. package/dist/secrets/fill-ordering.d.ts.map +1 -0
  224. package/dist/secrets/fill-ordering.js +41 -0
  225. package/dist/secrets/form-matcher.d.ts +60 -0
  226. package/dist/secrets/form-matcher.d.ts.map +1 -0
  227. package/dist/secrets/form-matcher.js +948 -0
  228. package/dist/secrets/protected-artifact-guard.d.ts +39 -0
  229. package/dist/secrets/protected-artifact-guard.d.ts.map +1 -0
  230. package/dist/secrets/protected-artifact-guard.js +44 -0
  231. package/dist/secrets/protected-bindings.d.ts +14 -0
  232. package/dist/secrets/protected-bindings.d.ts.map +1 -0
  233. package/dist/secrets/protected-bindings.js +29 -0
  234. package/dist/secrets/protected-exact-value-redaction.d.ts +14 -0
  235. package/dist/secrets/protected-exact-value-redaction.d.ts.map +1 -0
  236. package/dist/secrets/protected-exact-value-redaction.js +360 -0
  237. package/dist/secrets/protected-field-semantics.d.ts +9 -0
  238. package/dist/secrets/protected-field-semantics.d.ts.map +1 -0
  239. package/dist/secrets/protected-field-semantics.js +154 -0
  240. package/dist/secrets/protected-field-values.d.ts +15 -0
  241. package/dist/secrets/protected-field-values.d.ts.map +1 -0
  242. package/dist/secrets/protected-field-values.js +131 -0
  243. package/dist/secrets/protected-fill.d.ts +47 -0
  244. package/dist/secrets/protected-fill.d.ts.map +1 -0
  245. package/dist/secrets/protected-fill.js +446 -0
  246. package/dist/secrets/protected-value-adapters.d.ts +4 -0
  247. package/dist/secrets/protected-value-adapters.d.ts.map +1 -0
  248. package/dist/secrets/protected-value-adapters.js +118 -0
  249. package/dist/secrets/types.d.ts +70 -0
  250. package/dist/secrets/types.d.ts.map +1 -0
  251. package/dist/secrets/types.js +30 -0
  252. package/dist/session.d.ts +19 -0
  253. package/dist/session.d.ts.map +1 -0
  254. package/dist/session.js +120 -0
  255. package/dist/solver/browser-launcher.d.ts +14 -0
  256. package/dist/solver/browser-launcher.d.ts.map +1 -0
  257. package/dist/solver/browser-launcher.js +799 -0
  258. package/dist/solver/config.d.ts +18 -0
  259. package/dist/solver/config.d.ts.map +1 -0
  260. package/dist/solver/config.js +67 -0
  261. package/dist/solver/fingerprint.d.ts +9 -0
  262. package/dist/solver/fingerprint.d.ts.map +1 -0
  263. package/dist/solver/fingerprint.js +96 -0
  264. package/dist/solver/profile-manager.d.ts +8 -0
  265. package/dist/solver/profile-manager.d.ts.map +1 -0
  266. package/dist/solver/profile-manager.js +74 -0
  267. package/dist/solver/turnstile-challenge.d.ts +3 -0
  268. package/dist/solver/turnstile-challenge.d.ts.map +1 -0
  269. package/dist/solver/turnstile-challenge.js +173 -0
  270. package/dist/solver/types.d.ts +67 -0
  271. package/dist/solver/types.d.ts.map +1 -0
  272. package/dist/solver/types.js +1 -0
  273. package/dist/stagehand-runtime.d.ts +4 -0
  274. package/dist/stagehand-runtime.d.ts.map +1 -0
  275. package/dist/stagehand-runtime.js +10 -0
  276. package/dist/stagehand.d.ts +15 -0
  277. package/dist/stagehand.d.ts.map +1 -0
  278. package/dist/stagehand.js +19 -0
  279. package/dist/testing.d.ts +5 -0
  280. package/dist/testing.d.ts.map +1 -0
  281. package/dist/testing.js +4 -0
  282. package/dist/update-check.d.ts +14 -0
  283. package/dist/update-check.d.ts.map +1 -0
  284. package/dist/update-check.js +182 -0
  285. package/dist/workflow-session-state.d.ts +30 -0
  286. package/dist/workflow-session-state.d.ts.map +1 -0
  287. package/dist/workflow-session-state.js +74 -0
  288. package/docs/README.md +25 -0
  289. package/docs/api-reference.md +242 -0
  290. package/docs/assistive-runtime.md +148 -0
  291. package/docs/configuration.md +287 -0
  292. package/docs/getting-started.md +237 -0
  293. package/docs/integration-checklist.md +36 -0
  294. package/docs/protected-fill.md +112 -0
  295. package/docs/testing.md +50 -0
  296. package/docs/troubleshooting.md +71 -0
  297. package/examples/README.md +18 -0
  298. package/examples/attach.ts +27 -0
  299. package/examples/basic.ts +36 -0
  300. package/examples/extract.ts +50 -0
  301. package/package.json +83 -0
@@ -0,0 +1,799 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { existsSync, mkdirSync, readFileSync } from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { connect as connectPuppeteer } from 'puppeteer';
6
+ import puppeteerExtra from 'puppeteer-extra';
7
+ import StealthPlugin from 'puppeteer-extra-plugin-stealth';
8
+ import { buildTurnstileApiShimSource, isTurnstileApiRequest } from './turnstile-challenge.js';
9
+ const enhancedPuppeteer = puppeteerExtra;
10
+ const solverStealthPlugin = StealthPlugin();
11
+ // Some iframe-backed checkout flows break when this evasion runs on a connected real Chrome.
12
+ solverStealthPlugin.enabledEvasions.delete('iframe.contentWindow');
13
+ // We already pin the browser UA at launch time; this evasion races popup teardown on CI.
14
+ solverStealthPlugin.enabledEvasions.delete('user-agent-override');
15
+ enhancedPuppeteer.use(solverStealthPlugin);
16
+ const AUTO_CDP_PORT = 0;
17
+ const CDP_DISCOVERY_TIMEOUT_MS = 30_000;
18
+ const CDP_DISCOVERY_INTERVAL_MS = 500;
19
+ const BROWSER_CLOSE_TIMEOUT_MS = 1_000;
20
+ const EXTRA_PAGE_CLOSE_TIMEOUT_MS = 250;
21
+ const INTERCEPTED_PAGES = new WeakSet();
22
+ const LINUX_CI_CHROME_ARGS = [
23
+ '--no-sandbox',
24
+ '--disable-setuid-sandbox',
25
+ '--disable-dev-shm-usage',
26
+ ];
27
+ const MAC_CHROME_ARGS = ['--use-mock-keychain'];
28
+ const CHROME_PATHS = [
29
+ '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
30
+ '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
31
+ '/Applications/Chromium.app/Contents/MacOS/Chromium',
32
+ '/usr/bin/google-chrome',
33
+ '/usr/bin/google-chrome-stable',
34
+ '/usr/bin/chromium-browser',
35
+ '/usr/bin/chromium',
36
+ '/snap/bin/chromium',
37
+ ];
38
+ export async function launchSolver(profile, opts) {
39
+ const fp = withWindowSize(profile.fingerprint, opts?.windowSize);
40
+ const cdpPort = opts?.cdpPort ?? AUTO_CDP_PORT;
41
+ const executablePath = resolveChromeExecutable(opts?.executablePath);
42
+ const chromeProcess = spawnChromeProcess(executablePath, profile, fp, cdpPort, opts?.windowSize, opts?.headless, undefined);
43
+ try {
44
+ const cdpUrl = await discoverCdpUrl({
45
+ requestedPort: opts?.cdpPort,
46
+ userDataDir: profile.userDataDir,
47
+ chromeProcess,
48
+ });
49
+ if (!cdpUrl) {
50
+ throw buildCdpDiscoveryError(chromeProcess, opts?.cdpPort, profile.userDataDir);
51
+ }
52
+ const browser = await connectToBrowser(cdpUrl, opts?.stealth);
53
+ let page;
54
+ if (opts?.url) {
55
+ page = await createConfiguredPage(browser, fp);
56
+ page = await navigateConfiguredPage(browser, page, fp, opts.url);
57
+ }
58
+ else {
59
+ page = await createConfiguredPage(browser, fp);
60
+ }
61
+ await closeLaunchLeftoverPages(browser, page);
62
+ return {
63
+ browser,
64
+ page,
65
+ cdpUrl,
66
+ pid: chromeProcess.pid,
67
+ profile,
68
+ close: async () => {
69
+ try {
70
+ await closeBrowserWithinTimeout(browser, BROWSER_CLOSE_TIMEOUT_MS);
71
+ }
72
+ finally {
73
+ terminateProcessGroup(chromeProcess.pid);
74
+ }
75
+ },
76
+ disconnect: async () => {
77
+ await browser.disconnect();
78
+ },
79
+ };
80
+ }
81
+ catch (error) {
82
+ terminateProcessGroup(chromeProcess.pid);
83
+ throw error;
84
+ }
85
+ }
86
+ async function connectToBrowser(browserWSEndpoint, stealth) {
87
+ if (stealth === false) {
88
+ return connectPuppeteer({ browserWSEndpoint });
89
+ }
90
+ return enhancedPuppeteer.connect({ browserWSEndpoint });
91
+ }
92
+ async function discoverCdpUrl(options) {
93
+ const deadline = Date.now() + CDP_DISCOVERY_TIMEOUT_MS;
94
+ const activePortPath = path.join(options.userDataDir, 'DevToolsActivePort');
95
+ while (Date.now() < deadline) {
96
+ if (typeof options.requestedPort === 'number') {
97
+ const cdpUrl = await discoverCdpUrlOnPort(options.requestedPort);
98
+ if (cdpUrl) {
99
+ return cdpUrl;
100
+ }
101
+ }
102
+ else {
103
+ const activePort = readDevToolsActivePort(activePortPath);
104
+ const discoveredViaActivePort = await discoverCdpUrlFromActivePort(activePort);
105
+ if (discoveredViaActivePort) {
106
+ return discoveredViaActivePort;
107
+ }
108
+ }
109
+ if (typeof options.chromeProcess?.exitCode === 'number' || options.chromeProcess?.signalCode) {
110
+ break;
111
+ }
112
+ await sleep(CDP_DISCOVERY_INTERVAL_MS);
113
+ }
114
+ return null;
115
+ }
116
+ async function closeBrowserWithinTimeout(browser, timeoutMs) {
117
+ let timeoutId;
118
+ await Promise.race([
119
+ // Prefer Browser.close so puppeteer-extra can finish target shutdown hooks
120
+ // before we force-kill the owned Chrome process on slow CI runners.
121
+ browser
122
+ .close()
123
+ .catch(() => { }),
124
+ new Promise((resolve) => {
125
+ timeoutId = setTimeout(resolve, timeoutMs);
126
+ }),
127
+ ]);
128
+ if (timeoutId) {
129
+ clearTimeout(timeoutId);
130
+ }
131
+ }
132
+ async function closeLaunchLeftoverPages(browser, activePage) {
133
+ const allPages = await browser.pages();
134
+ for (const candidate of allPages) {
135
+ if (candidate === activePage || !isCloseableLaunchLeftover(candidate.url())) {
136
+ continue;
137
+ }
138
+ await closePageWithinTimeout(candidate, EXTRA_PAGE_CLOSE_TIMEOUT_MS);
139
+ }
140
+ }
141
+ function isCloseableLaunchLeftover(url) {
142
+ const normalized = url.trim().toLowerCase();
143
+ return (normalized.length === 0 ||
144
+ normalized === 'about:blank' ||
145
+ normalized === 'chrome://newtab/' ||
146
+ normalized === 'chrome://new-tab-page/' ||
147
+ normalized === 'chrome://newtab');
148
+ }
149
+ async function closePageWithinTimeout(page, timeoutMs) {
150
+ let timeoutId;
151
+ await Promise.race([
152
+ page.close().catch(() => undefined),
153
+ new Promise((resolve) => {
154
+ timeoutId = setTimeout(resolve, timeoutMs);
155
+ }),
156
+ ]);
157
+ if (timeoutId) {
158
+ clearTimeout(timeoutId);
159
+ }
160
+ }
161
+ async function discoverCdpUrlOnPort(port) {
162
+ try {
163
+ const res = await fetch(`http://127.0.0.1:${port}/json/version`);
164
+ if (!res.ok) {
165
+ return null;
166
+ }
167
+ const json = (await res.json());
168
+ return json.webSocketDebuggerUrl ?? null;
169
+ }
170
+ catch {
171
+ return null;
172
+ }
173
+ }
174
+ async function discoverCdpUrlFromActivePort(activePort) {
175
+ if (!activePort) {
176
+ return null;
177
+ }
178
+ const candidatePorts = new Set();
179
+ if (activePort.browserWSEndpoint) {
180
+ const wsPort = portFromBrowserWSEndpoint(activePort.browserWSEndpoint);
181
+ if (wsPort) {
182
+ candidatePorts.add(wsPort);
183
+ }
184
+ }
185
+ if (activePort.port > 0) {
186
+ candidatePorts.add(activePort.port);
187
+ }
188
+ for (const port of candidatePorts) {
189
+ const cdpUrl = await discoverCdpUrlOnPort(port);
190
+ if (cdpUrl) {
191
+ return cdpUrl;
192
+ }
193
+ }
194
+ return null;
195
+ }
196
+ function portFromBrowserWSEndpoint(browserWSEndpoint) {
197
+ try {
198
+ const url = new URL(browserWSEndpoint);
199
+ const port = Number(url.port);
200
+ return Number.isFinite(port) && port > 0 ? port : null;
201
+ }
202
+ catch {
203
+ return null;
204
+ }
205
+ }
206
+ function readDevToolsActivePort(activePortPath) {
207
+ if (!existsSync(activePortPath)) {
208
+ return null;
209
+ }
210
+ try {
211
+ const raw = readFileSync(activePortPath, 'utf-8').trim();
212
+ if (!raw) {
213
+ return null;
214
+ }
215
+ const [portLine = '', wsPathLine = ''] = raw.split(/\r?\n/, 2);
216
+ const port = Number(portLine.trim());
217
+ if (!Number.isFinite(port) || port <= 0) {
218
+ return null;
219
+ }
220
+ const wsPath = wsPathLine.trim();
221
+ return {
222
+ port,
223
+ browserWSEndpoint: wsPath
224
+ ? wsPath.startsWith('ws://')
225
+ ? wsPath
226
+ : `ws://127.0.0.1:${port}${wsPath.startsWith('/') ? wsPath : `/${wsPath}`}`
227
+ : undefined,
228
+ };
229
+ }
230
+ catch {
231
+ return null;
232
+ }
233
+ }
234
+ function buildCdpDiscoveryError(chromeProcess, requestedPort, userDataDir) {
235
+ const details = [`pid ${chromeProcess.pid ?? 'unknown'}`];
236
+ if (typeof chromeProcess.exitCode === 'number') {
237
+ details.push(`exitCode ${chromeProcess.exitCode}`);
238
+ }
239
+ if (chromeProcess.signalCode) {
240
+ details.push(`signal ${chromeProcess.signalCode}`);
241
+ }
242
+ if (typeof requestedPort === 'number') {
243
+ return new Error(`Chrome launched but CDP not reachable on port ${requestedPort} within ${CDP_DISCOVERY_TIMEOUT_MS}ms (${details.join(', ')}).`);
244
+ }
245
+ return new Error(`Chrome launched but CDP not reachable via auto discovery within ${CDP_DISCOVERY_TIMEOUT_MS}ms (${details.join(', ')}). Checked ${path.join(userDataDir, 'DevToolsActivePort')}.`);
246
+ }
247
+ async function createConfiguredPage(browser, fp) {
248
+ const page = await browser.newPage();
249
+ await installTurnstileApiInterception(page);
250
+ await applyFingerprint(page, fp);
251
+ if (fp.proxy?.username && fp.proxy.password) {
252
+ await page.authenticate({
253
+ username: fp.proxy.username,
254
+ password: fp.proxy.password,
255
+ });
256
+ }
257
+ return page;
258
+ }
259
+ async function installTurnstileApiInterception(page) {
260
+ if (INTERCEPTED_PAGES.has(page)) {
261
+ return;
262
+ }
263
+ await page.setRequestInterception(true);
264
+ page.on('request', (request) => {
265
+ void (async () => {
266
+ try {
267
+ if (isTurnstileApiRequest(request.url())) {
268
+ await request.respond({
269
+ status: 200,
270
+ contentType: 'application/javascript',
271
+ headers: {
272
+ 'access-control-allow-origin': '*',
273
+ 'cross-origin-resource-policy': 'cross-origin',
274
+ 'cache-control': 'no-store',
275
+ },
276
+ body: buildTurnstileApiShimSource(request.url()),
277
+ });
278
+ return;
279
+ }
280
+ await request.continue();
281
+ }
282
+ catch {
283
+ try {
284
+ await request.continue();
285
+ }
286
+ catch {
287
+ // Ignore navigations or already-handled requests.
288
+ }
289
+ }
290
+ })();
291
+ });
292
+ INTERCEPTED_PAGES.add(page);
293
+ }
294
+ async function navigateConfiguredPage(browser, page, fp, url) {
295
+ try {
296
+ await page.goto(url, { waitUntil: 'domcontentloaded' });
297
+ return page;
298
+ }
299
+ catch (err) {
300
+ if (!isDetachedFrameError(err)) {
301
+ throw err;
302
+ }
303
+ }
304
+ // Chrome may recycle the initial page during startup; retry on a fresh page once.
305
+ try {
306
+ if (!page.isClosed()) {
307
+ await page.close({ runBeforeUnload: false });
308
+ }
309
+ }
310
+ catch {
311
+ // Ignore close failures for detached/closed pages.
312
+ }
313
+ const retryPage = await createConfiguredPage(browser, fp);
314
+ await retryPage.goto(url, { waitUntil: 'domcontentloaded' });
315
+ return retryPage;
316
+ }
317
+ function isDetachedFrameError(err) {
318
+ const message = err instanceof Error ? err.message : String(err);
319
+ return message.toLowerCase().includes('detached frame');
320
+ }
321
+ function resolveChromeExecutable(explicitPath) {
322
+ if (explicitPath) {
323
+ if (!existsSync(explicitPath)) {
324
+ throw new Error(`Chrome executable does not exist: ${explicitPath}`);
325
+ }
326
+ return explicitPath;
327
+ }
328
+ if (process.env.CHROME_PATH && existsSync(process.env.CHROME_PATH)) {
329
+ return process.env.CHROME_PATH;
330
+ }
331
+ for (const chromePath of CHROME_PATHS) {
332
+ if (existsSync(chromePath))
333
+ return chromePath;
334
+ }
335
+ throw new Error(`Chrome executable not found. Set CHROME_PATH or pass executablePath explicitly. Checked: ${CHROME_PATHS.join(', ')}`);
336
+ }
337
+ function spawnChromeProcess(executablePath, profile, fp, cdpPort, windowSize, headless, url) {
338
+ mkdirSync(profile.userDataDir, { recursive: true });
339
+ const width = windowSize?.width ?? fp.viewport.width;
340
+ const height = windowSize?.height ?? fp.viewport.height;
341
+ const args = [
342
+ `--remote-debugging-port=${cdpPort}`,
343
+ '--remote-debugging-address=127.0.0.1',
344
+ `--user-data-dir=${profile.userDataDir}`,
345
+ `--window-size=${width},${height}`,
346
+ `--user-agent=${fp.userAgent}`,
347
+ '--disable-blink-features=AutomationControlled',
348
+ '--no-first-run',
349
+ '--no-default-browser-check',
350
+ ];
351
+ args.push(...chromeArgsForEnvironment());
352
+ if (headless) {
353
+ args.push('--headless=new');
354
+ }
355
+ if (fp.proxy?.server) {
356
+ args.push(`--proxy-server=${fp.proxy.server}`);
357
+ }
358
+ if (url) {
359
+ args.push(url);
360
+ }
361
+ const proc = spawn(executablePath, args, {
362
+ stdio: 'ignore',
363
+ detached: true,
364
+ env: process.env,
365
+ cwd: path.join(os.homedir()),
366
+ });
367
+ proc.unref();
368
+ if (!proc.pid) {
369
+ throw new Error('Failed to launch Chrome process');
370
+ }
371
+ return proc;
372
+ }
373
+ export function chromeArgsForEnvironment(platform = process.platform, env = process.env) {
374
+ const isLinuxCi = platform === 'linux' && (env.CI === 'true' || env.GITHUB_ACTIONS === 'true');
375
+ if (platform === 'darwin') {
376
+ return [...MAC_CHROME_ARGS];
377
+ }
378
+ return isLinuxCi ? [...LINUX_CI_CHROME_ARGS] : [];
379
+ }
380
+ function terminateProcessGroup(pid) {
381
+ try {
382
+ process.kill(-pid, 'SIGTERM');
383
+ return;
384
+ }
385
+ catch {
386
+ // Fall back to killing a single process.
387
+ }
388
+ try {
389
+ process.kill(pid, 'SIGTERM');
390
+ }
391
+ catch {
392
+ // Ignore already terminated process.
393
+ }
394
+ }
395
+ function sleep(ms) {
396
+ return new Promise((resolve) => setTimeout(resolve, ms));
397
+ }
398
+ function withWindowSize(fingerprint, windowSize) {
399
+ if (!windowSize)
400
+ return fingerprint;
401
+ const width = Math.max(800, Math.floor(windowSize.width));
402
+ const height = Math.max(600, Math.floor(windowSize.height));
403
+ const viewportHeight = Math.max(500, Math.min(height - 80, height));
404
+ return {
405
+ ...fingerprint,
406
+ viewport: {
407
+ width,
408
+ height: viewportHeight,
409
+ },
410
+ screen: {
411
+ ...fingerprint.screen,
412
+ width,
413
+ height,
414
+ },
415
+ };
416
+ }
417
+ async function applyFingerprint(page, fp) {
418
+ const client = await page.createCDPSession();
419
+ await client.send('Network.setUserAgentOverride', {
420
+ userAgent: fp.userAgent,
421
+ platform: fp.platform,
422
+ acceptLanguage: fp.locale,
423
+ });
424
+ await page.setViewport({
425
+ width: fp.viewport.width,
426
+ height: fp.viewport.height,
427
+ });
428
+ await page.emulateTimezone(fp.timezone);
429
+ await page.evaluateOnNewDocument((fingerprint) => {
430
+ const win = window;
431
+ const callbacksKey = '__agentbrowseTurnstileCallbacks';
432
+ const challengesKey = '__agentbrowseTurnstileChallenges';
433
+ const stateKey = '__agentbrowseTurnstileState';
434
+ if (!Array.isArray(win[challengesKey])) {
435
+ win[challengesKey] = [];
436
+ }
437
+ if (!win[callbacksKey] || typeof win[callbacksKey] !== 'object') {
438
+ win[callbacksKey] = {};
439
+ }
440
+ if (!win[stateKey] || typeof win[stateKey] !== 'object') {
441
+ win[stateKey] = { nextCallbackId: 1 };
442
+ }
443
+ let turnstileValue = win.turnstile;
444
+ if (turnstileValue && typeof turnstileValue === 'object') {
445
+ const turnstile = turnstileValue;
446
+ if (typeof turnstile.render === 'function' && !turnstile.__agentbrowseWrapped) {
447
+ const originalRender = turnstile.render.bind(turnstile);
448
+ turnstile.render = (container, options) => {
449
+ const state = win[stateKey];
450
+ const callbacks = win[callbacksKey];
451
+ const challenges = win[challengesKey];
452
+ const callbackId = typeof options?.callback === 'function'
453
+ ? `cf-turnstile-callback-${state.nextCallbackId ?? 1}`
454
+ : '';
455
+ if (callbackId) {
456
+ callbacks[callbackId] = options.callback;
457
+ state.nextCallbackId = (state.nextCallbackId ?? 1) + 1;
458
+ }
459
+ const siteKey = typeof options?.sitekey === 'string'
460
+ ? options.sitekey
461
+ : typeof options?.siteKey === 'string'
462
+ ? options.siteKey
463
+ : '';
464
+ if (siteKey) {
465
+ challenges.push({
466
+ siteKey,
467
+ action: typeof options?.action === 'string' ? options.action : '',
468
+ cData: typeof options?.cData === 'string' ? options.cData : '',
469
+ chlPageData: typeof options?.chlPageData === 'string' ? options.chlPageData : '',
470
+ callbackId,
471
+ userAgent: navigator.userAgent,
472
+ });
473
+ }
474
+ return originalRender(container, options);
475
+ };
476
+ turnstile.__agentbrowseWrapped = true;
477
+ }
478
+ else {
479
+ let renderValue = turnstile.render;
480
+ try {
481
+ Object.defineProperty(turnstile, 'render', {
482
+ configurable: true,
483
+ enumerable: true,
484
+ get: () => renderValue,
485
+ set: (value) => {
486
+ if (typeof value !== 'function') {
487
+ renderValue = value;
488
+ return;
489
+ }
490
+ const originalRender = value.bind(turnstile);
491
+ renderValue = (container, options) => {
492
+ const state = win[stateKey];
493
+ const callbacks = win[callbacksKey];
494
+ const challenges = win[challengesKey];
495
+ const callbackId = typeof options?.callback === 'function'
496
+ ? `cf-turnstile-callback-${state.nextCallbackId ?? 1}`
497
+ : '';
498
+ if (callbackId) {
499
+ callbacks[callbackId] = options.callback;
500
+ state.nextCallbackId = (state.nextCallbackId ?? 1) + 1;
501
+ }
502
+ const siteKey = typeof options?.sitekey === 'string'
503
+ ? options.sitekey
504
+ : typeof options?.siteKey === 'string'
505
+ ? options.siteKey
506
+ : '';
507
+ if (siteKey) {
508
+ challenges.push({
509
+ siteKey,
510
+ action: typeof options?.action === 'string' ? options.action : '',
511
+ cData: typeof options?.cData === 'string' ? options.cData : '',
512
+ chlPageData: typeof options?.chlPageData === 'string' ? options.chlPageData : '',
513
+ callbackId,
514
+ userAgent: navigator.userAgent,
515
+ });
516
+ }
517
+ return originalRender(container, options);
518
+ };
519
+ turnstile.__agentbrowseWrapped = true;
520
+ },
521
+ });
522
+ }
523
+ catch {
524
+ // Ignore non-configurable render properties.
525
+ }
526
+ }
527
+ }
528
+ try {
529
+ Object.defineProperty(win, 'turnstile', {
530
+ configurable: true,
531
+ enumerable: true,
532
+ get: () => turnstileValue,
533
+ set: (value) => {
534
+ turnstileValue = value;
535
+ if (!value || typeof value !== 'object')
536
+ return;
537
+ const turnstile = value;
538
+ if (typeof turnstile.render !== 'function' || turnstile.__agentbrowseWrapped) {
539
+ let renderValue = turnstile.render;
540
+ try {
541
+ Object.defineProperty(turnstile, 'render', {
542
+ configurable: true,
543
+ enumerable: true,
544
+ get: () => renderValue,
545
+ set: (nextValue) => {
546
+ if (typeof nextValue !== 'function') {
547
+ renderValue = nextValue;
548
+ return;
549
+ }
550
+ const originalRender = nextValue.bind(turnstile);
551
+ renderValue = (container, options) => {
552
+ const state = win[stateKey];
553
+ const callbacks = win[callbacksKey];
554
+ const challenges = win[challengesKey];
555
+ const callbackId = typeof options?.callback === 'function'
556
+ ? `cf-turnstile-callback-${state.nextCallbackId ?? 1}`
557
+ : '';
558
+ if (callbackId) {
559
+ callbacks[callbackId] = options.callback;
560
+ state.nextCallbackId = (state.nextCallbackId ?? 1) + 1;
561
+ }
562
+ const siteKey = typeof options?.sitekey === 'string'
563
+ ? options.sitekey
564
+ : typeof options?.siteKey === 'string'
565
+ ? options.siteKey
566
+ : '';
567
+ if (siteKey) {
568
+ challenges.push({
569
+ siteKey,
570
+ action: typeof options?.action === 'string' ? options.action : '',
571
+ cData: typeof options?.cData === 'string' ? options.cData : '',
572
+ chlPageData: typeof options?.chlPageData === 'string' ? options.chlPageData : '',
573
+ callbackId,
574
+ userAgent: navigator.userAgent,
575
+ });
576
+ }
577
+ return originalRender(container, options);
578
+ };
579
+ turnstile.__agentbrowseWrapped = true;
580
+ },
581
+ });
582
+ }
583
+ catch {
584
+ // Ignore non-configurable render properties.
585
+ }
586
+ return;
587
+ }
588
+ const originalRender = turnstile.render.bind(turnstile);
589
+ turnstile.render = (container, options) => {
590
+ const state = win[stateKey];
591
+ const callbacks = win[callbacksKey];
592
+ const challenges = win[challengesKey];
593
+ const callbackId = typeof options?.callback === 'function'
594
+ ? `cf-turnstile-callback-${state.nextCallbackId ?? 1}`
595
+ : '';
596
+ if (callbackId) {
597
+ callbacks[callbackId] = options.callback;
598
+ state.nextCallbackId = (state.nextCallbackId ?? 1) + 1;
599
+ }
600
+ const siteKey = typeof options?.sitekey === 'string'
601
+ ? options.sitekey
602
+ : typeof options?.siteKey === 'string'
603
+ ? options.siteKey
604
+ : '';
605
+ if (siteKey) {
606
+ challenges.push({
607
+ siteKey,
608
+ action: typeof options?.action === 'string' ? options.action : '',
609
+ cData: typeof options?.cData === 'string' ? options.cData : '',
610
+ chlPageData: typeof options?.chlPageData === 'string' ? options.chlPageData : '',
611
+ callbackId,
612
+ userAgent: navigator.userAgent,
613
+ });
614
+ }
615
+ return originalRender(container, options);
616
+ };
617
+ turnstile.__agentbrowseWrapped = true;
618
+ },
619
+ });
620
+ }
621
+ catch {
622
+ const fallbackTurnstile = win.turnstile;
623
+ if (fallbackTurnstile && typeof fallbackTurnstile === 'object') {
624
+ const turnstile = fallbackTurnstile;
625
+ if (typeof turnstile.render === 'function' && !turnstile.__agentbrowseWrapped) {
626
+ const originalRender = turnstile.render.bind(turnstile);
627
+ turnstile.render = (container, options) => {
628
+ const state = win[stateKey];
629
+ const callbacks = win[callbacksKey];
630
+ const challenges = win[challengesKey];
631
+ const callbackId = typeof options?.callback === 'function'
632
+ ? `cf-turnstile-callback-${state.nextCallbackId ?? 1}`
633
+ : '';
634
+ if (callbackId) {
635
+ callbacks[callbackId] = options.callback;
636
+ state.nextCallbackId = (state.nextCallbackId ?? 1) + 1;
637
+ }
638
+ const siteKey = typeof options?.sitekey === 'string'
639
+ ? options.sitekey
640
+ : typeof options?.siteKey === 'string'
641
+ ? options.siteKey
642
+ : '';
643
+ if (siteKey) {
644
+ challenges.push({
645
+ siteKey,
646
+ action: typeof options?.action === 'string' ? options.action : '',
647
+ cData: typeof options?.cData === 'string' ? options.cData : '',
648
+ chlPageData: typeof options?.chlPageData === 'string' ? options.chlPageData : '',
649
+ callbackId,
650
+ userAgent: navigator.userAgent,
651
+ });
652
+ }
653
+ return originalRender(container, options);
654
+ };
655
+ turnstile.__agentbrowseWrapped = true;
656
+ }
657
+ else if (!turnstile.__agentbrowseWrapped) {
658
+ let renderValue = turnstile.render;
659
+ try {
660
+ Object.defineProperty(turnstile, 'render', {
661
+ configurable: true,
662
+ enumerable: true,
663
+ get: () => renderValue,
664
+ set: (value) => {
665
+ if (typeof value !== 'function') {
666
+ renderValue = value;
667
+ return;
668
+ }
669
+ const originalRender = value.bind(turnstile);
670
+ renderValue = (container, options) => {
671
+ const state = win[stateKey];
672
+ const callbacks = win[callbacksKey];
673
+ const challenges = win[challengesKey];
674
+ const callbackId = typeof options?.callback === 'function'
675
+ ? `cf-turnstile-callback-${state.nextCallbackId ?? 1}`
676
+ : '';
677
+ if (callbackId) {
678
+ callbacks[callbackId] = options.callback;
679
+ state.nextCallbackId = (state.nextCallbackId ?? 1) + 1;
680
+ }
681
+ const siteKey = typeof options?.sitekey === 'string'
682
+ ? options.sitekey
683
+ : typeof options?.siteKey === 'string'
684
+ ? options.siteKey
685
+ : '';
686
+ if (siteKey) {
687
+ challenges.push({
688
+ siteKey,
689
+ action: typeof options?.action === 'string' ? options.action : '',
690
+ cData: typeof options?.cData === 'string' ? options.cData : '',
691
+ chlPageData: typeof options?.chlPageData === 'string' ? options.chlPageData : '',
692
+ callbackId,
693
+ userAgent: navigator.userAgent,
694
+ });
695
+ }
696
+ return originalRender(container, options);
697
+ };
698
+ turnstile.__agentbrowseWrapped = true;
699
+ },
700
+ });
701
+ }
702
+ catch {
703
+ // Ignore non-configurable render properties.
704
+ }
705
+ }
706
+ }
707
+ }
708
+ const pollId = window.setInterval(() => {
709
+ const candidate = window.turnstile;
710
+ if (!candidate || typeof candidate !== 'object')
711
+ return;
712
+ const turnstile = candidate;
713
+ if (typeof turnstile.render !== 'function' || turnstile.__agentbrowseWrapped) {
714
+ return;
715
+ }
716
+ const originalRender = turnstile.render.bind(turnstile);
717
+ turnstile.render = (container, options) => {
718
+ const state = win[stateKey];
719
+ const callbacks = win[callbacksKey];
720
+ const challenges = win[challengesKey];
721
+ const callbackId = typeof options?.callback === 'function'
722
+ ? `cf-turnstile-callback-${state.nextCallbackId ?? 1}`
723
+ : '';
724
+ if (callbackId) {
725
+ callbacks[callbackId] = options.callback;
726
+ state.nextCallbackId = (state.nextCallbackId ?? 1) + 1;
727
+ }
728
+ const siteKey = typeof options?.sitekey === 'string'
729
+ ? options.sitekey
730
+ : typeof options?.siteKey === 'string'
731
+ ? options.siteKey
732
+ : '';
733
+ if (siteKey) {
734
+ challenges.push({
735
+ siteKey,
736
+ action: typeof options?.action === 'string' ? options.action : '',
737
+ cData: typeof options?.cData === 'string' ? options.cData : '',
738
+ chlPageData: typeof options?.chlPageData === 'string' ? options.chlPageData : '',
739
+ callbackId,
740
+ userAgent: navigator.userAgent,
741
+ });
742
+ }
743
+ return originalRender(container, options);
744
+ };
745
+ turnstile.__agentbrowseWrapped = true;
746
+ }, 50);
747
+ window.setTimeout(() => {
748
+ window.clearInterval(pollId);
749
+ }, 30_000);
750
+ try {
751
+ if (typeof WebGLRenderingContext !== 'undefined') {
752
+ const getParameter = WebGLRenderingContext.prototype.getParameter;
753
+ WebGLRenderingContext.prototype.getParameter = function (parameter) {
754
+ const UNMASKED_VENDOR = 0x9245;
755
+ const UNMASKED_RENDERER = 0x9246;
756
+ if (parameter === UNMASKED_VENDOR)
757
+ return fingerprint.webglVendor;
758
+ if (parameter === UNMASKED_RENDERER)
759
+ return fingerprint.webglRenderer;
760
+ return getParameter.call(this, parameter);
761
+ };
762
+ }
763
+ }
764
+ catch {
765
+ // Some environments block prototype patching; keep the turnstile hook alive.
766
+ }
767
+ try {
768
+ Object.defineProperty(navigator, 'hardwareConcurrency', {
769
+ get: () => fingerprint.hardwareConcurrency,
770
+ });
771
+ }
772
+ catch {
773
+ // Ignore non-configurable navigator fields.
774
+ }
775
+ try {
776
+ Object.defineProperty(navigator, 'deviceMemory', {
777
+ get: () => fingerprint.deviceMemory,
778
+ });
779
+ }
780
+ catch {
781
+ // Ignore non-configurable navigator fields.
782
+ }
783
+ try {
784
+ Object.defineProperty(screen, 'width', { get: () => fingerprint.screen.width });
785
+ Object.defineProperty(screen, 'height', { get: () => fingerprint.screen.height });
786
+ Object.defineProperty(screen, 'colorDepth', { get: () => fingerprint.screen.colorDepth });
787
+ }
788
+ catch {
789
+ // Ignore non-configurable screen fields.
790
+ }
791
+ }, {
792
+ webglVendor: fp.webglVendor,
793
+ webglRenderer: fp.webglRenderer,
794
+ hardwareConcurrency: fp.hardwareConcurrency,
795
+ deviceMemory: fp.deviceMemory,
796
+ screen: fp.screen,
797
+ });
798
+ await client.detach();
799
+ }