Puppeteer

View as Markdown

Connect to Chaser sessions with Puppeteer. The API is the same as connecting to a local browser — only the endpoint changes.

Installation

$npm i puppeteer-core

Use puppeteer-core, not puppeteer. The full puppeteer package downloads its own Chromium, which you don’t need — the browser is on Chaser’s side.

Basic connection

1import puppeteer from "puppeteer-core";
2
3// 1. Create a session
4const { cdp_url, id } = await fetch(
5 "https://api.chaser.sh/v1/sessions",
6 {
7 method: "POST",
8 headers: {
9 Authorization: `Bearer ${process.env.CHASER_KEY}`,
10 "Content-Type": "application/json",
11 },
12 body: JSON.stringify({ ttl_seconds: 1800 }),
13 }
14).then((r) => r.json());
15
16// 2. Connect
17const browser = await puppeteer.connect({ browserWSEndpoint: cdp_url });
18const [page] = await browser.pages();
19
20// 3. Automate
21await page.goto("https://www.cloudflare.com");
22console.log(await page.title());
23
24// 4. Screenshot via the API
25const png = await fetch(
26 `https://api.chaser.sh/v1/sessions/${id}/screenshot`,
27 {
28 method: "POST",
29 headers: { Authorization: `Bearer ${process.env.CHASER_KEY}` },
30 }
31).then((r) => r.arrayBuffer());
32writeFileSync("page.png", Buffer.from(png));
33
34// 5. Clean up
35await fetch(`https://api.chaser.sh/v1/sessions/${id}`, { method: "DELETE" });

Notes

  • Use browserWSEndpoint, not browserURL (which is deprecated).
  • puppeteer.connect() returns immediately. The session must be in ready status first.
  • As with patchright: don’t create new contexts, don’t override the user-agent, and use the /screenshot endpoint instead of page.screenshot().
  • Puppeteer’s bundled Chromium has known automation artifacts. For production use, prefer patchright (Playwright-based) which patches these at the browser level.