Skip to main content
Version: v2

Playwright Customizations

This page covers advanced Playwright configurations and customizations when working with Browserless.

Migrating from Local Chrome to Browserless

Let's take a simple example of using playwright in a script. To migrate from local Chrome to Browserless, you need to change from chromium.launch() to chromium.connectOverCDP() with a WebSocket endpoint.

Optional optimization: You can also switch from playwright to playwright-core (which doesn't include browser binaries) since you'll be connecting to remote browsers instead of launching local ones:

Before Browserless

import { chromium } from "playwright";

const browser = await chromium.launch();
const page = await browser.newPage();
// ...

After Browserless

import { chromium } from "playwright-core";

const browser = await chromium.connectOverCDP(
`wss://production-sfo.browserless.io?token=YOUR_API_TOKEN_HERE`
);
const page = await browser.newPage();
// ...

Connection Methods

Browserless supports two connection methods for Playwright: connectOverCDP and connect.

The connectOverCDP method uses Chrome's DevTools Protocol and is the recommended approach for connecting to Browserless. This method allows you to experience advanced Browserless capabilities like stealth flag, in-built proxies, and more. It provides a stable and reliable connection for most automation tasks.

Note: connectOverCDP is only supported by Chrome-based browsers. For other browsers like Firefox or WebKit, you must use the connect method.

connect Method

Playwright's connect method uses its built-in browser-server protocol. While this method can be faster in some cases, it has some limitations:

  • Your client's Playwright version must match the server's version
  • Limited support for Browserless advanced features such as the stealth flag, in-built proxies, and more

Here's how to use the connect method:

import { chromium } from "playwright-core";

// Connect using Playwright's built-in protocol
const browser = await chromium.connect(
`wss://production-sfo.browserless.io/chrome/playwright?token=${TOKEN}`
);

Warning: To avoid errors with no apparent reason, please make sure your playwright version is compatible with one of these versions.

Using Other Browsers

Since connectOverCDP is only supported by Chrome-based browsers, you must use the connect method for Firefox and WebKit. While Chrome is recommended for most use cases, Browserless also supports these other browsers:

Firefox Example

import { firefox } from "playwright-core";

// Connect to Firefox using the connect method (required for non-Chrome browsers)
const browser = await firefox.connect(
`wss://production-sfo.browserless.io/firefox/playwright?token=${TOKEN}`
);
const context = await browser.newContext();
const page = await context.newPage();

// Navigate to target website
await page.goto("https://www.example.com/");
// Take a screenshot with Firefox
await page.screenshot({ path: "firefox-screenshot.png" });

// Clean up resources
await browser.close();

WebKit Example

import { webkit } from "playwright-core";

// Connect to WebKit using the connect method (required for non-Chrome browsers)
const browser = await webkit.connect(
`wss://production-sfo.browserless.io/webkit/playwright?token=${TOKEN}`
);
const context = await browser.newContext();
const page = await context.newPage();

// Navigate to target website
await page.goto("https://www.example.com/");
// Take a screenshot with WebKit
await page.screenshot({ path: "webkit-screenshot.png" });

// Clean up resources
await browser.close();

Important: When using Firefox or WebKit, you must use the connect method as CDP is only supported by Chrome-based browsers.

Session Timeout Configuration

BaaS sessions timer can be overridden. Refer to the Launch Options page to learn how to configure custom session timeouts.

Advanced Browser Context Options

When creating browser contexts with Playwright, you can leverage Browserless-specific features:

import { chromium } from "playwright-core";

const browser = await chromium.connectOverCDP(
"wss://production-sfo.browserless.io?token=YOUR_API_TOKEN"
);

// Create context with advanced options
const context = await browser.newContext({
// Browserless-specific stealth options
extraHTTPHeaders: {
'User-Agent': 'Custom User Agent String'
},

// Viewport and device emulation
viewport: { width: 1920, height: 1080 },
deviceScaleFactor: 1,

// Geolocation
geolocation: { longitude: -122.4194, latitude: 37.7749 },
permissions: ['geolocation']
});

const page = await context.newPage();

Performance Optimization Tips

Use playwright-core Instead of playwright

Since you're connecting to remote browsers, you don't need the full Playwright package with browser binaries:

# Instead of: npm install playwright
npm install playwright-core

Connection Pooling

For high-throughput applications, consider implementing connection pooling:

class BrowserlessConnectionPool {
constructor(maxConnections = 5) {
this.maxConnections = maxConnections;
this.connections = [];
this.available = [];
}

async getConnection() {
if (this.available.length > 0) {
return this.available.pop();
}

if (this.connections.length < this.maxConnections) {
const browser = await chromium.connectOverCDP(
`wss://production-sfo.browserless.io?token=${TOKEN}`
);
this.connections.push(browser);
return browser;
}

// Wait for an available connection
return new Promise(resolve => {
const checkAvailable = () => {
if (this.available.length > 0) {
resolve(this.available.pop());
} else {
setTimeout(checkAvailable, 100);
}
};
checkAvailable();
});
}

releaseConnection(browser) {
this.available.push(browser);
}
}

Error Handling and Retry Logic

Implement robust error handling for network issues:

async function connectWithRetry(maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const browser = await chromium.connectOverCDP(
`wss://production-sfo.browserless.io?token=${TOKEN}`
);
return browser;
} catch (error) {
if (i === maxRetries - 1) throw error;

console.log(`Connection attempt ${i + 1} failed, retrying...`);
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}

Browser-Specific Optimizations

Chrome/Chromium Optimizations

const browser = await chromium.connectOverCDP(
`wss://production-sfo.browserless.io?token=${TOKEN}`
);

const context = await browser.newContext({
// Disable images for faster loading
bypassCSP: true,

// Custom user agent
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',

// Disable JavaScript (if not needed)
// javaScriptEnabled: false,

// Custom viewport
viewport: { width: 1366, height: 768 }
});

Firefox Optimizations

const browser = await firefox.connect(
`wss://production-sfo.browserless.io/firefox/playwright?token=${TOKEN}`
);

const context = await browser.newContext({
// Firefox-specific options
locale: 'en-US',
timezoneId: 'America/New_York',

// Custom preferences
extraPrefsFirefox: {
'dom.webdriver.enabled': false,
'useAutomationExtension': false
}
});

Debugging and Troubleshooting

Enable Debug Logging

// Set environment variable for debug logging
process.env.DEBUG = 'pw:api';

const browser = await chromium.connectOverCDP(
`wss://production-sfo.browserless.io?token=${TOKEN}`
);

Network Interception

const page = await context.newPage();

// Intercept network requests for debugging
await page.route('**/*', route => {
console.log('Request:', route.request().url());
route.continue();
});

// Intercept specific requests
await page.route('**/*.{png,jpg,jpeg,gif,svg}', route => {
console.log('Image request:', route.request().url());
route.continue();
});

Performance Monitoring

const page = await context.newPage();

// Monitor page performance
const performanceMetrics = await page.evaluate(() => {
const navigation = performance.getEntriesByType('navigation')[0];
return {
domContentLoaded: navigation.domContentLoadedEventEnd - navigation.domContentLoadedEventStart,
loadComplete: navigation.loadEventEnd - navigation.loadEventStart,
totalTime: navigation.loadEventEnd - navigation.fetchStart
};
});

console.log('Performance metrics:', performanceMetrics);

Best Practices

  1. Always close browsers and contexts to free up resources
  2. Use connection pooling for high-throughput applications
  3. Implement retry logic for network failures
  4. Monitor performance metrics to optimize your automation
  5. Use appropriate timeouts for different operations
  6. Handle errors gracefully with proper cleanup
  7. Leverage Browserless-specific features like stealth mode and built-in proxies