Point Playwright at the real, signed-in Chrome of a person or a test machine. One package, two variables, and the rest is Playwright as you already write it.
Three things have to be true:
Install @tabtunnel/playwright. It connects Playwright to your
browser in place of launching a local Chromium, and handles signing in with your
token.
pnpm add -D @tabtunnel/playwright @playwright/test
# or: npm i -D @tabtunnel/playwright @playwright/test
Set two variables. The token is the one from the dashboard's Tokens page.
export TABTUNNEL_URL=https://tabtunnel.dev
export TABTUNNEL_TOKEN=tt_live_…
Then import test from here instead of from
@playwright/test, and write the test you would have written
anyway:
import { test, expect } from '@tabtunnel/playwright/test'
test('the dashboard loads', async ({ page }) => {
await page.goto('https://app.example.com/')
await expect(page.locator('h1')).toHaveText('Welcome back')
})
That is the whole of it. page, context, locators and
expect are Playwright's own and behave as they always do — the
browser fixture is the only one replaced, and it is worker-scoped,
so a worker connects once and every test in it gets a fresh context and page on
that connection.
connect() hands you a Playwright Browser and asks for
nothing else. Use it from a script, a job, or any runner that is not
@playwright/test.
import { connect } from '@tabtunnel/playwright'
const browser = await connect() // or connect({ url, token, browser, foreground, timeout })
const page = await browser.newPage()
await page.goto('https://example.com/')
console.log(await page.title())
await browser.close() // disconnects; TabTunnel closes the tabs it opened
An explicit option wins over the environment variable of the same name.
npx tabtunnel-playwright doctor
It reads the same variables and tells you which browser your tests would use, or why they cannot connect — without starting anything. Run it first whenever a suite will not connect.
TABTUNNEL_URL | The address above, starting https://. Plain http:// is accepted only for localhost. |
TABTUNNEL_TOKEN | Your tt_live_… token. It is never printed. |
TABTUNNEL_BROWSER | Optional. Which browser to use, by its id — shown on the extension's “connected” screen, and the last part of the browser's page address in the dashboard. Leave it out if only one browser you can use has CDP on. |
TABTUNNEL_FOREGROUND | Optional. 1 opens pages in front, where the person at the browser can watch. |
TABTUNNEL_TIMEOUT_MS | Optional. How long to wait for a connection, in milliseconds. Default 30 000, which covers a browser that has to reconnect first. |
It is a real person's Chrome, with their profile, driven through the extension. So it behaves differently from the fresh Chromium Playwright usually launches:
newContext() works, but every context is the same profile, so
tests are not isolated from each other.window.open does not reach your test, and no
page event fires.expect timeouts generous.goto to a new
site asks the person at the browser and the test waits. For a browser kept for
testing, choose Allow everything.Each of these comes back with a code and a message saying what to do.
CDP_DISABLED | CDP is off for that browser. Open it from Browsers and press Switch CDP on. If it is already on, check Billing — your plan may have no CDP browsers left. |
NO_CDP_BROWSER | None of the browsers your token can use has CDP on. Switch it on for one, or set TABTUNNEL_BROWSER to the one you meant. |
AMBIGUOUS_BROWSER | More than one browser could be used. Set TABTUNNEL_BROWSER to pick one. |
READ_ONLY | That browser is shared with you to view only. Ask its owner to let you use it. |
BROWSER_OFFLINE | Chrome is closed, or the extension is signed out. Open Chrome and check the extension. |
SESSION_CEILING | Too many connections are already open with this token. Use fewer workers, or stop a run that is still going. |
A running connection is checked every ten seconds and closed, with a reason, as soon as it may no longer be used:
paused | The browser's owner paused it. It works again once they resume it. |
revoked | Your token was stopped, or you can no longer use this browser. Create a new token, or ask the owner. |
cdp_disabled | CDP was switched off for the browser, or your plan no longer includes it. |
read_only | The browser is now shared with you to view only. |
slow_consumer · event_flood | A page sent events faster than your test could read them. Usually a page that logs or animates heavily; run fewer tests at once against it. |
Is something here wrong, or missing? Tell us.