Browser
Use Browser to run named server-side automations against Playwright, Browserbase, or Cloudflare Browser Rendering. Definitions receive browser, capabilities, native, and context, then call helpers such as content(), screenshot(), pdf(), snapshot(), links(), markdown(), json(), scrape(), and crawl().
Define browsers in server/browsers/** with defineBrowser(handler, options?), then run them with runBrowser().
Getting started
Install the package
Install @vitehub/browser and the SDK for the provider you plan to use.
pnpm add https://pkg.pr.new/vite-hub/vitehub/@vitehub/browser@main cloudflare
Configure a provider
On Cloudflare, ViteHub usually uses the Cloudflare browser provider. On Vercel, it usually uses Browserbase. On Netlify, it uses Playwright when PLAYWRIGHT_WS_ENDPOINT is present. Set browser.provider when local development or another host should force a provider explicitly.
export default defineNuxtConfig({
modules: ['@vitehub/browser/nuxt'],
browser: {
provider: 'cloudflare',
accountId: process.env.CLOUDFLARE_ACCOUNT_ID,
},
})
Define a browser
Browser definitions accept portable execution defaults: timeout, session, and viewport. Set the default budget once on the definition, then add per-call or per-step timeouts only when a specific action genuinely needs a different limit.
export default defineBrowser(async (payload: { url: string }, { browser, context }) => {
const snapshot = await browser.snapshot({
screenshot: {
fullPage: true,
},
url: payload.url,
})
return {
context,
html: snapshot.content,
screenshot: snapshot.screenshot,
}
}, {
timeout: 10_000,
viewport: {
width: 1440,
height: 900,
},
})
Run the browser
Import runBrowser() from @vitehub/browser in Vite apps and pass the browser name with a payload. In Nitro and Nuxt, runBrowser() and readValidatedPayload() are auto-imported when @vitehub/browser/nuxt or @vitehub/browser/nitro is registered. Set nitro.imports.autoImport = false in nitro.config.ts or nuxt.config.ts when you want to disable ViteHub's Nitro auto-imports and use explicit imports instead. Use getBrowser() when you want direct access to the active browser client.
import { readBody } from 'h3'
export default defineEventHandler(async (event) => {
const input = await readValidatedPayload(await readBody(event), (value) => {
if (!value || typeof value !== 'object' || typeof value.url !== 'string')
throw new Error('A valid URL is required.')
return { url: value.url }
})
return await runBrowser('snapshot-homepage', input, {
context: {
requestId: crypto.randomUUID(),
},
})
})
Public API
| Function | Use it for |
|---|---|
defineBrowser(handler, options?) | Register one named browser with the direct (handler, options?) form. |
createBrowser(options?)(handler) | Register one named browser with the curried form. |
runBrowser(name, payload?, options?) | Execute a named browser definition. |
getBrowser(name) | Resolve the active browser client directly. |
Use runBrowser() for the common case. Switch to getBrowser() when you need the browser client itself, want to branch on browser.capabilities, or want the raw SDK object through browser.native.