serverFetch vs browserFetch in ego-lite: HTTP Request Handling Guide

serverFetch executes HTTP requests from the Node.js host process, while browserFetch runs requests inside the active browser tab, inheriting the page's authentication state, cookies, and origin constraints.

The ego-lite framework (citrolabs/ego-lite) provides a unified fetch façade that exposes two distinct HTTP request strategies through fetch.server and fetch.browser. Understanding the difference between serverFetch and browserFetch is essential for writing agents that interact correctly with external APIs versus authenticated web applications.

Execution Context: Node.js vs Browser Page

The fundamental difference between these methods lies in where the HTTP request physically executes.

Server-Side Execution with serverFetch

serverFetch runs inside the Node.js process that hosts the ego-lite runtime. According to the implementation in [src/http.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/http.ts#L11-L27), this method uses Node's global fetch to perform requests directly from the server environment. Because it operates outside the browser sandbox, serverFetch has no access to the active page's cookies, session storage, or origin policies.

Browser-Side Execution with browserFetch

browserFetch executes within the active browser tab that the agent controls. As implemented in [src/http.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/http.ts#L35-L52), this method sends a payload to the browser via the evaluate helper (defined in [src/cdp-eval.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/cdp-eval.ts)), creating an async IIFE that runs fetch inside the page's JavaScript environment. This allows the request to inherit the page's authentication headers, CSRF tokens, and same-origin policies.

Implementation and Technical Differences

Request Headers and User-Agent

serverFetch merges caller-provided headers with a default User-Agent: Mozilla/5.0 to emulate browser requests. This prevents basic bot detection while maintaining server-side execution.

browserFetch uses the page's native fetch implementation, automatically including any headers the browser would normally send—including cookies, Accept headers, and authentication tokens bound to the current domain.

URL Resolution Behavior

serverFetch requires absolute URLs because the Node environment has no concept of a current page context. Attempting to pass relative URLs will result in resolution errors.

browserFetch accepts relative URLs (e.g., /api/user), resolving them against the current page's URL exactly as standard browser navigation would. This mirrors normal web application behavior.

Timeout Handling Mechanisms

The timeout implementations differ between environments. serverFetch uses AbortSignal.timeout (available in Node.js ≥16), while browserFetch implements a manual timeout mechanism using setTimeout paired with an AbortController to cancel the in-page request.

Practical Code Examples

Use fetch.server when retrieving external resources unrelated to the current page:

// Server-side fetch: Download external HTML or API data
const html = await fetch.server('https://example.com/data', {
  timeout: 10,  // seconds
  headers: { 'Accept': 'text/html' }
});
// Returns raw response body as string

Use fetch.browser when the request must execute as the logged-in user:

// Browser-side fetch: Call authenticated endpoints
const userData = await fetch.browser('/api/user/profile', {
  method: 'GET',
  headers: { 'Accept': 'application/json' },
  timeout: 5
});
// Inherits the page's cookies and authentication state

Summary

Frequently Asked Questions

When should I use serverFetch instead of browserFetch?

Use serverFetch when retrieving external resources that are not tied to the current page context, such as downloading files from third-party APIs or scraping remote HTML pages. Use browserFetch when the request must execute within the user's authenticated session, such as calling internal APIs that rely on cookies, CSRF tokens, or same-origin policies.

Can browserFetch handle relative URLs?

Yes. Unlike serverFetch, which requires absolute URLs, browserFetch resolves relative URLs against the current page's location, matching standard browser behavior. This allows agents to interact with web applications using the same relative paths used by the application's frontend code.

How does authentication differ between serverFetch and browserFetch?

serverFetch executes as a standalone Node.js process and cannot access the browser's cookie store or session storage. browserFetch runs inside the page's JavaScript context and automatically includes all browser-managed credentials, including HTTP-only cookies, bearer tokens, and CSRF headers required by the current origin.

What timeout mechanisms do these methods use?

serverFetch leverages Node.js's native AbortSignal.timeout (Node ≥16) to cancel requests that exceed the specified duration. browserFetch implements a manual timeout using setTimeout combined with an AbortController to terminate the fetch operation within the browser page, ensuring compatibility with the browser's fetch implementation.

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 →