@nuanu-ai/agentbrowse 0.2.12 → 0.2.14

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 (69) hide show
  1. package/README.md +5 -0
  2. package/dist/agentpay-stagehand-llm.d.ts +16 -0
  3. package/dist/agentpay-stagehand-llm.d.ts.map +1 -1
  4. package/dist/agentpay-stagehand-llm.js +35 -10
  5. package/dist/commands/act.d.ts.map +1 -1
  6. package/dist/commands/act.js +16 -15
  7. package/dist/commands/action-acceptance.d.ts +1 -0
  8. package/dist/commands/action-acceptance.d.ts.map +1 -1
  9. package/dist/commands/action-acceptance.js +77 -1
  10. package/dist/commands/extract-snapshot-sanitizer.d.ts +2 -0
  11. package/dist/commands/extract-snapshot-sanitizer.d.ts.map +1 -0
  12. package/dist/commands/extract-snapshot-sanitizer.js +65 -0
  13. package/dist/commands/extract-stagehand-executor.d.ts.map +1 -1
  14. package/dist/commands/extract-stagehand-executor.js +33 -3
  15. package/dist/commands/extract.d.ts.map +1 -1
  16. package/dist/commands/extract.js +29 -0
  17. package/dist/commands/launch.js +0 -7
  18. package/dist/commands/observe-inventory.d.ts.map +1 -1
  19. package/dist/commands/observe-inventory.js +43 -0
  20. package/dist/commands/observe-persistence.d.ts +1 -0
  21. package/dist/commands/observe-persistence.d.ts.map +1 -1
  22. package/dist/commands/observe-persistence.js +52 -1
  23. package/dist/commands/observe-projection.d.ts +28 -5
  24. package/dist/commands/observe-projection.d.ts.map +1 -1
  25. package/dist/commands/observe-projection.js +189 -9
  26. package/dist/commands/observe-semantics.d.ts.map +1 -1
  27. package/dist/commands/observe-semantics.js +13 -2
  28. package/dist/commands/observe-surfaces.d.ts +1 -0
  29. package/dist/commands/observe-surfaces.d.ts.map +1 -1
  30. package/dist/commands/observe-surfaces.js +65 -0
  31. package/dist/commands/observe.d.ts.map +1 -1
  32. package/dist/commands/observe.js +49 -19
  33. package/dist/commands/observe.test-harness.d.ts +1 -0
  34. package/dist/commands/observe.test-harness.d.ts.map +1 -1
  35. package/dist/commands/observe.test-harness.js +53 -16
  36. package/dist/commands/semantic-observe.d.ts +2 -0
  37. package/dist/commands/semantic-observe.d.ts.map +1 -1
  38. package/dist/commands/semantic-observe.js +4 -0
  39. package/dist/playwright-runtime.d.ts +3 -1
  40. package/dist/playwright-runtime.d.ts.map +1 -1
  41. package/dist/playwright-runtime.js +42 -2
  42. package/dist/runtime-state.d.ts +3 -0
  43. package/dist/runtime-state.d.ts.map +1 -1
  44. package/dist/runtime-state.js +2 -0
  45. package/dist/secrets/fill-ordering.d.ts +1 -2
  46. package/dist/secrets/fill-ordering.d.ts.map +1 -1
  47. package/dist/secrets/fill-ordering.js +0 -3
  48. package/dist/secrets/form-matcher.d.ts.map +1 -1
  49. package/dist/secrets/form-matcher.js +0 -9
  50. package/dist/secrets/types.d.ts +0 -9
  51. package/dist/secrets/types.d.ts.map +1 -1
  52. package/dist/solver/browser-launcher.d.ts.map +1 -1
  53. package/dist/solver/browser-launcher.js +492 -55
  54. package/dist/solver/captcha-detector.d.ts.map +1 -1
  55. package/dist/solver/captcha-detector.js +187 -12
  56. package/dist/solver/captcha-runtime.d.ts.map +1 -1
  57. package/dist/solver/captcha-runtime.js +8 -0
  58. package/dist/solver/captcha-solver.d.ts +11 -1
  59. package/dist/solver/captcha-solver.d.ts.map +1 -1
  60. package/dist/solver/captcha-solver.js +11 -4
  61. package/dist/solver/turnstile-challenge.d.ts +3 -0
  62. package/dist/solver/turnstile-challenge.d.ts.map +1 -0
  63. package/dist/solver/turnstile-challenge.js +173 -0
  64. package/dist/solver/types.d.ts +10 -8
  65. package/dist/solver/types.d.ts.map +1 -1
  66. package/package.json +1 -1
  67. package/dist/secrets/request-guidance.d.ts +0 -24
  68. package/dist/secrets/request-guidance.d.ts.map +0 -1
  69. package/dist/secrets/request-guidance.js +0 -142
@@ -1,14 +1,16 @@
1
1
  import { spawn } from 'node:child_process';
2
- import { existsSync, mkdirSync } from 'node:fs';
2
+ import { existsSync, mkdirSync, readFileSync } from 'node:fs';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import puppeteerExtra from 'puppeteer-extra';
6
6
  import StealthPlugin from 'puppeteer-extra-plugin-stealth';
7
+ import { buildTurnstileApiShimSource, isTurnstileApiRequest } from './turnstile-challenge.js';
7
8
  const enhancedPuppeteer = puppeteerExtra;
8
9
  enhancedPuppeteer.use(StealthPlugin());
9
- const DEFAULT_CDP_PORT = 9222;
10
- const CDP_DISCOVERY_ATTEMPTS = 20;
10
+ const AUTO_CDP_PORT = 0;
11
+ const CDP_DISCOVERY_TIMEOUT_MS = 30_000;
11
12
  const CDP_DISCOVERY_INTERVAL_MS = 500;
13
+ const INTERCEPTED_PAGES = new WeakSet();
12
14
  const CHROME_PATHS = [
13
15
  '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
14
16
  '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
@@ -21,31 +23,22 @@ const CHROME_PATHS = [
21
23
  ];
22
24
  export async function launchSolver(profile, opts) {
23
25
  const fp = withWindowSize(profile.fingerprint, opts?.windowSize);
24
- const cdpPort = opts?.cdpPort ?? DEFAULT_CDP_PORT;
26
+ const cdpPort = opts?.cdpPort ?? AUTO_CDP_PORT;
25
27
  const executablePath = resolveChromeExecutable(opts?.executablePath);
26
- const chromePid = spawnChromeProcess(executablePath, profile, fp, cdpPort, opts?.windowSize, opts?.headless, opts?.url);
28
+ const chromeProcess = spawnChromeProcess(executablePath, profile, fp, cdpPort, opts?.windowSize, opts?.headless, undefined);
27
29
  try {
28
- const cdpUrl = await discoverCdpUrl(cdpPort);
30
+ const cdpUrl = await discoverCdpUrl({
31
+ requestedPort: opts?.cdpPort,
32
+ userDataDir: profile.userDataDir,
33
+ });
29
34
  if (!cdpUrl) {
30
- throw new Error(`Chrome launched but CDP not reachable on port ${cdpPort}`);
35
+ throw buildCdpDiscoveryError(chromeProcess, opts?.cdpPort, profile.userDataDir);
31
36
  }
32
37
  const browser = await enhancedPuppeteer.connect({ browserWSEndpoint: cdpUrl });
33
38
  let page;
34
39
  if (opts?.url) {
35
- // Chrome was launched with the URL — reuse the existing tab.
36
- const existingPages = await browser.pages();
37
- page = existingPages[0] ?? (await browser.newPage());
38
- await applyFingerprint(page, fp);
39
- if (fp.proxy?.username && fp.proxy.password) {
40
- await page.authenticate({ username: fp.proxy.username, password: fp.proxy.password });
41
- }
42
- // If Chrome hasn't finished loading yet, wait for it.
43
- const currentUrl = page.url();
44
- if (!currentUrl || currentUrl === 'about:blank' || currentUrl === 'chrome://newtab/') {
45
- await page
46
- .waitForNavigation({ waitUntil: 'domcontentloaded', timeout: 15_000 })
47
- .catch(() => { });
48
- }
40
+ page = await createConfiguredPage(browser, fp);
41
+ page = await navigateConfiguredPage(browser, page, fp, opts.url);
49
42
  }
50
43
  else {
51
44
  page = await createConfiguredPage(browser, fp);
@@ -72,7 +65,7 @@ export async function launchSolver(profile, opts) {
72
65
  await browser.disconnect();
73
66
  }
74
67
  finally {
75
- terminateProcessGroup(chromePid);
68
+ terminateProcessGroup(chromeProcess.pid);
76
69
  }
77
70
  },
78
71
  disconnect: async () => {
@@ -81,30 +74,93 @@ export async function launchSolver(profile, opts) {
81
74
  };
82
75
  }
83
76
  catch (error) {
84
- terminateProcessGroup(chromePid);
77
+ terminateProcessGroup(chromeProcess.pid);
85
78
  throw error;
86
79
  }
87
80
  }
88
- async function discoverCdpUrl(port) {
89
- for (let i = 0; i < CDP_DISCOVERY_ATTEMPTS; i++) {
90
- try {
91
- const res = await fetch(`http://127.0.0.1:${port}/json/version`);
92
- if (!res.ok)
93
- throw new Error(`CDP endpoint returned ${res.status}`);
94
- const json = (await res.json());
95
- if (json.webSocketDebuggerUrl) {
96
- return json.webSocketDebuggerUrl;
81
+ async function discoverCdpUrl(options) {
82
+ const deadline = Date.now() + CDP_DISCOVERY_TIMEOUT_MS;
83
+ const activePortPath = path.join(options.userDataDir, 'DevToolsActivePort');
84
+ while (Date.now() < deadline) {
85
+ if (typeof options.requestedPort === 'number') {
86
+ const cdpUrl = await discoverCdpUrlOnPort(options.requestedPort);
87
+ if (cdpUrl) {
88
+ return cdpUrl;
97
89
  }
98
90
  }
99
- catch {
100
- // Retry while Chrome is initializing.
91
+ else {
92
+ const activePort = readDevToolsActivePort(activePortPath);
93
+ if (activePort?.browserWSEndpoint) {
94
+ return activePort.browserWSEndpoint;
95
+ }
96
+ if (activePort?.port) {
97
+ const cdpUrl = await discoverCdpUrlOnPort(activePort.port);
98
+ if (cdpUrl) {
99
+ return cdpUrl;
100
+ }
101
+ }
101
102
  }
102
- await new Promise((resolve) => setTimeout(resolve, CDP_DISCOVERY_INTERVAL_MS));
103
+ await sleep(CDP_DISCOVERY_INTERVAL_MS);
103
104
  }
104
105
  return null;
105
106
  }
107
+ async function discoverCdpUrlOnPort(port) {
108
+ try {
109
+ const res = await fetch(`http://127.0.0.1:${port}/json/version`);
110
+ if (!res.ok) {
111
+ return null;
112
+ }
113
+ const json = (await res.json());
114
+ return json.webSocketDebuggerUrl ?? null;
115
+ }
116
+ catch {
117
+ return null;
118
+ }
119
+ }
120
+ function readDevToolsActivePort(activePortPath) {
121
+ if (!existsSync(activePortPath)) {
122
+ return null;
123
+ }
124
+ try {
125
+ const raw = readFileSync(activePortPath, 'utf-8').trim();
126
+ if (!raw) {
127
+ return null;
128
+ }
129
+ const [portLine = '', wsPathLine = ''] = raw.split(/\r?\n/, 2);
130
+ const port = Number(portLine.trim());
131
+ if (!Number.isFinite(port) || port <= 0) {
132
+ return null;
133
+ }
134
+ const wsPath = wsPathLine.trim();
135
+ return {
136
+ port,
137
+ browserWSEndpoint: wsPath
138
+ ? wsPath.startsWith('ws://')
139
+ ? wsPath
140
+ : `ws://127.0.0.1:${port}${wsPath.startsWith('/') ? wsPath : `/${wsPath}`}`
141
+ : undefined,
142
+ };
143
+ }
144
+ catch {
145
+ return null;
146
+ }
147
+ }
148
+ function buildCdpDiscoveryError(chromeProcess, requestedPort, userDataDir) {
149
+ const details = [`pid ${chromeProcess.pid ?? 'unknown'}`];
150
+ if (typeof chromeProcess.exitCode === 'number') {
151
+ details.push(`exitCode ${chromeProcess.exitCode}`);
152
+ }
153
+ if (chromeProcess.signalCode) {
154
+ details.push(`signal ${chromeProcess.signalCode}`);
155
+ }
156
+ if (typeof requestedPort === 'number') {
157
+ return new Error(`Chrome launched but CDP not reachable on port ${requestedPort} within ${CDP_DISCOVERY_TIMEOUT_MS}ms (${details.join(', ')}).`);
158
+ }
159
+ 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')}.`);
160
+ }
106
161
  async function createConfiguredPage(browser, fp) {
107
162
  const page = await browser.newPage();
163
+ await installTurnstileApiInterception(page);
108
164
  await applyFingerprint(page, fp);
109
165
  if (fp.proxy?.username && fp.proxy.password) {
110
166
  await page.authenticate({
@@ -114,6 +170,41 @@ async function createConfiguredPage(browser, fp) {
114
170
  }
115
171
  return page;
116
172
  }
173
+ async function installTurnstileApiInterception(page) {
174
+ if (INTERCEPTED_PAGES.has(page)) {
175
+ return;
176
+ }
177
+ await page.setRequestInterception(true);
178
+ page.on('request', (request) => {
179
+ void (async () => {
180
+ try {
181
+ if (isTurnstileApiRequest(request.url())) {
182
+ await request.respond({
183
+ status: 200,
184
+ contentType: 'application/javascript',
185
+ headers: {
186
+ 'access-control-allow-origin': '*',
187
+ 'cross-origin-resource-policy': 'cross-origin',
188
+ 'cache-control': 'no-store',
189
+ },
190
+ body: buildTurnstileApiShimSource(request.url()),
191
+ });
192
+ return;
193
+ }
194
+ await request.continue();
195
+ }
196
+ catch {
197
+ try {
198
+ await request.continue();
199
+ }
200
+ catch {
201
+ // Ignore navigations or already-handled requests.
202
+ }
203
+ }
204
+ })();
205
+ });
206
+ INTERCEPTED_PAGES.add(page);
207
+ }
117
208
  async function navigateConfiguredPage(browser, page, fp, url) {
118
209
  try {
119
210
  await page.goto(url, { waitUntil: 'domcontentloaded' });
@@ -166,6 +257,7 @@ function spawnChromeProcess(executablePath, profile, fp, cdpPort, windowSize, he
166
257
  '--remote-debugging-address=127.0.0.1',
167
258
  `--user-data-dir=${profile.userDataDir}`,
168
259
  `--window-size=${width},${height}`,
260
+ `--user-agent=${fp.userAgent}`,
169
261
  '--disable-blink-features=AutomationControlled',
170
262
  '--no-first-run',
171
263
  '--no-default-browser-check',
@@ -189,7 +281,7 @@ function spawnChromeProcess(executablePath, profile, fp, cdpPort, windowSize, he
189
281
  if (!proc.pid) {
190
282
  throw new Error('Failed to launch Chrome process');
191
283
  }
192
- return proc.pid;
284
+ return proc;
193
285
  }
194
286
  function terminateProcessGroup(pid) {
195
287
  try {
@@ -206,6 +298,9 @@ function terminateProcessGroup(pid) {
206
298
  // Ignore already terminated process.
207
299
  }
208
300
  }
301
+ function sleep(ms) {
302
+ return new Promise((resolve) => setTimeout(resolve, ms));
303
+ }
209
304
  function withWindowSize(fingerprint, windowSize) {
210
305
  if (!windowSize)
211
306
  return fingerprint;
@@ -238,25 +333,367 @@ async function applyFingerprint(page, fp) {
238
333
  });
239
334
  await page.emulateTimezone(fp.timezone);
240
335
  await page.evaluateOnNewDocument((fingerprint) => {
241
- const getParameter = WebGLRenderingContext.prototype.getParameter;
242
- WebGLRenderingContext.prototype.getParameter = function (parameter) {
243
- const UNMASKED_VENDOR = 0x9245;
244
- const UNMASKED_RENDERER = 0x9246;
245
- if (parameter === UNMASKED_VENDOR)
246
- return fingerprint.webglVendor;
247
- if (parameter === UNMASKED_RENDERER)
248
- return fingerprint.webglRenderer;
249
- return getParameter.call(this, parameter);
250
- };
251
- Object.defineProperty(navigator, 'hardwareConcurrency', {
252
- get: () => fingerprint.hardwareConcurrency,
253
- });
254
- Object.defineProperty(navigator, 'deviceMemory', {
255
- get: () => fingerprint.deviceMemory,
256
- });
257
- Object.defineProperty(screen, 'width', { get: () => fingerprint.screen.width });
258
- Object.defineProperty(screen, 'height', { get: () => fingerprint.screen.height });
259
- Object.defineProperty(screen, 'colorDepth', { get: () => fingerprint.screen.colorDepth });
336
+ const win = window;
337
+ const callbacksKey = '__agentbrowseTurnstileCallbacks';
338
+ const challengesKey = '__agentbrowseTurnstileChallenges';
339
+ const stateKey = '__agentbrowseTurnstileState';
340
+ if (!Array.isArray(win[challengesKey])) {
341
+ win[challengesKey] = [];
342
+ }
343
+ if (!win[callbacksKey] || typeof win[callbacksKey] !== 'object') {
344
+ win[callbacksKey] = {};
345
+ }
346
+ if (!win[stateKey] || typeof win[stateKey] !== 'object') {
347
+ win[stateKey] = { nextCallbackId: 1 };
348
+ }
349
+ let turnstileValue = win.turnstile;
350
+ if (turnstileValue && typeof turnstileValue === 'object') {
351
+ const turnstile = turnstileValue;
352
+ if (typeof turnstile.render === 'function' && !turnstile.__agentbrowseWrapped) {
353
+ const originalRender = turnstile.render.bind(turnstile);
354
+ turnstile.render = (container, options) => {
355
+ const state = win[stateKey];
356
+ const callbacks = win[callbacksKey];
357
+ const challenges = win[challengesKey];
358
+ const callbackId = typeof options?.callback === 'function'
359
+ ? `cf-turnstile-callback-${state.nextCallbackId ?? 1}`
360
+ : '';
361
+ if (callbackId) {
362
+ callbacks[callbackId] = options.callback;
363
+ state.nextCallbackId = (state.nextCallbackId ?? 1) + 1;
364
+ }
365
+ const siteKey = typeof options?.sitekey === 'string'
366
+ ? options.sitekey
367
+ : typeof options?.siteKey === 'string'
368
+ ? options.siteKey
369
+ : '';
370
+ if (siteKey) {
371
+ challenges.push({
372
+ siteKey,
373
+ action: typeof options?.action === 'string' ? options.action : '',
374
+ cData: typeof options?.cData === 'string' ? options.cData : '',
375
+ chlPageData: typeof options?.chlPageData === 'string' ? options.chlPageData : '',
376
+ callbackId,
377
+ userAgent: navigator.userAgent,
378
+ });
379
+ }
380
+ return originalRender(container, options);
381
+ };
382
+ turnstile.__agentbrowseWrapped = true;
383
+ }
384
+ else {
385
+ let renderValue = turnstile.render;
386
+ try {
387
+ Object.defineProperty(turnstile, 'render', {
388
+ configurable: true,
389
+ enumerable: true,
390
+ get: () => renderValue,
391
+ set: (value) => {
392
+ if (typeof value !== 'function') {
393
+ renderValue = value;
394
+ return;
395
+ }
396
+ const originalRender = value.bind(turnstile);
397
+ renderValue = (container, options) => {
398
+ const state = win[stateKey];
399
+ const callbacks = win[callbacksKey];
400
+ const challenges = win[challengesKey];
401
+ const callbackId = typeof options?.callback === 'function'
402
+ ? `cf-turnstile-callback-${state.nextCallbackId ?? 1}`
403
+ : '';
404
+ if (callbackId) {
405
+ callbacks[callbackId] = options.callback;
406
+ state.nextCallbackId = (state.nextCallbackId ?? 1) + 1;
407
+ }
408
+ const siteKey = typeof options?.sitekey === 'string'
409
+ ? options.sitekey
410
+ : typeof options?.siteKey === 'string'
411
+ ? options.siteKey
412
+ : '';
413
+ if (siteKey) {
414
+ challenges.push({
415
+ siteKey,
416
+ action: typeof options?.action === 'string' ? options.action : '',
417
+ cData: typeof options?.cData === 'string' ? options.cData : '',
418
+ chlPageData: typeof options?.chlPageData === 'string' ? options.chlPageData : '',
419
+ callbackId,
420
+ userAgent: navigator.userAgent,
421
+ });
422
+ }
423
+ return originalRender(container, options);
424
+ };
425
+ turnstile.__agentbrowseWrapped = true;
426
+ },
427
+ });
428
+ }
429
+ catch {
430
+ // Ignore non-configurable render properties.
431
+ }
432
+ }
433
+ }
434
+ try {
435
+ Object.defineProperty(win, 'turnstile', {
436
+ configurable: true,
437
+ enumerable: true,
438
+ get: () => turnstileValue,
439
+ set: (value) => {
440
+ turnstileValue = value;
441
+ if (!value || typeof value !== 'object')
442
+ return;
443
+ const turnstile = value;
444
+ if (typeof turnstile.render !== 'function' || turnstile.__agentbrowseWrapped) {
445
+ let renderValue = turnstile.render;
446
+ try {
447
+ Object.defineProperty(turnstile, 'render', {
448
+ configurable: true,
449
+ enumerable: true,
450
+ get: () => renderValue,
451
+ set: (nextValue) => {
452
+ if (typeof nextValue !== 'function') {
453
+ renderValue = nextValue;
454
+ return;
455
+ }
456
+ const originalRender = nextValue.bind(turnstile);
457
+ renderValue = (container, options) => {
458
+ const state = win[stateKey];
459
+ const callbacks = win[callbacksKey];
460
+ const challenges = win[challengesKey];
461
+ const callbackId = typeof options?.callback === 'function'
462
+ ? `cf-turnstile-callback-${state.nextCallbackId ?? 1}`
463
+ : '';
464
+ if (callbackId) {
465
+ callbacks[callbackId] = options.callback;
466
+ state.nextCallbackId = (state.nextCallbackId ?? 1) + 1;
467
+ }
468
+ const siteKey = typeof options?.sitekey === 'string'
469
+ ? options.sitekey
470
+ : typeof options?.siteKey === 'string'
471
+ ? options.siteKey
472
+ : '';
473
+ if (siteKey) {
474
+ challenges.push({
475
+ siteKey,
476
+ action: typeof options?.action === 'string' ? options.action : '',
477
+ cData: typeof options?.cData === 'string' ? options.cData : '',
478
+ chlPageData: typeof options?.chlPageData === 'string' ? options.chlPageData : '',
479
+ callbackId,
480
+ userAgent: navigator.userAgent,
481
+ });
482
+ }
483
+ return originalRender(container, options);
484
+ };
485
+ turnstile.__agentbrowseWrapped = true;
486
+ },
487
+ });
488
+ }
489
+ catch {
490
+ // Ignore non-configurable render properties.
491
+ }
492
+ return;
493
+ }
494
+ const originalRender = turnstile.render.bind(turnstile);
495
+ turnstile.render = (container, options) => {
496
+ const state = win[stateKey];
497
+ const callbacks = win[callbacksKey];
498
+ const challenges = win[challengesKey];
499
+ const callbackId = typeof options?.callback === 'function'
500
+ ? `cf-turnstile-callback-${state.nextCallbackId ?? 1}`
501
+ : '';
502
+ if (callbackId) {
503
+ callbacks[callbackId] = options.callback;
504
+ state.nextCallbackId = (state.nextCallbackId ?? 1) + 1;
505
+ }
506
+ const siteKey = typeof options?.sitekey === 'string'
507
+ ? options.sitekey
508
+ : typeof options?.siteKey === 'string'
509
+ ? options.siteKey
510
+ : '';
511
+ if (siteKey) {
512
+ challenges.push({
513
+ siteKey,
514
+ action: typeof options?.action === 'string' ? options.action : '',
515
+ cData: typeof options?.cData === 'string' ? options.cData : '',
516
+ chlPageData: typeof options?.chlPageData === 'string' ? options.chlPageData : '',
517
+ callbackId,
518
+ userAgent: navigator.userAgent,
519
+ });
520
+ }
521
+ return originalRender(container, options);
522
+ };
523
+ turnstile.__agentbrowseWrapped = true;
524
+ },
525
+ });
526
+ }
527
+ catch {
528
+ const fallbackTurnstile = win.turnstile;
529
+ if (fallbackTurnstile && typeof fallbackTurnstile === 'object') {
530
+ const turnstile = fallbackTurnstile;
531
+ if (typeof turnstile.render === 'function' && !turnstile.__agentbrowseWrapped) {
532
+ const originalRender = turnstile.render.bind(turnstile);
533
+ turnstile.render = (container, options) => {
534
+ const state = win[stateKey];
535
+ const callbacks = win[callbacksKey];
536
+ const challenges = win[challengesKey];
537
+ const callbackId = typeof options?.callback === 'function'
538
+ ? `cf-turnstile-callback-${state.nextCallbackId ?? 1}`
539
+ : '';
540
+ if (callbackId) {
541
+ callbacks[callbackId] = options.callback;
542
+ state.nextCallbackId = (state.nextCallbackId ?? 1) + 1;
543
+ }
544
+ const siteKey = typeof options?.sitekey === 'string'
545
+ ? options.sitekey
546
+ : typeof options?.siteKey === 'string'
547
+ ? options.siteKey
548
+ : '';
549
+ if (siteKey) {
550
+ challenges.push({
551
+ siteKey,
552
+ action: typeof options?.action === 'string' ? options.action : '',
553
+ cData: typeof options?.cData === 'string' ? options.cData : '',
554
+ chlPageData: typeof options?.chlPageData === 'string' ? options.chlPageData : '',
555
+ callbackId,
556
+ userAgent: navigator.userAgent,
557
+ });
558
+ }
559
+ return originalRender(container, options);
560
+ };
561
+ turnstile.__agentbrowseWrapped = true;
562
+ }
563
+ else if (!turnstile.__agentbrowseWrapped) {
564
+ let renderValue = turnstile.render;
565
+ try {
566
+ Object.defineProperty(turnstile, 'render', {
567
+ configurable: true,
568
+ enumerable: true,
569
+ get: () => renderValue,
570
+ set: (value) => {
571
+ if (typeof value !== 'function') {
572
+ renderValue = value;
573
+ return;
574
+ }
575
+ const originalRender = value.bind(turnstile);
576
+ renderValue = (container, options) => {
577
+ const state = win[stateKey];
578
+ const callbacks = win[callbacksKey];
579
+ const challenges = win[challengesKey];
580
+ const callbackId = typeof options?.callback === 'function'
581
+ ? `cf-turnstile-callback-${state.nextCallbackId ?? 1}`
582
+ : '';
583
+ if (callbackId) {
584
+ callbacks[callbackId] = options.callback;
585
+ state.nextCallbackId = (state.nextCallbackId ?? 1) + 1;
586
+ }
587
+ const siteKey = typeof options?.sitekey === 'string'
588
+ ? options.sitekey
589
+ : typeof options?.siteKey === 'string'
590
+ ? options.siteKey
591
+ : '';
592
+ if (siteKey) {
593
+ challenges.push({
594
+ siteKey,
595
+ action: typeof options?.action === 'string' ? options.action : '',
596
+ cData: typeof options?.cData === 'string' ? options.cData : '',
597
+ chlPageData: typeof options?.chlPageData === 'string' ? options.chlPageData : '',
598
+ callbackId,
599
+ userAgent: navigator.userAgent,
600
+ });
601
+ }
602
+ return originalRender(container, options);
603
+ };
604
+ turnstile.__agentbrowseWrapped = true;
605
+ },
606
+ });
607
+ }
608
+ catch {
609
+ // Ignore non-configurable render properties.
610
+ }
611
+ }
612
+ }
613
+ }
614
+ const pollId = window.setInterval(() => {
615
+ const candidate = window.turnstile;
616
+ if (!candidate || typeof candidate !== 'object')
617
+ return;
618
+ const turnstile = candidate;
619
+ if (typeof turnstile.render !== 'function' || turnstile.__agentbrowseWrapped) {
620
+ return;
621
+ }
622
+ const originalRender = turnstile.render.bind(turnstile);
623
+ turnstile.render = (container, options) => {
624
+ const state = win[stateKey];
625
+ const callbacks = win[callbacksKey];
626
+ const challenges = win[challengesKey];
627
+ const callbackId = typeof options?.callback === 'function'
628
+ ? `cf-turnstile-callback-${state.nextCallbackId ?? 1}`
629
+ : '';
630
+ if (callbackId) {
631
+ callbacks[callbackId] = options.callback;
632
+ state.nextCallbackId = (state.nextCallbackId ?? 1) + 1;
633
+ }
634
+ const siteKey = typeof options?.sitekey === 'string'
635
+ ? options.sitekey
636
+ : typeof options?.siteKey === 'string'
637
+ ? options.siteKey
638
+ : '';
639
+ if (siteKey) {
640
+ challenges.push({
641
+ siteKey,
642
+ action: typeof options?.action === 'string' ? options.action : '',
643
+ cData: typeof options?.cData === 'string' ? options.cData : '',
644
+ chlPageData: typeof options?.chlPageData === 'string' ? options.chlPageData : '',
645
+ callbackId,
646
+ userAgent: navigator.userAgent,
647
+ });
648
+ }
649
+ return originalRender(container, options);
650
+ };
651
+ turnstile.__agentbrowseWrapped = true;
652
+ }, 50);
653
+ window.setTimeout(() => {
654
+ window.clearInterval(pollId);
655
+ }, 30_000);
656
+ try {
657
+ if (typeof WebGLRenderingContext !== 'undefined') {
658
+ const getParameter = WebGLRenderingContext.prototype.getParameter;
659
+ WebGLRenderingContext.prototype.getParameter = function (parameter) {
660
+ const UNMASKED_VENDOR = 0x9245;
661
+ const UNMASKED_RENDERER = 0x9246;
662
+ if (parameter === UNMASKED_VENDOR)
663
+ return fingerprint.webglVendor;
664
+ if (parameter === UNMASKED_RENDERER)
665
+ return fingerprint.webglRenderer;
666
+ return getParameter.call(this, parameter);
667
+ };
668
+ }
669
+ }
670
+ catch {
671
+ // Some environments block prototype patching; keep the turnstile hook alive.
672
+ }
673
+ try {
674
+ Object.defineProperty(navigator, 'hardwareConcurrency', {
675
+ get: () => fingerprint.hardwareConcurrency,
676
+ });
677
+ }
678
+ catch {
679
+ // Ignore non-configurable navigator fields.
680
+ }
681
+ try {
682
+ Object.defineProperty(navigator, 'deviceMemory', {
683
+ get: () => fingerprint.deviceMemory,
684
+ });
685
+ }
686
+ catch {
687
+ // Ignore non-configurable navigator fields.
688
+ }
689
+ try {
690
+ Object.defineProperty(screen, 'width', { get: () => fingerprint.screen.width });
691
+ Object.defineProperty(screen, 'height', { get: () => fingerprint.screen.height });
692
+ Object.defineProperty(screen, 'colorDepth', { get: () => fingerprint.screen.colorDepth });
693
+ }
694
+ catch {
695
+ // Ignore non-configurable screen fields.
696
+ }
260
697
  }, {
261
698
  webglVendor: fp.webglVendor,
262
699
  webglRenderer: fp.webglRenderer,
@@ -1 +1 @@
1
- {"version":3,"file":"captcha-detector.d.ts","sourceRoot":"","sources":["../../src/solver/captcha-detector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,2BAA2B,GAAG;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC;IACpD,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IACrD,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACzD,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAKF,wBAAsB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAqC3E;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAG7F;AAED,wBAAsB,+BAA+B,CACnD,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,aAAa,EACrB,IAAI,CAAC,EAAE,2BAA2B,GACjC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAmFhC;AAyUD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CA4B3E"}
1
+ {"version":3,"file":"captcha-detector.d.ts","sourceRoot":"","sources":["../../src/solver/captcha-detector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,2BAA2B,GAAG;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC;IACpD,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IACrD,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACzD,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAKF,wBAAsB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAyI3E;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAG7F;AAED,wBAAsB,+BAA+B,CACnD,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,aAAa,EACrB,IAAI,CAAC,EAAE,2BAA2B,GACjC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAuHhC;AA4YD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CA4B3E"}