Playwright is a modern automation framework that supports multiple browsers including Chromium, Firefox, and WebKit (Safari). This guide shows you how to set up Playwright for cross-browser testing and automation.
Installation
JavaScript/Node.js
Install Playwright and all browser binaries:
npm install playwright
For specific browsers only:
npm install playwright-chromium  # Chromium only
npm install playwright-firefox   # Firefox only
npm install playwright-webkit    # WebKit only
Python
Install Playwright for Python:
pip install playwright
playwright install
Install specific browsers:
playwright install chromium
playwright install firefox
playwright install webkit
.NET
dotnet add package Microsoft.Playwright
playwright install
Basic Multi-Browser Setup
JavaScript Example
const { chromium, firefox, webkit } = require('playwright');
async function runOnAllBrowsers() {
  const browsers = [
    { name: 'chromium', engine: chromium },
    { name: 'firefox', engine: firefox },
    { name: 'webkit', engine: webkit }
  ];
  for (const { name, engine } of browsers) {
    console.log(`Testing on ${name}...`);
    const browser = await engine.launch({ headless: false });
    const context = await browser.newContext();
    const page = await context.newPage();
    await page.goto('https://example.com');
    await page.screenshot({ path: `screenshot-${name}.png` });
    await browser.close();
  }
}
runOnAllBrowsers();
Python Example
from playwright.sync_api import sync_playwright
def run_on_all_browsers():
    with sync_playwright() as p:
        browsers = [
            ('chromium', p.chromium),
            ('firefox', p.firefox),
            ('webkit', p.webkit)
        ]
        for name, browser_type in browsers:
            print(f"Testing on {name}...")
            browser = browser_type.launch(headless=False)
            context = browser.new_context()
            page = context.new_page()
            page.goto('https://example.com')
            page.screenshot(path=f'screenshot-{name}.png')
            browser.close()
run_on_all_browsers()
Advanced Multi-Browser Configuration
Parallel Execution
Run tests across multiple browsers simultaneously:
const { chromium, firefox, webkit } = require('playwright');
async function parallelBrowserTest() {
  const browsers = [chromium, firefox, webkit];
  const promises = browsers.map(async (browserType, index) => {
    const browser = await browserType.launch();
    const context = await browser.newContext();
    const page = await context.newPage();
    await page.goto('https://example.com');
    const title = await page.title();
    console.log(`Browser ${index + 1} title: ${title}`);
    await browser.close();
    return title;
  });
  const results = await Promise.all(promises);
  console.log('All browsers finished:', results);
}
parallelBrowserTest();
Browser-Specific Configuration
const { chromium, firefox, webkit } = require('playwright');
async function configureBrowsers() {
  // Chromium with custom args
  const chromiumBrowser = await chromium.launch({
    headless: false,
    args: ['--start-maximized', '--disable-web-security']
  });
  // Firefox with custom preferences
  const firefoxBrowser = await firefox.launch({
    headless: false,
    firefoxUserPrefs: {
      'media.navigator.streams.fake': true
    }
  });
  // WebKit with device emulation
  const webkitBrowser = await webkit.launch({ headless: false });
  const webkitContext = await webkitBrowser.newContext({
    userAgent: 'Mozilla/5.0 (iPad; CPU OS 15_0 like Mac OS X) AppleWebKit/605.1.15'
  });
  // Use browsers...
  await chromiumBrowser.close();
  await firefoxBrowser.close();
  await webkitBrowser.close();
}
configureBrowsers();
Cross-Browser Test Runner
const { test, expect } = require('@playwright/test');
// Define browsers to test
const browsers = ['chromium', 'firefox', 'webkit'];
browsers.forEach(browserName => {
  test.describe(`Tests on ${browserName}`, () => {
    test.use({ browserName });
    test('should load homepage', async ({ page }) => {
      await page.goto('https://example.com');
      await expect(page).toHaveTitle(/Example/);
    });
    test('should handle form submission', async ({ page }) => {
      await page.goto('https://example.com/contact');
      await page.fill('#name', 'Test User');
      await page.click('#submit');
      await expect(page.locator('.success')).toBeVisible();
    });
  });
});
Browser Detection and Capabilities
async function detectBrowserCapabilities() {
  const browsers = [
    { name: 'Chromium', engine: chromium },
    { name: 'Firefox', engine: firefox },
    { name: 'WebKit', engine: webkit }
  ];
  for (const { name, engine } of browsers) {
    const browser = await engine.launch();
    const context = await browser.newContext();
    const page = await context.newPage();
    // Get browser version
    const version = browser.version();
    console.log(`${name} version: ${version}`);
    // Test specific features
    await page.goto('data:text/html,<html><body><h1>Test</h1></body></html>');
    const userAgent = await page.evaluate(() => navigator.userAgent);
    console.log(`${name} User Agent:`, userAgent);
    await browser.close();
  }
}
detectBrowserCapabilities();
Best Practices
- Resource Management: Always close browsers to free resources
- Error Handling: Wrap browser operations in try-catch blocks
- Parallel Testing: Use Promise.all() for faster execution
- Browser Selection: Choose browsers based on your target audience
- Configuration: Use environment variables for browser selection in CI/CD
Troubleshooting
- Installation Issues: Run playwright install-depsfor system dependencies
- Browser Not Found: Ensure browsers are installed with playwright install
- Permission Errors: Check file permissions for browser binaries
- Memory Issues: Limit concurrent browser instances in resource-constrained environments