browserFetch vs serverFetch in ego-lite: Execution Context and Use Cases Explained
The fetch.browser() helper runs HTTP requests inside the active browser page (inheriting cookies and origin), while fetch.server() executes requests directly from the Node.js agent process outside the browser context.
In citrolabs/ego-lite, these two complementary helpers solve distinct automation challenges. Understanding when to use each prevents authentication failures, CORS errors, and unexpected behavior in your agent scripts. Both functions are implemented in src/http.ts and exposed through the helpers registry in src/helpers.ts.
What browserFetch Does: In-Page Request Execution
fetch.browser() executes fetch() inside the currently loaded page using Chrome DevTools Protocol (CDP) evaluation.
How It Works
According to the source code in src/http.ts (lines 35-52), browserFetch sends a script via evaluate that runs the native fetch API within the page's JavaScript context. This gives it three critical properties:
- Cookie inheritance: Requests include the page's stored cookies automatically
- Origin respect: Same-origin policy applies as if the user clicked a button
- Relative URL resolution: Paths like
/api/dataresolve against the page URL
When to Use browserFetch
Use fetch.browser() when you need to interact with endpoints that depend on the page state:
- Authenticated API endpoints requiring session cookies
- CSRF-protected forms
- Relative URLs that only make sense in the page context
- Endpoints that check
OriginorRefererheaders
// POST to a relative endpoint with automatic cookie handling
const response = await fetch.browser('/api/v1/user/profile', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'updated' })
});
What serverFetch Does: Agent-Side Request Execution
fetch.server() runs HTTP requests from the Node.js process driving the browser, completely outside the page context.
How It Works
The serverFetch implementation in src/http.ts (lines 11-27) calls globalThis.fetch with a browser-like User-Agent header and timeout controller. Since it runs in Node, it operates without browser security constraints.
Key Characteristics
- No cookie jar: Requests are stateless unless you manually attach headers
- No origin restrictions: Can reach any URL regardless of CORS policies
- Direct network access: Bypasses any page-level proxies or interceptors
When to Use serverFetch
Use fetch.server() for operations independent of page state:
- Downloading static resources (images, PDFs, binaries)
- Calling external APIs unrelated to the current session
- Fetching data before navigating to a target page
- Bypassing CORS restrictions that block browser requests
// Fetch a resource directly from the agent
const html = await fetch.server('https://cdn.example.com/data.json');
console.log('Fetched bytes:', html.length);
Side-by-Side Comparison
| Aspect | fetch.browser() |
fetch.server() |
|---|---|---|
| Execution location | Inside active browser page (evaluate) |
Node.js agent process |
| Source file | src/http.ts lines 35-52 |
src/http.ts lines 11-27 |
| Cookie handling | Automatic (page's cookie jar) | None (manual header required) |
| Relative URLs | Resolve against page URL | Invalid (requires absolute URL) |
| CORS policy | Enforced by browser | Ignored |
| Use case | Page-dependent API calls | External resource fetching |
Implementation Details from Source Code
Both helpers are registered in src/helpers.ts where the documentation string explains their API surface (lines 818-819). Their public signatures are declared in src/format.ts for the help() system:
"fetch.server": { signature: "fetch.server(url, options?) => Promise<string>", ... }(lines 886-904)"fetch.browser": { signature: "fetch.browser(url, options?) => Promise<string>", ... }(lines 906-925)
Both return Promise<string> containing the response body, not a Response object. The options parameter accepts standard fetch init properties (method, headers, body, etc.).
Common Mistakes to Avoid
Using fetch.server() for authenticated endpoints
: Server requests lack the page's session cookies. APIs requiring login will return 401 errors.
Using fetch.browser() for cross-origin external APIs
: Browser CORS policies block requests to unrelated domains unless the server allows them.
Passing relative URLs to fetch.server()
: Server fetch has no page context; always use absolute URLs.
Summary
fetch.browser()runs inside the loaded page via CDPevaluate, inheriting cookies, origin, and security policies—ideal for authenticated page APIs.fetch.server()executes from the Node agent with direct network access, bypassing CORS and browser constraints—ideal for external resources and pre-navigation fetching.- Both helpers live in
src/http.ts, are registered insrc/helpers.ts, and documented insrc/format.ts. - Both return
Promise<string>and accept standard fetch options.
Frequently Asked Questions
Can I use fetch.server() to bypass CORS restrictions?
Yes. Since fetch.server() runs in Node.js outside the browser context, it is not subject to CORS policies. This makes it useful for accessing APIs that deny cross-origin browser requests. However, any authentication or session state must be manually provided in the headers option.
Why does fetch.browser() fail with a relative URL error on some pages?
fetch.browser() resolves relative URLs against the current page URL. If no page is loaded (or the page URL is about:blank), resolution fails. Ensure you've navigated to a valid page with browser.goto() before calling fetch.browser() with relative paths.
Do these helpers support streaming responses?
No. According to the signature declarations in src/format.ts, both helpers return Promise<string>—the full response body as a string. For large binary downloads, use fetch.server() and consider the memory implications, or implement chunked handling at the agent level.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →