cbrowser 18.55.1 → 18.56.0

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 (60) hide show
  1. package/README.md +4 -4
  2. package/dist/analysis/accessibility-empathy.d.ts.map +1 -1
  3. package/dist/analysis/accessibility-empathy.js +4 -34
  4. package/dist/analysis/accessibility-empathy.js.map +1 -1
  5. package/dist/analysis/agent-ready-audit.d.ts.map +1 -1
  6. package/dist/analysis/agent-ready-audit.js +37 -32
  7. package/dist/analysis/agent-ready-audit.js.map +1 -1
  8. package/dist/analysis/competitive-benchmark.d.ts.map +1 -1
  9. package/dist/analysis/competitive-benchmark.js +4 -13
  10. package/dist/analysis/competitive-benchmark.js.map +1 -1
  11. package/dist/browser.d.ts.map +1 -1
  12. package/dist/browser.js +97 -46
  13. package/dist/browser.js.map +1 -1
  14. package/dist/cli.js +90 -1
  15. package/dist/cli.js.map +1 -1
  16. package/dist/mcp-server-remote.d.ts.map +1 -1
  17. package/dist/mcp-server-remote.js +93 -118
  18. package/dist/mcp-server-remote.js.map +1 -1
  19. package/dist/mcp-tools/base/advanced-interaction-tools.d.ts +14 -0
  20. package/dist/mcp-tools/base/advanced-interaction-tools.d.ts.map +1 -0
  21. package/dist/mcp-tools/base/advanced-interaction-tools.js +174 -0
  22. package/dist/mcp-tools/base/advanced-interaction-tools.js.map +1 -0
  23. package/dist/mcp-tools/base/audit-tools.d.ts +3 -3
  24. package/dist/mcp-tools/base/audit-tools.d.ts.map +1 -1
  25. package/dist/mcp-tools/base/audit-tools.js +172 -47
  26. package/dist/mcp-tools/base/audit-tools.js.map +1 -1
  27. package/dist/mcp-tools/base/browser-management-tools.d.ts.map +1 -1
  28. package/dist/mcp-tools/base/browser-management-tools.js +62 -0
  29. package/dist/mcp-tools/base/browser-management-tools.js.map +1 -1
  30. package/dist/mcp-tools/base/browser-state-tools.d.ts +14 -0
  31. package/dist/mcp-tools/base/browser-state-tools.d.ts.map +1 -0
  32. package/dist/mcp-tools/base/browser-state-tools.js +229 -0
  33. package/dist/mcp-tools/base/browser-state-tools.js.map +1 -0
  34. package/dist/mcp-tools/base/cognitive-tools.d.ts.map +1 -1
  35. package/dist/mcp-tools/base/cognitive-tools.js +10 -5
  36. package/dist/mcp-tools/base/cognitive-tools.js.map +1 -1
  37. package/dist/mcp-tools/base/index.d.ts +2 -0
  38. package/dist/mcp-tools/base/index.d.ts.map +1 -1
  39. package/dist/mcp-tools/base/index.js +10 -2
  40. package/dist/mcp-tools/base/index.js.map +1 -1
  41. package/dist/mcp-tools/base/navigation-tools.d.ts.map +1 -1
  42. package/dist/mcp-tools/base/navigation-tools.js +9 -2
  43. package/dist/mcp-tools/base/navigation-tools.js.map +1 -1
  44. package/dist/mcp-tools/base/persona-comparison-tools.d.ts.map +1 -1
  45. package/dist/mcp-tools/base/persona-comparison-tools.js +27 -2
  46. package/dist/mcp-tools/base/persona-comparison-tools.js.map +1 -1
  47. package/dist/mcp-tools/base/visual-testing-tools.d.ts.map +1 -1
  48. package/dist/mcp-tools/base/visual-testing-tools.js +3 -1
  49. package/dist/mcp-tools/base/visual-testing-tools.js.map +1 -1
  50. package/dist/mcp-tools/tool-categories.d.ts.map +1 -1
  51. package/dist/mcp-tools/tool-categories.js +12 -0
  52. package/dist/mcp-tools/tool-categories.js.map +1 -1
  53. package/dist/remediation/llms-txt.js +4 -14
  54. package/dist/remediation/llms-txt.js.map +1 -1
  55. package/dist/remediation/structured-data.js +4 -13
  56. package/dist/remediation/structured-data.js.map +1 -1
  57. package/dist/types.d.ts +16 -0
  58. package/dist/types.d.ts.map +1 -1
  59. package/dist/types.js.map +1 -1
  60. package/package.json +1 -1
package/dist/browser.js CHANGED
@@ -392,9 +392,15 @@ For more help: https://playwright.dev/docs/browsers
392
392
  };
393
393
  contextOptions.permissions = ["geolocation"];
394
394
  }
395
- // Apply locale if configured
395
+ // Apply locale if configured — sets navigator.language AND Accept-Language header
396
+ // This makes sites that respect Accept-Language serve localized content
396
397
  if (this.config.locale) {
397
398
  contextOptions.locale = this.config.locale;
399
+ const lang = this.config.locale.split("-")[0];
400
+ contextOptions.extraHTTPHeaders = {
401
+ ...contextOptions.extraHTTPHeaders,
402
+ "Accept-Language": `${this.config.locale},${lang};q=0.9,en;q=0.5`,
403
+ };
398
404
  }
399
405
  // Apply timezone if configured
400
406
  if (this.config.timezone) {
@@ -1427,59 +1433,103 @@ For more help: https://playwright.dev/docs/browsers
1427
1433
  const waitStrategy = options.waitStrategy || "auto";
1428
1434
  const waitTimeout = options.waitTimeout ?? 10000;
1429
1435
  const waitForStability = options.waitForStability ?? (waitStrategy === "auto" || waitStrategy === "domcontentloaded");
1430
- if (waitStrategy === "commit") {
1431
- // Fastest: don't wait at all after navigation commits
1432
- await page.goto(url, { waitUntil: "commit", timeout: this.config.timeout || 30000 });
1433
- }
1434
- else if (waitStrategy === "load") {
1435
- // Standard: wait for load event
1436
- await page.goto(url, { waitUntil: "load", timeout: this.config.timeout || 30000 });
1437
- }
1438
- else if (waitStrategy === "domcontentloaded") {
1439
- // Fast: wait only for DOM
1440
- await page.goto(url, { waitUntil: "domcontentloaded", timeout: this.config.timeout || 30000 });
1441
- if (waitForStability) {
1442
- await this.waitForStability(page, 2000);
1436
+ // Helper to detect proxy tunnel errors and provide actionable messages
1437
+ const wrapProxyError = (e) => {
1438
+ const errMsg = e.message || "";
1439
+ if (errMsg.includes("ERR_TUNNEL_CONNECTION_FAILED") || errMsg.includes("ERR_PROXY_CONNECTION_FAILED")) {
1440
+ const proxyServer = this.config.proxy?.server || "configured proxy";
1441
+ throw new Error(`Proxy tunnel rejected by ${url}. The target site is blocking proxy/VPN connections ` +
1442
+ `(proxy: ${proxyServer}). This is the site's anti-bot defense, not a CBrowser issue.\n\n` +
1443
+ `Recommendations:\n` +
1444
+ `1. Re-run without the proxy to test from your direct IP\n` +
1445
+ `2. Try a different geo region — the site may block specific IP ranges\n` +
1446
+ `3. Some sites (Stripe, GitHub, banking) aggressively block residential proxies`);
1447
+ }
1448
+ if (errMsg.includes("ERR_NETWORK_CHANGED") && this.config.proxy) {
1449
+ throw new Error(`Network changed during proxy connection to ${url}. The residential proxy IP may have rotated mid-request ` +
1450
+ `or the site detected and dropped the proxy tunnel.\n\n` +
1451
+ `Recommendations:\n` +
1452
+ `1. Retry — residential proxy IPs rotate and the next one may work\n` +
1453
+ `2. Re-run without the proxy to test from your direct IP\n` +
1454
+ `3. Use a sticky session proxy for sites that are sensitive to IP changes`);
1455
+ }
1456
+ throw e;
1457
+ };
1458
+ try {
1459
+ if (waitStrategy === "commit") {
1460
+ // Fastest: don't wait at all after navigation commits
1461
+ await page.goto(url, { waitUntil: "commit", timeout: this.config.timeout || 30000 });
1462
+ }
1463
+ else if (waitStrategy === "load") {
1464
+ // Standard: wait for load event
1465
+ await page.goto(url, { waitUntil: "load", timeout: this.config.timeout || 30000 });
1466
+ }
1467
+ else if (waitStrategy === "domcontentloaded") {
1468
+ // Fast: wait only for DOM
1469
+ await page.goto(url, { waitUntil: "domcontentloaded", timeout: this.config.timeout || 30000 });
1470
+ if (waitForStability) {
1471
+ await this.waitForStability(page, 2000);
1472
+ }
1443
1473
  }
1444
- }
1445
- else if (waitStrategy === "networkidle") {
1446
- // Strict: wait for network idle, may fail on SPAs
1447
- await page.goto(url, { waitUntil: "networkidle", timeout: this.config.timeout || 30000 });
1448
- }
1449
- else {
1450
- // "auto" (default): Progressive loading strategy
1451
- // Many SPAs (GitHub, NYT, BBC, etc.) never reach networkidle
1452
- const networkIdleTimeout = Math.min(waitTimeout, this.config.timeout || 30000);
1453
- try {
1454
- // Try networkidle first with short timeout
1455
- await page.goto(url, {
1456
- waitUntil: "networkidle",
1457
- timeout: networkIdleTimeout,
1458
- });
1474
+ else if (waitStrategy === "networkidle") {
1475
+ // Strict: wait for network idle, may fail on SPAs
1476
+ await page.goto(url, { waitUntil: "networkidle", timeout: this.config.timeout || 30000 });
1459
1477
  }
1460
- catch (e) {
1461
- const error = e;
1462
- if (error.message?.includes("Timeout") || error.message?.includes("timeout")) {
1463
- // Fallback: Use domcontentloaded + manual stability check
1464
- if (this.config.verbose) {
1465
- console.log(`⚠️ networkidle timeout after ${waitTimeout}ms, falling back to domcontentloaded...`);
1466
- }
1467
- // Fallback to domcontentloaded (rethrows on failure)
1478
+ else {
1479
+ // "auto" (default): Progressive loading strategy
1480
+ // Many SPAs (GitHub, NYT, BBC, etc.) never reach networkidle
1481
+ const networkIdleTimeout = Math.min(waitTimeout, this.config.timeout || 30000);
1482
+ try {
1483
+ // Try networkidle first with short timeout
1468
1484
  await page.goto(url, {
1469
- waitUntil: "domcontentloaded",
1470
- timeout: this.config.timeout || 30000,
1485
+ waitUntil: "networkidle",
1486
+ timeout: networkIdleTimeout,
1471
1487
  });
1472
- // Wait for page to stabilize (no major DOM changes for 500ms)
1473
- if (waitForStability) {
1474
- await this.waitForStability(page, 2000);
1475
- }
1476
1488
  }
1477
- else {
1478
- // Non-timeout error, rethrow
1479
- throw e;
1489
+ catch (e) {
1490
+ const error = e;
1491
+ if (error.message?.includes("Timeout") || error.message?.includes("timeout")) {
1492
+ // Fallback: Use domcontentloaded + manual stability check
1493
+ if (this.config.verbose) {
1494
+ console.log(`⚠️ networkidle timeout after ${waitTimeout}ms, falling back to domcontentloaded...`);
1495
+ }
1496
+ // Fallback to domcontentloaded (rethrows on failure)
1497
+ await page.goto(url, {
1498
+ waitUntil: "domcontentloaded",
1499
+ timeout: this.config.timeout || 30000,
1500
+ });
1501
+ // Wait for page to stabilize (no major DOM changes for 500ms)
1502
+ if (waitForStability) {
1503
+ await this.waitForStability(page, 2000);
1504
+ }
1505
+ }
1506
+ else {
1507
+ // Non-timeout error — proxy detection handled by outer catch
1508
+ wrapProxyError(e);
1509
+ }
1480
1510
  }
1481
1511
  }
1482
1512
  }
1513
+ catch (navError) {
1514
+ // Wrap any proxy-related navigation error with actionable message
1515
+ wrapProxyError(navError);
1516
+ }
1517
+ // Post-navigation waits for dynamic content (translation, deferred rendering)
1518
+ let waitSelectorTimedOut = false;
1519
+ if (options.waitForSelector) {
1520
+ try {
1521
+ await page.waitForSelector(options.waitForSelector, {
1522
+ timeout: options.waitTimeout ?? 10000,
1523
+ });
1524
+ }
1525
+ catch {
1526
+ waitSelectorTimedOut = true;
1527
+ warnings.push(`waitForSelector "${options.waitForSelector}" timed out after ${options.waitTimeout ?? 10000}ms — the expected element never appeared. The page may not have completed the operation you were waiting for (e.g., translation, dynamic render).`);
1528
+ }
1529
+ }
1530
+ if (options.waitAfterLoad && options.waitAfterLoad > 0) {
1531
+ await page.waitForTimeout(options.waitAfterLoad);
1532
+ }
1483
1533
  const loadTime = Date.now() - startTime;
1484
1534
  // v11.9.0: Post-navigation verification to detect context desync (issue #84)
1485
1535
  const actualUrl = page.url();
@@ -1526,6 +1576,7 @@ For more help: https://playwright.dev/docs/browsers
1526
1576
  warnings,
1527
1577
  loadTime,
1528
1578
  success: true,
1579
+ ...(waitSelectorTimedOut ? { waitSelectorTimedOut: true } : {}),
1529
1580
  };
1530
1581
  }
1531
1582
  /**