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

> Understand Ego-Lite's dual fetch mechanism. Learn how serverFetch and browserFetch enable efficient resource retrieval in Node.js and browser environments.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: deep-dive
- Published: 2026-08-27

---

**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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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:

```javascript
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:

```javascript
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:

```javascript
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`](https://github.com/citrolabs/ego-lite/blob/main/src/http.ts), lines 11–27) uses `globalThis.fetch` with automatic User‑Agent headers and timeout enforcement.
- **`browserFetch`** ([`src/http.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/http.ts), lines 35–52) injects code via `evaluate` ([`src/cdp-eval.js`](https://github.com/citrolabs/ego-lite/blob/main/src/cdp-eval.js)) to execute `fetch` inside the page, preserving cookies and CSP constraints.
- Both helpers are exported from [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) and registered in `LEGACY_GLOBAL_HELPERS` ([`src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/http.ts)—`serverFetch` at lines 11–27 and `browserFetch` at lines 35–52. They are re‑exported from [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) (line 101) and registered in the global SDK surface in [`package/ego-browser/src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts) (lines 123–124) as part of `LEGACY_GLOBAL_HELPERS`.