Introduction
Playwright connects to BotCloud through CDP (Chrome DevTools Protocol). If you already use Playwright, the change is minimal: replace browser.launch() with browser.connectOverCDP(). All Playwright APIs work the same way.
Prerequisites
- Node.js 18 or later
playwrightorplaywright-corepackage- A BotCloud API key from bots.win
npm install playwright-core
Basic Connection
const { chromium } = require('playwright-core');
async function main() {
const browser = await chromium.connectOverCDP(
'wss://cloud.bots.win?token=YOUR_TOKEN'
);
const context = browser.contexts()[0];
const page = context.pages()[0] || await context.newPage();
await page.goto('https://example.com');
console.log('Title:', await page.title());
await browser.close();
}
main().catch(console.error);
Common Patterns
Screenshot and PDF
const page = context.pages()[0] || await context.newPage();
// Screenshot
await page.goto('https://example.com', { waitUntil: 'networkidle' });
await page.screenshot({ path: 'screenshot.png', fullPage: true });
// PDF
await page.pdf({ path: 'output.pdf', format: 'A4' });
Waiting for Elements
Playwright's auto-waiting is one of its strongest features and works identically with cloud browsers:
// Wait for element to be visible
await page.waitForSelector('.content-loaded');
// Wait for network to settle
await page.goto(url, { waitUntil: 'networkidle' });
// Wait for specific response
const response = await page.waitForResponse(
resp => resp.url().includes('/api/data') && resp.status() === 200
);
Data Extraction with Locators
const page = context.pages()[0] || await context.newPage();
await page.goto('https://example.com/products');
// Use Playwright's locator API
const products = await page.locator('.product-card').evaluateAll(cards =>
cards.map(card => ({
name: card.querySelector('.name')?.textContent?.trim(),
price: card.querySelector('.price')?.textContent?.trim(),
}))
);
Form Interaction
await page.goto('https://example.com/login');
await page.fill('#email', 'user@example.com');
await page.fill('#password', 'secret');
await page.click('button[type="submit"]');
await page.waitForURL('**/dashboard');
Network Interception
await page.route('**/*.{png,jpg,jpeg,gif,svg}', route => route.abort());
await page.route('**/api/analytics', route => route.abort());
await page.goto('https://example.com'); // Loads faster without images
With Proxy
const browser = await chromium.connectOverCDP(
'wss://cloud.bots.win?token=YOUR_TOKEN&--proxy-server=socks5h://user:pass@proxy.example.com:1080'
);
Python Example
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(
'wss://cloud.bots.win?token=YOUR_TOKEN'
)
context = browser.contexts[0]
page = context.pages[0] if context.pages else context.new_page()
page.goto('https://example.com')
print('Title:', page.title())
browser.close()
Migration from Local Playwright
// Before
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext();
const page = await context.newPage();
// After
const browser = await chromium.connectOverCDP(
'wss://cloud.bots.win?token=YOUR_TOKEN'
);
const context = browser.contexts()[0];
const page = context.pages()[0] || await context.newPage();
// Everything below stays the same
Error Handling
async function automateWithPlaywright(url) {
const browser = await chromium.connectOverCDP(
'wss://cloud.bots.win?token=YOUR_TOKEN'
);
try {
const context = browser.contexts()[0];
const page = context.pages()[0] || await context.newPage();
await page.goto(url, { timeout: 30000 });
return await page.content();
} finally {
await browser.close();
}
}
Next Steps
- Puppeteer Integration Guide - If you prefer Puppeteer
- Scaling Browser Automation - Running at scale
- Proxy Configuration - Geographic distribution
#playwright#tutorial#integration#javascript