How to Evaluate JavaScript in the Browser Context Using ego-browser

Use the evaluate() or js() helpers exported from src/helpers.ts to execute arbitrary JavaScript via the Chrome DevTools Protocol Runtime.evaluate method inside the controlled Chromium instance.

The ego-browser package within the citrolabs/ego-lite repository provides AI agents with direct access to the browser runtime through a secure evaluation layer. By wrapping the Chrome DevTools Protocol (CDP), the system enables agents to evaluate JavaScript in the browser context using the utilities defined in src/cdp-eval.ts. This architecture allows seamless querying of DOM state, execution of async operations, and interaction with web APIs using native JavaScript syntax.

CDP Evaluation Architecture in src/cdp-eval.ts

The core evaluation engine resides in [src/cdp-eval.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/cdp-eval.ts). This module exports the evaluate() function, which constructs CDP Runtime.evaluate payloads and manages bidirectional communication with the embedded browser.

When invoked, evaluate() sends a JSON payload structured as follows:

{
  "method": "Runtime.evaluate",
  "params": {
    "expression": "<your_code>",
    "awaitPromise": true,
    "returnByValue": true,
    "userGesture": true
  }
}

The function resolves with the complete CDP response, including the result object containing the value, type, and object ID, along with any exceptionDetails if the script threw an error.

The Helper Functions: evaluate() vs js()

The system exposes two distinct interfaces for JavaScript execution, both re-exported from [src/helpers.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts).

evaluate(): Raw CDP Access

Use evaluate(expr: string, opts?) when you need the full CDP response or detailed error information. This function returns the raw result from the browser's runtime, including metadata like object references and exception details.

js(): Convenience Wrapper

The js(expr: string) helper simplifies common use cases by automatically extracting result.value from the CDP response. It wraps top-level return statements in an IIFE, allowing concise syntax like js('document.title'). If evaluation fails, it throws an ElementResolutionError with the browser-side exception details.

Automatic Context Injection via helperContext()

Agent scripts do not require manual imports to access these utilities. The helperContext() function in src/helpers.ts automatically injects evaluate and js into the global scope of every executing script. This injection happens before script execution, ensuring seamless access to browser evaluation capabilities without require or import statements.

Evaluating JavaScript: Code Examples

Querying DOM Properties

Retrieve page state using the simplified js() helper:

const pageTitle = await js('document.title');
const pageUrl = await js('window.location.href');
const elementCount = await js('document.querySelectorAll("div").length');

Executing Async Operations

Perform asynchronous work by passing promises to evaluate():

const response = await evaluate(`
  fetch('https://api.example.com/data')
    .then(r => r.json())
    .then(data => data.items)
`);

console.log('Items:', response.result.value);

Error Handling Patterns

Catch browser-side exceptions using standard try-catch blocks:

try {
  await js('undefinedVariable.dangerousMethod()');
} catch (err) {
  console.error('Script failed:', err.message);
}

Internal Usage in Driver Modules

The evaluation helpers power the entire browser automation stack. The driver modules utilize these functions for low-level browser interactions.

For instance, [src/driver/pointer.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/driver/pointer.ts) invokes evaluate() to calculate element bounding boxes before simulating mouse events. [src/driver/nav.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/driver/nav.ts) uses these helpers to verify navigation completion and inspect window.location changes after redirects. Additionally, [src/driver/observe.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/driver/observe.ts) relies on evaluation to capture page state and DOM snapshots during observation tasks.

Summary

  • Core evaluation logic is implemented in src/cdp-eval.ts, wrapping CDP Runtime.evaluate with awaitPromise, returnByValue, and userGesture flags.
  • Two interfaces are available: evaluate() for raw protocol access and js() for simplified value extraction with automatic IIFE wrapping.
  • Global injection via helperContext() in src/helpers.ts makes these functions available to all agent scripts without imports.
  • Driver integration means src/driver/pointer.ts, src/driver/nav.ts, and src/driver/observe.ts all depend on these helpers for element interaction and state inspection.
  • Built-in error handling converts CDP exceptions into catchable JavaScript errors via ElementResolutionError.

Frequently Asked Questions

What is the difference between evaluate() and js() in ego-browser?

evaluate() returns the complete Chrome DevTools Protocol response object, including result.objectId, result.value, and exceptionDetails. The js() helper extracts only the result.value field and automatically wraps expressions in an IIFE, making it ideal for quick property lookups. Use evaluate() when you need full metadata or custom handling of CDP responses.

Can I execute asynchronous JavaScript using ego-browser?

Yes. The evaluate() function sets awaitPromise: true by default, allowing you to pass promises and async functions. The browser waits for the promise to resolve before returning the result, enabling HTTP requests and other async operations within the evaluation context.

How does ego-browser handle JavaScript errors during evaluation?

When browser execution throws an exception, evaluate() returns the error details in the exceptionDetails field. The js() wrapper detects these cases and throws an ElementResolutionError containing the message and stack trace from the browser context, allowing your agent code to handle failures gracefully.

Are the evaluation helpers available automatically in agent scripts?

Yes. The helperContext() function in src/helpers.ts injects both evaluate() and js() into the global scope before script execution. You can call these functions directly without importing them, as the ego-browser runtime prepares the execution environment with these utilities pre-loaded.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →