serverFetch vs browserFetch in ego-browser: Key Differences Explained

serverFetch executes HTTP requests from the Node.js host process while browserFetch runs requests inside the controlled browser page, inheriting cookies, authentication state, and same-origin policies.

The ego-browser package in the citrolabs/ego-lite repository exposes a unified fetch façade that abstracts two distinct HTTP strategies. Understanding the difference between serverFetch and browserFetch is essential for writing automation scripts that interact with both external APIs and authenticated web applications.

Execution Context and Architecture

Server-Side Requests with serverFetch

As implemented in ego-browser/src/http.ts (lines 11-27), serverFetch operates entirely within the Node.js runtime that hosts the ego-lite agent. It calls the native Node.js fetch implementation directly, making it suitable for retrieving resources that do not require the browser's session context. Because it runs server-side, it only accepts absolute URLs and has no access to the page's cookies or local storage.

Browser-Side Requests with browserFetch

Conversely, browserFetch (defined in ego-browser/src/http.ts, lines 35-52) executes code inside the active browser tab via the evaluate helper from src/cdp-eval.ts. This method creates an async IIFE within the page’s JavaScript context, allowing the request to inherit the page’s origin, CSRF tokens, and authentication cookies. It supports relative URLs, which resolve against the current page's location.

Source Code Implementation Details

Underlying these differences are distinct timeout mechanisms and header handling strategies:

  • serverFetch: Uses AbortSignal.timeout (requires Node.js ≥ 16) for request cancellation. It merges caller-provided headers with a default User-Agent: Mozilla/5.0 to emulate browser requests, and validates that URLs are absolute.

  • browserFetch: Implements manual timeout handling via setTimeout and an AbortController injected into the page context. It relies on the browser's native fetch, automatically including the page's default headers, cookies, and security policies.

The unified façade exposing both methods is defined in src/helpers.ts (lines 28-31), while public type signatures and comprehensive documentation reside in src/format.ts (lines 886-925).

Key Differences Comparison

Feature serverFetch browserFetch
Execution Environment Node.js host process Active browser page via CDP
URL Support Absolute URLs only Absolute and relative URLs
Authentication State No inherited cookies or sessions Full cookie and session inheritance
User-Agent Handling Injected Mozilla/5.0 Native browser header
Timeout Mechanism AbortSignal.timeout AbortController with setTimeout
Error Handling Throws on non-OK HTTP statuses Throws on non-OK HTTP statuses

Practical Code Examples

Use serverFetch when retrieving external resources from third-party APIs that do not require session authentication:

// Server-side: Fetch external data with custom timeout
const html = await fetch.server('https://api.example.com/data', {
  timeout: 10,
  headers: { 'Accept': 'application/json' }
});

Use browserFetch for authenticated endpoints that rely on the current page's security context:

// Browser-side: Call API using current page's cookies and origin
const userData = await fetch.browser('/api/user/profile', {
  method: 'GET',
  headers: { 'Accept': 'application/json' },
  timeout: 5
});
// Relative URL '/api/user/profile' resolves against window.location

When to Use Each Method

Choose serverFetch for operations such as downloading static assets from CDNs, scraping public HTML pages, or calling external REST APIs where browser session state is irrelevant. This avoids the overhead of browser execution and bypasses Content Security Policy restrictions that might block requests within the page context.

Choose browserFetch when interacting with endpoints protected by CSRF tokens, session cookies, or strict same-origin policies. This method executes requests as if the user triggered them manually, preserving the authentication and security context of the active tab.

Summary

  • serverFetch runs in Node.js via ego-browser/src/http.ts (lines 11-27), requires absolute URLs, and uses AbortSignal.timeout
  • browserFetch executes inside the browser page via src/cdp-eval.ts, inherits cookies, resolves relative URLs, and uses AbortController
  • Both methods throw errors for non-OK HTTP statuses and are exposed through the unified façade in src/helpers.ts
  • serverFetch adds a default Mozilla User-Agent; browserFetch uses native browser headers

Frequently Asked Questions

Can browserFetch access cookies from the current browser session?

Yes. Because browserFetch executes via the evaluate helper in src/cdp-eval.ts, it runs the fetch call within the page's JavaScript context. This means it automatically includes all cookies, authentication headers, and browser state associated with the current origin, behaving exactly like a user-initiated request.

Why does serverFetch require absolute URLs while browserFetch supports relative paths?

The serverFetch implementation in ego-browser/src/http.ts runs in the Node.js environment, which has no concept of a "current page" or base URL for resolution. Therefore, it cannot resolve relative paths. browserFetch executes inside the browser where the native fetch resolves relative paths against window.location.

Which method should I use for downloading large files?

Use serverFetch for large external downloads to avoid consuming browser memory and to bypass potential Content Security Policy restrictions within the page. serverFetch streams data directly through the Node.js process, while browserFetch executes within the browser context and inherits all page-level limitations.

Does serverFetch support custom headers?

Yes. According to the implementation in ego-browser/src/http.ts, serverFetch merges caller-provided headers with its default User-Agent. You can pass any valid headers object to override defaults or add API keys for external services, though the request will not include any cookies from the browser session.

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 →