Banata

Browser Sessions

CDP Connection

How to connect to Banata browser sessions using Puppeteer, Playwright, or raw CDP WebSocket clients.

Once a browser session reaches the ready state, the cdpUrl field contains a WebSocket URL you can use to connect with any Chrome DevTools Protocol client.


Connection URL

The cdpUrl returned in the session response looks like this:

typescript
wss://browsers.banata.dev/ws?token=<JWT>&session=<sessionId>

The URL includes an authentication token that is valid for 1 hour from when the session becomes ready.


Connecting with Puppeteer

typescript
import puppeteer from "puppeteer-core";
 
const browser = await puppeteer.connect({
  browserWSEndpoint: cdpUrl,
});
 
const page = (await browser.pages())[0];
 
await page.goto("https://example.com");
console.log(await page.title());
 
// When done
await browser.disconnect();

Each session comes with a page already created and ready to use. Use (await browser.pages())[0] to access it. There is no need to call browser.newPage() — the session is pre-configured with the stealth fingerprint, proxy, and profile settings you requested.

Note: browser.newPage() is not supported. Each session provides a single, fully configured page. If you need multiple pages, create multiple sessions.


Connecting with Playwright

typescript
import { chromium } from "playwright";
 
const browser = await chromium.connectOverCDP(cdpUrl);
const context = browser.contexts()[0];
const page = context.pages()[0];
 
await page.goto("https://example.com");
console.log(await page.title());
 
await browser.close();

Same pattern — use the existing context and page.


The @banata-boxes/sdk SDK handles session creation, polling, and cleanup so you can focus on your automation logic:

typescript
import puppeteer from "puppeteer-core";
import { BrowserCloud } from "@banata-boxes/sdk";
 
const cloud = new BrowserCloud({
  apiKey: "br_live_...",
});
 
const { cdpUrl, sessionId, close } = await cloud.launch({
  weight: "light",
  stealth: true,
});
 
const browser = await puppeteer.connect({ browserWSEndpoint: cdpUrl });
const page = (await browser.pages())[0];
 
await page.goto("https://example.com");
console.log(await page.title());
 
await browser.disconnect();
await close();

The SDK handles:

  • Session creation and readiness polling (configurable timeout, default 30 seconds)
  • Automatic retry with exponential backoff on rate limit and server errors
  • Clean session teardown via close()

Connecting with Raw WebSocket

If you are building a custom CDP client or using a language without a dedicated library, connect directly via WebSocket:

javascript
const ws = new WebSocket(cdpUrl);
 
ws.onopen = () => {
  ws.send(JSON.stringify({
    id: 1,
    method: "Page.navigate",
    params: { url: "https://example.com" },
  }));
};
 
ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
  console.log(message);
};

Supported CDP Domains

The following CDP domains are available on each session:

DomainExamples
Pagenavigate, screenshot, PDF, lifecycle events
Runtimeevaluate, callFunctionOn, console events
Networkrequest interception, cookies, headers
DOMquerySelector, getDocument, node inspection
InputdispatchMouseEvent, dispatchKeyEvent
EmulationsetDeviceMetricsOverride, setGeolocationOverride

Each session is scoped to a single page. Browser-level commands like Target.createTarget (new tabs) and Browser.close are not available. If you need parallel browsing, create multiple sessions — each one runs independently with its own configuration.


Connection Timing

When stealth mode is enabled, all anti-detection setup completes before your CDP commands are processed. If you connect immediately after seeing status: "ready", any commands you send are held until the browser is fully prepared, then executed in order.

This means you can connect as soon as the session is ready — no delays or polling needed on your side. Your first Page.navigate will execute at exactly the right moment.


Error Handling

ScenarioWhat Happens
Expired tokenWebSocket connection rejected with 401
Session already endedWebSocket connection rejected with 410
Network interruptionWebSocket closes — reconnect using the same cdpUrl if the session is still active

Next Steps