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
.
connectOverCDP
Method (Recommended)
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
- Always close browsers and contexts to free up resources
- Use connection pooling for high-throughput applications
- Implement retry logic for network failures
- Monitor performance metrics to optimize your automation
- Use appropriate timeouts for different operations
- Handle errors gracefully with proper cleanup
- Leverage Browserless-specific features like stealth mode and built-in proxies