# @browserless.io/bap-ts (Browser Automation Protocol) > A Puppeteer-like TypeScript SDK for [Browserless](https://browserless.io). It is > a GraphQL client: each `Page` method builds a BrowserQL mutation, sends it over a > single WebSocket, and awaits the response (no CDP). Isomorphic — runs in Node and > the browser. If you know Puppeteer's `Page` API, you mostly already know this one. Install: `npm install @browserless.io/bap-ts` ## Canonical usage ```typescript import Browserless from "@browserless.io/bap-ts"; const browser = Browserless.connect({ browserWSEndpoint: "wss://production-sfo.browserless.io/chromium/bql", token: "your-api-token", }); const page = await browser.newPage(); await page.goto("https://example.com"); const title = await page.title(); await browser.close(); ``` Named exports: `Browserless`, `Browser`, `Page`, `ElementHandle`, `Transport`, `EventEmitter`, `BrowserQLError`, `ConnectionError`, `TimeoutError`. Default export is `Browserless`. ## Key facts for code generation - Operations are serial per connection; state persists across calls on the same page. - `screenshot()` / `pdf()` return `Uint8Array`. The `path` option writes to disk in Node only; in the browser it rejects — use the returned bytes. - `content({ clean })` and `markdown()` return token-efficient page text — prefer these over raw DOM walking when feeding an LLM. - Errors carry a `code` field: `'BQL' | 'CONNECTION' | 'TIMEOUT'`. `TimeoutError` also exposes `operation` and `timeoutMs`. Branch on `code`, don't parse messages. - Streaming events use a Puppeteer-style emitter: `page.on('console'|'request'| 'response', cb)` (plus `once`/`off`). The first listener lazily opens a GraphQL subscription over the same multiplexed `graphql-transport-ws` connection that carries queries and mutations; the last removal closes it. `response` omits the body by default (expensive to stream). Handshake/stream failures surface via `page.on('error', cb)`, never throw. ## Method groups (Puppeteer-named where applicable) - Navigation: `goto`, `goBack`, `goForward`, `reload`, `setContent`, `waitForNavigation` - Interaction: `click`, `type`, `select`, `hover`, `check`, `uncheck`, `scroll` - Content: `content`, `title`, `url`, `screenshot`, `pdf`, `html`, `text`, `markdown` - Selectors: `$`, `$$`, `$eval`, `$$eval`, `mapSelector`, `waitForSelector` - Settings: `setUserAgent`, `setViewport`, `setCookie`, `cookies`, `setExtraHTTPHeaders` - Network: `request`, `response`, `waitForRequest`, `waitForResponse`, `reject`, `proxy` - Events: `on`, `once`, `off`, `removeAllListeners` (`console`, `request`, `response`, `error`) - Browserless-only: `solve`, `solveImageCaptcha`, `liveURL`, `reconnect`, `preferences` ## Docs - README.md (in the GitHub repo): full API reference, examples, Puppeteer comparison, the complete generated method/return-type table - AGENTS.md (in the GitHub repo): contributing (codegen invariants, commands) - CONTRIBUTING.md (in the GitHub repo)