Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

To learn Playwright with Python, install the Playwright pytest plugin and its browser binaries, write one small test with a user-facing locator and a web-first assertion, then expand into fixtures, cross-browser projects, tracing, and CI. The examples below use the synchronous API so a beginner can follow one consistent style.

What Playwright with Python is—and which path to choose

Playwright is a browser-automation library that drives Chromium, Firefox, and WebKit. Python developers commonly use it in two complementary ways:

  • pytest-playwright: the recommended route for end-to-end tests. It supplies pytest fixtures such as page, integrates with test discovery, and gives you a familiar test-runner workflow.
  • The direct Playwright library: a general-purpose automation API for scripts, crawlers, one-off checks, and applications that already have their own runner.

Start with one style. For a test suite, choose pytest and the synchronous API unless your surrounding application is already asynchronous. You can learn the async API later without changing the core concepts: browser, context, page, locator, action, and assertion.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Install Playwright for Python

Prerequisites

The current Playwright Python introduction lists Python 3.8 or newer and supported Windows, macOS, Debian, and Ubuntu versions. Operating-system support and minimum versions can change, so check the current Playwright installation page when you set up a new machine.

Use a virtual environment so Playwright and pytest do not alter your system Python:

python -m venv .venv
# macOS/Linux
source .venv/bin/activate
# Windows PowerShell
.venvScriptsActivate.ps1
python -m pip install --upgrade pip

Recommended end-to-end test setup

  1. Install the pytest plugin:
    pip install pytest-playwright
  2. Download the browser binaries that match your installed Playwright version:
    playwright install
  3. Create a test file named tests/test_home.py.
  4. Run pytest:
    pytest

By default, the pytest integration runs headlessly on Chromium. Installing the Python package and installing browsers are separate operations; when you upgrade Playwright, rerun playwright install so the binaries match the package version.

Direct-library setup for scripts

If you are writing an automation script rather than a pytest suite, install the library directly:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
pip install playwright
playwright install

The library provides both synchronous and asynchronous APIs. Do not mix them in the same example or call synchronous methods from an active asyncio event loop.

Write your first Playwright pytest

This documented starter pattern navigates to a page, finds a link by its accessible role and name, clicks it, and checks a heading. Replace the example URL and names with controls that exist in your application.

from playwright.sync_api import Page, expect


def test_get_started_link(page: Page) -> None:
    page.goto("https://playwright.dev/")
    page.get_by_role("link", name="Get started").click()
    expect(page.get_by_role("heading", name="Installation")).to_be_visible()

Run only this test while you iterate:

pytest tests/test_home.py -q

The page fixture creates an isolated browser page for the test. Playwright actions wait for elements to become actionable, and expect assertions retry until the expected browser state is reached or the timeout expires. That is why a web-first assertion is preferable to a fixed sleep.

Locators that survive UI changes

A locator is a query that identifies an element when an action or assertion runs. Prefer selectors that describe how a user experiences the interface:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • get_by_role for buttons, links, headings, checkboxes, and other accessible roles.
  • get_by_label for form controls associated with a visible label.
  • get_by_text for stable, user-visible copy when a role or label is not appropriate.
  • get_by_test_id for an explicit testing contract such as data-testid="save-button".

Scope a locator when a page contains repeated controls:

dialog = page.get_by_role("dialog", name="Delete project")
dialog.get_by_role("button", name="Delete").click()
expect(dialog).to_be_hidden()

Avoid long CSS or XPath chains tied to layout and generated class names. If a locator matches more than one element, refine it with a role name, label, text, or a containing locator rather than selecting an arbitrary index. A unique accessible name also improves the accessibility of the application itself.

Assertions and synchronization

Use web-first assertions from playwright.sync_api.expect. Common checks include:

expect(page).to_have_title("Account")
expect(page.get_by_role("heading", name="Account")).to_be_visible()
expect(page.get_by_label("Email")).to_have_value("[email protected]")
expect(page.get_by_role("button", name="Save")).to_be_enabled()
expect(page.get_by_role("alert")).to_contain_text("Saved")

These assertions wait for the condition. A hard-coded time.sleep() waits the same amount whether the page is ready immediately or still loading, which creates slow or flaky tests. If an application has a real readiness condition, wait for that condition—for example, a specific response, selector, or state—rather than adding an arbitrary delay.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use Codegen as a starting point

Codegen can record your interactions and suggest locators. Start it with:

playwright codegen https://example.com

Interact with the page, then copy the generated Python actions into a test. Codegen can also generate visibility, text, and value assertions. Review every generated line: replace brittle selectors, add meaningful test data, separate setup from verification, and name the test after the behavior it protects. Generated code is scaffolding, not a finished test architecture.

Codegen can save authenticated browser storage state. That file may contain cookies and tokens. Keep it outside version control, add it to your ignore file, restrict its permissions, and delete it when no longer needed.

Run selected tests, headed browsers, and browser engines

Useful pytest commands

# one file
pytest tests/test_home.py
# one test by name
pytest -k get_started_link
# show browser while debugging
pytest --headed
# pause after a failure for inspection
pytest --headed --slowmo 200

Headless mode is efficient for routine runs. Headed mode lets you watch navigation and interaction, but it needs a display on a local machine or a CI virtual display.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Chromium, Firefox, and WebKit

Playwright supports Chromium, Firefox, and WebKit. Each Playwright release requires specific browser binaries, so keep package and binary installation in sync. A practical progression is:

  1. Run Chromium locally while the test and locator are changing.
  2. Add Firefox and WebKit once the behavior is stable.
  3. Choose a CI matrix based on the browsers your users actually rely on and the time your pipeline can afford.

Browser channels and mobile-device emulation are available when your compatibility requirements call for them. You do not need every device and channel on your first day.

Configure projects in pytest

The pytest plugin exposes browser selection through command-line options. For repeatable team and CI runs, keep shared settings in pytest.ini or pyproject.toml, then document the commands that exercise each target. A simple local check is to run the same test with Chromium, Firefox, and WebKit options provided by your installed plugin version; option names can change, so use pytest --help as the authoritative list for that version.

Debug failures with Inspector and traces

Playwright Inspector

Inspector can step through API calls, show action logs, and help you inspect locators. Launch a test with debugging enabled:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
PWDEBUG=1 pytest tests/test_home.py
# Windows PowerShell
$env:PWDEBUG="1"; pytest tests/test_home.py

Step through navigation and actions, verify which locator matched, and inspect the page at the point of failure. Remove the environment variable for normal runs.

Trace Viewer

Tracing records screenshots, snapshots, network details, and action timing for later inspection. Capture a trace for a failing or diagnostic run using the tracing options supported by your installed pytest plugin, then open the resulting archive with the Playwright trace viewer. In CI, retain traces for failed tests rather than every successful test to control storage and review time.

Design a maintainable test suite

  • Keep tests independent. Create the data a test needs and avoid relying on execution order.
  • Use fixtures for shared setup. A fixture can create an account, seed data, or provide a logged-in context while each test still gets isolation.
  • Separate behavior from mechanics. Page-object or helper methods are useful when they express a business action, not when they hide every assertion.
  • Control external systems. Stub unstable third-party services where appropriate and assert your integration boundary.
  • Make failures diagnosable. Use clear test names, retain traces for failures, and include relevant server logs in CI artifacts.

Start with a small, readable test. Add abstractions only after repeated patterns appear; premature wrappers can make locator failures harder to understand.

Common problems and fixes

Executable doesn't exist or browser launch failures

Cause: the Python package is installed but its matching browser binaries are not. Fix: run playwright install in the same virtual environment, and rerun it after upgrading Playwright.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Test cannot find an element

Cause: a locator is ambiguous, the accessible name differs from the visible text, the element is inside a frame, or the page has not reached the expected state. Fix: inspect the locator in Inspector or Codegen, scope it to the correct container, use the frame locator when needed, and assert a readiness condition before interacting.

Timeout while clicking

Cause: an overlay, disabled control, navigation race, or incorrect locator prevents the action. Fix: run headed with Inspector, check whether a consent dialog or modal covers the control, and wait for the application state that makes the button actionable. Do not “fix” it with a long sleep.

Works locally but fails in CI

Cause: missing browser dependencies, a different browser binary, environment-specific URLs, timezone, credentials, or insufficient diagnostics. Fix: install browsers in the CI image, pin compatible package versions, use explicit test data and configuration, and publish a trace for failures.

Authentication leaks into source control

Cause: a saved storage-state file was committed or uploaded. Fix: revoke exposed credentials, remove the file from history, add it to .gitignore, store it only on the machine or CI secret volume, and delete it when finished.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability, and cost choices

Reuse a browser process through fixtures while creating isolated contexts or pages per test. This usually avoids repeated startup overhead without sharing cookies between tests. Keep the fast Chromium suite on every commit and run the broader engine matrix on a schedule or on changes that affect cross-browser behavior. Parallelism can shorten CI time, but only after test data and external dependencies are isolated; otherwise it amplifies contention and flakiness.

Playwright itself has no separate per-test service charge in the documented workflow: you install the Python package and browser binaries. Your practical costs are CI minutes, storage for traces and artifacts, and any environments or test data your application requires.

Or skip the browser setup

If your goal is simply to obtain a clean screenshot rather than build a browser test, ScreenshotNeo provides a website screenshot API and MCP server. A single request returns PNG, JPEG, WebP, or PDF:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo documentation for parameters and response details. The same request in Python:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

And in Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
  • Cookie banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be disabled.
  • Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Response headers report the page verdict and whether it was billed.
  • An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
  • The service includes full-page and element capture, device and viewport settings, retina scale, PDF controls, custom CSS and JavaScript, waits, request blocking, headers, cookies, user agents, timezone, geolocation, transparent backgrounds, resizing, caching, signed links, asynchronous webhooks, bulk capture, usage API, and an OpenAPI specification.

The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try it.

What to learn next

Once your first test is understandable, add fixtures and reliable test data, then practice a second browser engine, Inspector, and trace analysis. Playwright Training is another optional learning resource linked from the official documentation. Keep checking the current installation, browser, and release information because supported Python versions and browser binaries evolve with Playwright releases.

Frequently Asked Questions

Should I learn synchronous or asynchronous Playwright first?

For a first pytest suite, synchronous Playwright keeps examples straightforward. Choose the asynchronous API when the surrounding application and test infrastructure already use asyncio; the browser concepts and locator practices are the same.

Do I need to install all three Playwright browsers?

No. Start with the engine you need, commonly Chromium, and add Firefox or WebKit when your users or compatibility policy require them. Install the binaries again whenever the Playwright package version changes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Where should authentication state files live?

Keep them local or in a protected CI secret volume, exclude them from version control, restrict access, and delete or rotate them when they are no longer needed because they can contain cookies and tokens.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.