Skip to content

Introduction to Playwright

Playwright is Microsoft's open-source browser automation library for reliable end-to-end and API testing across Chromium, Firefox, and WebKit. This introduction explains what Playwright is, how it differs from older WebDriver tools, and why it has become a leading choice for modern web applications.

What Is Playwright?

Playwright is a Node.js library (with bindings for Python, Java, and .NET) that lets you drive real browsers through a single, consistent API. It ships with a built-in test runner, auto-waiting, powerful locators, network interception, trace recording, and first-class TypeScript support.

Unlike classic Selenium WebDriver, Playwright communicates with browsers over a modern, bidirectional protocol and runs each test in an isolated browser context. That isolation, combined with automatic waiting on actions and assertions, dramatically reduces the flakiness that plagued older automation stacks.

import { test, expect } from '@playwright/test';

test('homepage shows welcome message', async ({ page }) => {
  await page.goto('/');
  await expect(page.getByRole('heading', { name: 'Welcome' })).toBeVisible();
});

A complete Playwright test: navigate, locate by accessible role, and assert visibility — with auto-waiting built in.

How a Playwright Test Is Structured

import { test, expect } from '@playwright/test';

test.describe('feature name', () => {
  test('does something specific', async ({ page }) => {
    // actions and assertions
  });
});
  • test.describe() groups related tests into a readable block.
  • test() defines a single test case with a clear description.
  • The page fixture provides a browser tab for navigation and interaction.
  • expect() from @playwright/test includes web-first assertions that auto-retry.
  • Spec files live in a tests/ folder by default and use .spec.ts naming.

Playwright at a Glance

Core ideas you will use in nearly every Playwright test.

Concept Example Purpose
Navigate await page.goto('/login') Load a URL in the browser tab
Locate by role page.getByRole('button', { name: 'Save' }) Find elements the way users and assistive tech do
Interact .click(), .fill('text') Simulate user actions with auto-waiting
Assert await expect(locator).toBeVisible() Verify expected state with retries
Group tests test.describe('...', () => {}) Organize related scenarios
Run headless npx playwright test Execute the full suite in CI
Run with UI npx playwright test --ui Debug interactively in UI Mode
Mock network await page.route('**/api/**', handler) Control API responses during tests
Record trace trace: 'on-first-retry' in config Capture debugging artifacts on failure

How Playwright Architecture Differs from WebDriver

Classic WebDriver sends one-way commands to a browser driver over HTTP. Playwright instead maintains a persistent connection to each browser engine and can observe events, intercept network traffic, and execute code in multiple isolated contexts within one browser process.

Each test gets a fresh browser context by default — equivalent to an incognito profile with its own cookies, storage, and permissions. That design makes parallel execution and test isolation straightforward without spinning up separate browser instances for every test.

  • Single API across Chromium, Firefox, and WebKit.
  • Browser contexts provide cookie/storage isolation per test.
  • Auto-waiting on locators, actions, and web assertions.
  • Built-in network routing, tracing, and video/screenshot capture.

What You Can Test with Playwright

Playwright supports end-to-end testing of full user journeys, API testing via APIRequestContext, component testing for React/Vue/Svelte, and accessibility scans via integrations like @axe-core/playwright.

Testing Type Description
End-to-end (E2E) Full user flows through real browsers
API testing Direct HTTP calls via request fixture or APIRequestContext
Component testing Mount individual UI components in isolation
Visual regression Screenshot comparisons with toHaveScreenshot()

Common Mistakes

  • Assuming Playwright works like Cypress — Playwright runs out-of-process and supports multiple tabs, contexts, and languages.
  • Skipping the official Trace Viewer when debugging failures; it replaces much guesswork.
  • Treating Playwright as Chromium-only when Firefox and WebKit are first-class engines.
  • Writing tests without await on async Playwright calls, causing race conditions.

Key Takeaways

  • Playwright is a cross-browser automation library with a built-in test runner and TypeScript-first API.
  • Browser contexts isolate cookies and storage, enabling safe parallel execution.
  • Auto-waiting on actions and expect() assertions reduces manual wait logic.
  • Playwright covers E2E, API, component, and accessibility testing from one toolchain.

Pro Tip

Before writing your first real test, run npx playwright codegen <url> on your app. Watching Playwright generate locators live teaches the recommended getByRole patterns faster than reading docs alone.