Connect
Copy
import { playwright } from '@bctrl/sdk';
const session = await playwright.connect({
apiKey: process.env.BCTRL_API_KEY,
sessionOptions: {
humanize: true, // Human-like mouse movements
useStealth: true, // Anti-detection
screen: { width: 1920, height: 1080 }
}
});
Session Structure
Copy
session.browser // RemotePlaywrightBrowser
session.context // RemotePlaywrightBrowserContext (default)
session.page // RemotePlaywrightPage (default)
Navigation
Copy
const page = session.page;
await page.goto('https://example.com');
await page.goto('https://example.com', { waitUntil: 'networkidle' });
await page.goBack();
await page.goForward();
await page.reload();
const url = page.url();
const title = await page.title();
Locators
Playwrightβs locator API is fully supported:Copy
// CSS selectors
await page.locator('button').click();
await page.locator('.submit-btn').click();
await page.locator('#email').fill('[email protected]');
// Text selectors
await page.locator('text=Sign In').click();
await page.getByText('Submit').click();
// Role selectors
await page.getByRole('button', { name: 'Submit' }).click();
await page.getByRole('textbox', { name: 'Email' }).fill('[email protected]');
// Other selectors
await page.getByLabel('Email').fill('[email protected]');
await page.getByPlaceholder('Enter email').fill('[email protected]');
await page.getByTestId('submit-button').click();
// Chaining
await page.locator('form').locator('button[type="submit"]').click();
Actions
Copy
// Click
await page.locator('button').click();
await page.locator('button').dblclick();
await page.locator('button').click({ button: 'right' });
// Type
await page.locator('input').fill('Hello World');
await page.locator('input').type('Hello', { delay: 100 });
await page.locator('input').press('Enter');
// Select
await page.locator('select').selectOption('value');
await page.locator('select').selectOption({ label: 'Option 1' });
// Checkbox
await page.locator('input[type="checkbox"]').check();
await page.locator('input[type="checkbox"]').uncheck();
// Hover
await page.locator('button').hover();
Getting Content
Copy
// Text
const text = await page.locator('h1').innerText();
const html = await page.locator('div').innerHTML();
// Attributes
const href = await page.locator('a').getAttribute('href');
const value = await page.locator('input').inputValue();
// Multiple elements
const items = await page.locator('li').allInnerTexts();
const count = await page.locator('li').count();
Waiting
Copy
// Wait for element
await page.locator('button').waitFor();
await page.locator('button').waitFor({ state: 'visible' });
// Wait for navigation
await page.waitForURL('**/dashboard');
await page.waitForLoadState('networkidle');
// Wait for response
const response = await page.waitForResponse('**/api/data');
Screenshots
Copy
// Full page
await page.screenshot({ path: 'page.png' });
await page.screenshot({ path: 'full.png', fullPage: true });
// Element
await page.locator('header').screenshot({ path: 'header.png' });
// As buffer
const buffer = await page.screenshot();
Evaluate JavaScript
Copy
// Simple evaluation
const title = await page.evaluate(() => document.title);
// With arguments
const text = await page.evaluate(
(selector) => document.querySelector(selector)?.textContent,
'h1'
);
// Return complex data
const data = await page.evaluate(() => ({
url: window.location.href,
cookies: document.cookie
}));
Browser Contexts
Create isolated contexts with separate cookies/storage:Copy
// Create new context
const context = await session.browser.newContext();
const page = await context.newPage();
// Cookie management
await context.addCookies([
{ name: 'token', value: 'abc123', domain: 'example.com' }
]);
const cookies = await context.cookies();
await context.clearCookies();
// Storage state
const state = await context.storageState();
Multiple Pages
Copy
// Open new page
const page2 = await session.context.newPage();
await page2.goto('https://other-site.com');
// Work with both pages
await session.page.locator('button').click();
await page2.locator('input').fill('text');
AI Agents
Use AI for complex tasks:Copy
// Natural language actions
await session.stagehand.act('Click the login button');
await session.stagehand.act('Fill the email field with [email protected]');
// Extract structured data
import { z } from 'zod';
const products = await session.stagehand.extract(
'Get all product names and prices',
z.array(z.object({
name: z.string(),
price: z.number()
}))
);
// Autonomous agent
const agent = session.stagehand.agent({ maxSteps: 10 });
await agent.execute('Find and add the cheapest laptop to cart');
Full Example
Copy
import { playwright } from '@bctrl/sdk';
import { z } from 'zod';
async function scrapeHackerNews() {
const session = await playwright.connect({
apiKey: process.env.BCTRL_API_KEY
});
const page = session.page;
await page.goto('https://news.ycombinator.com');
// Traditional approach
const titles = await page.locator('.titleline > a').allInnerTexts();
console.log('Top stories:', titles.slice(0, 5));
// AI approach
const stories = await session.stagehand.extract(
'Get the top 5 stories with title, link, and points',
z.array(z.object({
title: z.string(),
url: z.string(),
points: z.number()
}))
);
console.log('AI extracted:', stories);
await session.close();
}
scrapeHackerNews();

