// Use case · Browser sessions

Run your Playwright script on hosted anti-detect Chromium

For jobs that need a real browser session: log in, click through steps and hold one exit IP, without running a browser fleet. Your driver, our browser.

  • credits per open-page hour

    8

  • connections per link token

    1–100

  • exit targeting

    City, ISP

WSS /ws?token=…&country=US&session=run42 connected
// First message on the socket, then plain CDP{  "type": "connected",  "connectionId": "0c2c3a1e-…",  "instanceId": "inst-…",  "contextId": "ctx-…"}
credits per open-page hour
What your driver receives when the browser is ready. After this it is ordinary Playwright or Puppeteer. Sessions bill 8 credits per open-page hour.

// Why

A response is not a browser

The problem

A scraping API returns a page; your job needs a browser

  • Logging in, filling a form and waiting for the element you came for take several steps. A request/response endpoint returns one page and keeps nothing.
  • Running your own browsers means a pool, upgrades, driver versions and proxy wiring, all yours to maintain.
  • A cookie issued to one IP and replayed from another is an easy signal for a site to read.

What Wayfern does

Hosted anti-detect Chromium that you drive over CDP

  • Open one WebSocket with chromium.connectOverCDP or puppeteer.connect. The session starts when the socket opens: no SDK, no create call.
  • The Wayfern Chromium build runs headed on a virtual display in our containers. Cookies and storage stay live for as long as your socket is open.
  • Choose the exit in the URL: country, region, city or ISP, plus a sticky session id to keep one IP across a flow.

// How it works

Mint a token, connect, drive

There is no SDK and no session API to learn. From the connect call onward it is the Playwright or Puppeteer you already write.

  1. Step 1 of 4

    Create a link token

    In a project, mint a link token. Set its connection cap (1 to 100, default 10) and an optional expiry.

    Project → Links → New link

  2. Step 2 of 4

    Connect your driver

    Open the CDP WebSocket with the token in the query string. Playwright and Puppeteer attach as they would to a local browser.

    wss://api.wayfern.com/ws

  3. Step 3 of 4

    Pick the exit

    Add country, region, city or isp for a residential exit and session to keep one IP. Leave them off for the free datacenter exit.

    ?country=US&session=run42

  4. Step 4 of 4

    Drive it, then close

    Everything after connect is your usual script. Billing runs per open page and stops when the socket closes.

    8 credits / open-page hour

// Code

Log in, then keep going

The same login flow in each client. Exit selectors ride on the connection URL.

Connect over CDP
import { chromium } from "playwright";

// The session is created when this socket opens: there is no REST call to
// "start" one, and no queue to poll.
const browser = await chromium.connectOverCDP(
  "wss://api.wayfern.com/ws?token=<LINK_TOKEN>&country=US&region=CA&session=run42",
);
const page = await browser.contexts()[0].newPage();

// Everything below is ordinary Playwright, on a browser you hold open.
await page.goto("https://example.com/login");
await page.fill("#email", process.env.ACCOUNT_EMAIL);
await page.fill("#password", process.env.ACCOUNT_PASSWORD);
await page.click("button[type=submit]");
await page.waitForSelector("[data-testid=dashboard]");

console.log(await page.title());
await browser.close();

// Build or buy

The real question is who runs the browser

A scraping endpoint hands you the page it fetched. A browser lets you log in, fill a form and wait for what you came for. The difference is structural.

  • Interaction

    Scraping API
    One request in, one response out
    Self-hosted browsers
    Full CDP, once you run the browsers
    Wayfern
    Full CDP over one WebSocket: goto, fill, click, wait
  • Login state

    Scraping API
    Ends with the response
    Self-hosted browsers
    Yours to keep alive
    Wayfern
    Cookies and storage stay live while the socket is open
  • Isolation

    Scraping API
    Not exposed to the caller
    Self-hosted browsers
    Yours to build and enforce
    Wayfern
    A pooled instance is reused only for the same link token, workload and exit
  • Exit location

    Scraping API
    Whatever the vendor exposes
    Self-hosted browsers
    Whatever your proxy vendor exposes, wired by hand
    Wayfern
    Country, region, city and ISP, plus a sticky session id
  • Who maintains it

    Scraping API
    The vendor, on their roadmap
    Self-hosted browsers
    You: pool, upgrades, proxy wiring, driver versions
    Wayfern
    We run the pool; you keep your Playwright code

// Exits

Down to the city and the carrier

Location is part of the connection URL, not a separate proxy integration. Add country for a residential exit there; narrow it with region, city and isp. Leave them off for the default datacenter exit, whose egress is free.

  • country

    Type
    string
    What it does
    ISO-3166 country code of the residential exit, e.g. "US". Required to enable residential location targeting; omit for the default exit. See GET /api/proxy/locations.
  • region

    Type
    string
    What it does
    Region/state code within the country, e.g. "CA". Optional; narrows the exit.
  • city

    Type
    string
    What it does
    City code within the country/region. Optional; narrows the exit.
  • isp

    Type
    string
    What it does
    ISP code. Optional; narrows the exit to a carrier.
  • session

    Type
    string
    What it does
    Sticky-session id ([A-Za-z0-9]+). When set, the same residential exit IP is held for the session TTL so a multi-step flow keeps one IP.
Every code is checked against the live catalog before the browser is handed over; an unknown location is refused with close code 4007 instead of falling back to the wrong place. The catalog is served at GET /api/proxy/locations, GET /api/proxy/locations/countries, GET /api/proxy/locations/regions?country=US, GET /api/proxy/locations/cities?country=US&region=CA, GET /api/proxy/locations/isps?country=US and returns code / name pairs you can feed back into the URL.

// What it costs

Metered by the open page

Sessions draw on the same credit balance as the Web Data API. The exit you choose is usually the bigger line.

A one-hour run on a residential exit

One page held open for an hour, logged in, on a sticky residential IP.

Credits for: A one-hour run on a residential exit
ItemCredits
1 page open for 60 minutes8
0.15 GB residential traffic (320 / GB)48

Total

56credits

about $0.70
at $0.0125 / credit

About 27 runs a month on Developer ($19 for 1,520 credits).

The same hour on the datacenter exit

No location params: the default exit, whose egress is free.

Credits for: The same hour on the datacenter exit
ItemCredits
1 page open for 60 minutes8
Datacenter egress0

Total

8credits

about $0.10
at $0.0125 / credit

About 190 runs a month on Developer ($19 for 1,520 credits).

Every page you open is billed for at least 60 seconds. Full rates, plans and credit packs are on the pricing page.

// FAQ

Before you connect

How long does a new session take to start?

Plan for a cold start. A new browser takes about 45 to 50 seconds to be ready, and up to about 80 seconds with a residential exit, because there is no pre-started pool for CDP sessions. Set your connect timeout above that.

Is the browser headless?

No. The Wayfern Chromium build runs headed on a virtual display (Xvfb) inside our containers, so there is nothing to install or display on your side.

How is a session billed?

Per open page, pro-rated from 8 credits per open-page hour, with a 60-second minimum on every page you open. Two pages for half an hour cost the same as one page for an hour. Residential traffic adds 320 credits per GB; datacenter egress is free. At zero balance the next connection is refused with close code 4005.

Do sessions keep cookies between runs?

No. There are no persistent customer profiles: cookies and storage live for as long as your socket is open. A browser instance is shared only by open connections with the same link token and exit location, and it is removed when the last of them closes.

When should I use the Web Data API instead?

When you only need the page. A session suits logins, forms and multi-step flows. For a single fetch, scrape costs 1 credit per page and a screenshot 5 per capture, from the same balance.

Which clients can connect?

Anything that speaks the Chrome DevTools Protocol over a WebSocket: Playwright's connectOverCDP (Node or Python), Puppeteer's connect, or a raw CDP client.

// Next step

Point your existing script at a hosted browser

Create a project, mint a link token, and change one line: the connect URL. The rest of your Playwright or Puppeteer code stays as it is.