Browser
Drive a hosted browser from a local Playwright script, signed in with a saved profile, for sites with no API or data behind a login wall.
Some work has no API: a portal that only renders in a browser, a report behind a login, a page that needs a real session. geni browser opens a hosted browser you drive from your own machine over the Chrome DevTools Protocol, exactly the way the platform's agents do it.
A saved browser (a profile) holds the cookies and storage of the sites you have signed in to. Open a session with --profile and it arrives signed in; close it and the session state is saved back.
geni browser profileslists your browser and the ones teammates shared with you.geni browser openopens a hosted session and prints its CDP URL.geni browser closesaves the login and stops billing.geni browser request-loginsigns in to a site on your own browser through a live view.geni browser report-loginrecords whether a saved login still works.
The flow
geni browser profiles # find your browser id and its logins
geni browser open --profile bprof_01HX # arrives signed in
geni exec bash -- 'node scrape.js' # GI_BROWSER_CDP_URL is exported for you
geni browser close # always, including after failuresWhile a session is open, geni exec bash exports GI_BROWSER_CDP_URL (and a NO_PROXY carve-out for it) into the subprocess. Connect with playwright-core:
import { chromium } from 'playwright-core'
const browser = await chromium.connectOverCDP(process.env.GI_BROWSER_CDP_URL)
const page =
browser.contexts()[0].pages()[0] ?? (await browser.contexts()[0].newPage())
await page.goto('https://portal.example.com/reports')
console.log(await page.title())
await browser.close()Run it with node, not bun. No --cred is needed for the browser itself.
Sessions and billing
One session at a time. A session bills hosted browser time until it is closed. A detached keepalive holds the lease while your script runs, and a forgotten session force-closes after two hours so a mistake bills bounded time. Close it yourself as soon as the script is done.
Login walls
When a script hits a real sign-in form (a restricted page bounced to login, not a homepage that merely shows a Sign in button):
- On your own browser, run
request-login <domain>. A live view opens in your real browser; you sign in (2FA and all), the login is verified and saved, and the nextopen --profilearrives signed in. - On a browser a teammate shared, run
report-login <domain> logged_outand ask its owner to reconnect it.