How Ego‑Lite’s Dual Fetch Works: Server vs. Browser Requests Explained

Ego‑Lite provides two distinct fetch helpers—serverFetch for Node.js runtime requests and browserFetch for page‑context execution—allowing agents to retrieve resources either directly from the host process or from within the automated browser session.

The dual fetch architecture in citrolabs/ego-lite solves a critical automation challenge: distinguishing between network calls that should execute in the Node.js host environment versus those that must run inside the browser to access cookies, authentication state, or relative URLs.

What is Dual Fetch in Ego‑Lite?

Ego‑Lite’s dual fetch system consists of complementary helpers exported from package/ego-browser/src/helpers.ts (line 101) and registered in the SDK’s public surface via LEGACY_GLOBAL_HELPERS in package/ego-browser/src/index.ts (lines 123–124). When the SDK installs via installEgoSdk, both helpers are wrapped with readiness logic so agents can invoke them immediately.

  • serverFetch: Executes in the Node.js process using the native globalThis.fetch
  • browserFetch: Executes inside the Chrome DevTools Protocol (CDP) page context via script injection

serverFetch: Node.js Runtime Requests

The serverFetch helper performs standard HTTP requests from the host machine. According to the source code in package/ego-browser/src/http.ts (lines 11–27), this function:

  • Verifies that globalThis.fetch exists in the Node environment
  • Injects a browser‑like User‑Agent header automatically
  • Applies a timeout using AbortSignal.timeout
  • Throws an error on non‑OK HTTP status codes
  • Returns the response body as plain text via response.text()

This approach avoids CDP round‑trip overhead and functions even when no browser page is currently loaded.

browserFetch: Page Context Requests

The browserFetch helper executes requests inside the actual browser page, making it essential for resources that depend on the page’s state. In package/ego-browser/src/http.ts (lines 35–52), the implementation:

  1. Serializes the URL, options, and timeout into a JSON payload
  2. Calls evaluate to inject an async IIFE into the page context (leveraging package/ego-browser/src/cdp-eval.js)
  3. Creates an AbortController inside the page to handle timeouts
  4. Executes the native fetch call (line 43) within the page’s JavaScript environment
  5. Returns the text response back to the host process

Because the request originates from within the page, it automatically respects the page’s cookies, session storage, Content Security Policy (CSP), and resolves relative URLs against the current window.location.

Key Differences and When to Use Each

Understanding when to invoke each helper determines whether your automation script succeeds or fails against authenticated endpoints:

  • Use serverFetch when retrieving public APIs, configuration files, or static resources that do not require the page’s authentication state. It executes faster due to zero CDP communication overhead.
  • Use browserFetch when the target URL requires session cookies, bearer tokens stored in the browser, or when resolving relative paths (e.g., ./api/user) against the current page’s origin.

Practical Code Examples

Fetching Public Data with serverFetch

Retrieve repository information directly from the host process:

const body = await serverFetch('https://api.github.com/repos/citrolabs/ego-lite');
console.log('Raw JSON length:', body.length);

Accessing Authenticated Resources with browserFetch

Download a protected image that requires the page’s logged‑in session:

const imageData = await browserFetch('/protected/image.png', {
  headers: { Accept: 'image/png' },
  timeout: 10,
});
console.log('Fetched image bytes:', imageData.length);

Combining Both Fetch Strategies

First retrieve a URL list from a public API, then download each resource using the browser’s authentication context:

const listJson = await serverFetch('https://example.com/api/url-list');
const urls = JSON.parse(listJson);  // e.g., ["./doc1.pdf", "./doc2.pdf"]

for (const relative of urls) {
  const content = await browserFetch(relative, { timeout: 5 });
  console.log(`Fetched ${relative}: ${content.length} chars`);
}

Summary

  • Dual fetch architecture in citrolabs/ego-lite provides serverFetch for Node.js and browserFetch for CDP page contexts.
  • serverFetch (src/http.ts, lines 11–27) uses globalThis.fetch with automatic User‑Agent headers and timeout enforcement.
  • browserFetch (src/http.ts, lines 35–52) injects code via evaluate (src/cdp-eval.js) to execute fetch inside the page, preserving cookies and CSP constraints.
  • Both helpers are exported from src/helpers.ts and registered in LEGACY_GLOBAL_HELPERS (src/index.ts, lines 123–124) for immediate use after SDK installation.
  • Choose serverFetch for speed and independence from page state;choose browserFetch for authenticated or relative URL resolution.

Frequently Asked Questions

What is the main difference between serverFetch and browserFetch?

serverFetch executes in the Node.js host process using the native globalThis.fetch, while browserFetch injects and runs an asynchronous function inside the browser page via Chrome DevTools Protocol evaluation. The browser variant inherits all page‑specific context including cookies and authentication headers.

How does browserFetch handle cookies and authentication?

Because browserFetch runs the request inside the actual page context using the evaluate method from src/cdp-eval.js, the browser’s native fetch implementation automatically includes all relevant cookies, session storage tokens, and authentication headers associated with the page’s current origin.

Can I use serverFetch when no page is loaded?

Yes. serverFetch operates entirely within the Node.js runtime and does not require an active CDP session or loaded page. This makes it suitable for retrieving configuration data or external APIs before or between page navigations.

Where are the fetch helpers defined in the source code?

Both helpers are implemented in package/ego-browser/src/http.tsserverFetch at lines 11–27 and browserFetch at lines 35–52. They are re‑exported from package/ego-browser/src/helpers.ts (line 101) and registered in the global SDK surface in package/ego-browser/src/index.ts (lines 123–124) as part of LEGACY_GLOBAL_HELPERS.

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 →