# BrowserSession

URL: https://cogitator.app/docs/browser/session

> Manage browser lifecycle, tabs, cookies, proxy, and stealth configuration with BrowserSession.

## Overview

`BrowserSession` is the core class that manages a Playwright browser instance. It handles launching the browser, creating contexts with the right configuration, and provides tab and cookie management.

Every browser tool receives a session reference and operates on its active page.

```typescript
import { BrowserSession } from '@cogitator-ai/browser';

const session = new BrowserSession({
  headless: true,
  browser: 'chromium',
  stealth: true,
});

await session.start();
// ... use tools ...
await session.close();
```

## Configuration

The full `BrowserSessionConfig` interface:

```typescript
interface BrowserSessionConfig {
  headless?: boolean; // default: true
  browser?: BrowserType; // 'chromium' | 'firefox' | 'webkit', default: 'chromium'
  stealth?: boolean | StealthConfig;
  proxy?: string | ProxyConfig;
  viewport?: { width: number; height: number }; // default: 1280x720
  userAgent?: string;
  locale?: string; // e.g. 'en-US'
  timezone?: string; // e.g. 'America/New_York'
  geolocation?: { latitude: number; longitude: number };
  persistentContext?: string; // user data dir; profile survives restarts
  cookies?: BrowserCookie[]; // initial cookies
  timeout?: number; // navigation timeout, default: 30000ms
  actionTimeout?: number; // action timeout, default: 10000ms
  pool?: { maxPages: number }; // max open tabs for newTab(), positive integer
  robots?: RobotsChecker; // block navigations the site's robots.txt disallows
}
```

### Persistent Profile

`persistentContext` launches Playwright's persistent context with the given user data directory. Cookies, `localStorage`, IndexedDB and cache survive across sessions, which keeps logins without exporting cookies. In this mode `session.browser` is `null` and the profile's existing tabs become the session's tabs.

```typescript
const session = new BrowserSession({ persistentContext: './.browser-profile' });
await session.start();
```

### Tab Limit

`pool.maxPages` caps the number of tabs `newTab()` may open. Opening a tab beyond the limit throws `Tab limit reached: pool.maxPages is N`.

```typescript
const session = new BrowserSession({ pool: { maxPages: 3 } });
```

### robots.txt

`robots` takes a checker such as `RobotsPolicy` from `@cogitator-ai/core`. Every page navigation, typed, clicked, redirected or in a frame, is checked against the site's robots.txt, and disallowed ones are blocked. `newTab(url)` and the `browser_navigate` tool throw `robots.txt does not allow visiting <url>`, so an agent learns why.

```typescript
import { RobotsPolicy } from '@cogitator-ai/core';

const userAgent = 'NewsBot/1.0 (+https://example.com/bot)';
const session = new BrowserSession({ userAgent, robots: new RobotsPolicy({ userAgent }) });
```

### Browser Types

Playwright supports three browser engines:

```typescript
new BrowserSession({ browser: 'chromium' }); // Chrome, Edge
new BrowserSession({ browser: 'firefox' }); // Firefox
new BrowserSession({ browser: 'webkit' }); // Safari
```

### Proxy

Pass a URL string or a full `ProxyConfig` with authentication:

```typescript
new BrowserSession({ proxy: 'http://proxy.example.com:8080' });

new BrowserSession({
  proxy: {
    server: 'http://proxy.example.com:8080',
    username: 'user',
    password: 'pass',
  },
});
```

### User Agent

An explicit `userAgent` wins over stealth: the random stealth user agent is skipped, but the evasion scripts still run and report a `navigator.platform` that matches your user agent.

### Viewport and Locale

```typescript
new BrowserSession({
  viewport: { width: 1920, height: 1080 },
  locale: 'de-DE',
  timezone: 'Europe/Berlin',
  geolocation: { latitude: 52.52, longitude: 13.405 }, // also grants the geolocation permission
});
```

## Lifecycle

### `start()`

Launches the browser, creates a context with the configured options, opens the first tab, and applies stealth evasions if enabled. If any step fails, everything launched so far is closed and the error is rethrown, so the session can be started again. Calling `start()` while the session is running or starting throws.

```typescript
const session = new BrowserSession({ headless: false });
await session.start();
```

If the browser context closes on its own (crash, the user closing a headed window), the session resets and `started` becomes `false`.

### `ensureStarted()`

Starts the session if needed. Concurrent callers share a single launch. Tools returned by `browserTools()` call it before every execution, so a session that was never started, or whose browser was closed or crashed, is (re)launched on the next tool call.

```typescript
await Promise.all([session.ensureStarted(), session.ensureStarted()]); // one browser
```

### `onStart(listener)`

Registers a listener that receives the `BrowserContext` after every successful start, and immediately if the session is already running. Returns an unsubscribe function. The network tools use it to record traffic from the first request.

```typescript
const unsubscribe = session.onStart((context) => {
  context.on('request', (req) => console.log(req.url()));
});
```

### `close()`

Closes the browser (or the persistent context) and cleans up all resources. Safe to call multiple times, and waits for a launch in progress first.

```typescript
await session.close();
```

`BrowserSession` is also async-disposable, so `await using` closes it at the end of the scope:

```typescript
await using session = new BrowserSession();
await session.start();
```

### `page`

Returns the currently active `Page` object. Throws if the session hasn't been started. If the active tab was closed, the session falls back to an open tab. `session.started` tells whether a context is running and `session.activeTabIndex` returns the active tab index.

```typescript
const page = session.page;
console.log(page.url());
```

## Tab Management

Sessions support multiple tabs. New tabs automatically become the active tab. Pages opened by the site itself (popups, `target="_blank"` links) are tracked in `tabs` too, without changing the active tab.

### `newTab(url?)`

Opens a new tab, optionally navigating to a URL. Returns the Playwright `Page` object. If navigation fails the tab is closed and the error is rethrown. Respects `pool.maxPages`.

```typescript
const page = await session.newTab('https://example.com');
```

### `switchTab(index)`

Switches the active tab by index.

```typescript
session.switchTab(0); // switch to first tab
```

### `closeTab(index?)`

Closes a tab by index. Defaults to closing the active tab. Cannot close the last remaining tab.

```typescript
await session.closeTab(1);
```

### `tabs`

Returns a copy of all open `Page` objects. Tabs closed outside the session are pruned, and `switchTab`/`closeTab` indexes always refer to this pruned list.

```typescript
for (const tab of session.tabs) {
  console.log(tab.url());
}
```

## Cookie Management

### `getCookies()`

Returns all cookies from the current browser context.

```typescript
const cookies = await session.getCookies();
```

### `setCookies(cookies)`

Adds cookies to the browser context. Cookies with a `domain` but no `path` default to `path: '/'`.

```typescript
await session.setCookies([{ name: 'session', value: 'abc123', domain: '.example.com' }]);
```

### `saveCookies(filePath)` / `loadCookies(filePath)`

Persist cookies to a JSON file and restore them later. Useful for maintaining login state across sessions. `loadCookies` requires a JSON array and skips entries without `name`, `value`, and `url` or `domain`.

```typescript
await session.saveCookies('./cookies.json');

// later...
const session2 = new BrowserSession();
await session2.start();
await session2.loadCookies('./cookies.json');
```

## Initial Cookies

Pass cookies at construction time to have them applied on `start()`:

```typescript
const session = new BrowserSession({
  cookies: [{ name: 'token', value: 'xyz', domain: '.example.com', path: '/' }],
});
await session.start();
```

## Accessing Playwright Objects

For advanced use cases, you can access the underlying Playwright objects directly:

```typescript
session.browser; // Browser | null (null with persistentContext)
session.context; // BrowserContext | null
session.page; // active Page
```

The resolved configuration is available too:

```typescript
session.config; // BrowserSessionConfig with defaults applied
session.stealthEnabled; // true when `stealth` is set
session.stealthConfig; // StealthConfig merged with defaults, or null
```

## Next Steps

* [Tools Reference](/docs/browser/tools) — all 33 tools that operate on the session
* [Stealth](/docs/browser/stealth) — anti-detection configuration
