Playwright Official Documentation for Python: Complete Setup and Usage Guide
Install Playwright for Python, write reliable browser automation and pytest tests, debug failures, manage browsers, and capture pages in CI.

Playwright for Python is both a general-purpose browser-automation library and an end-to-end testing framework. It supports Chromium, WebKit, and Firefox through synchronous and asynchronous Python APIs. For pytest-based tests, install the official plugin, install the browser binaries, use the page fixture with role-based locators and web-first assertions, then run pytest.
The official documentation is the authority for installation, browser management, library usage, test execution, and debugging: Introduction, Library, Browsers, Running tests, and Debugging.
Install Playwright for Python
Pytest projects
python -m pip install pytest-playwright
playwright install
The plugin supplies isolated browser contexts, the page fixture, browser-selection options, and pytest integration.
Library-only scripts
python -m pip install playwright
playwright install
Use Python 3.8 or newer. The documented operating-system requirements include Windows 11 or Server 2019 and newer, macOS 14 or newer, and Debian 12/13 or Ubuntu 22.04/24.04/26.04 on x86-64 or arm64. Check the current installation page when your platform or Python version changes.
Your first synchronous Playwright script
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://playwright.dev")
print(page.title())
browser.close()
sync_playwright() starts the Playwright driver, launch() starts a browser, and new_page() creates a fresh page. Always close the browser, preferably with a context manager as shown.
Async Python usage
import asyncio
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
await page.goto("https://playwright.dev")
print(await page.title())
await browser.close()
asyncio.run(main())
Use the async API when your application already uses asyncio. On Windows, the browser driver subprocess requires a compatible Proactor event loop.
Write a first pytest test
# tests/test_playwright.py
from playwright.sync_api import Page, expect
def test_playwright_homepage(page: Page):
page.goto("https://playwright.dev/")
expect(page).to_have_title("Playwright")
page.get_by_role("link", name="Get started").click()
expect(page.get_by_role("heading", name="Installation")).to_be_visible()
Run it with:

pytest
The default run is headless Chromium. Select another browser or a matrix with pytest options documented in Running tests. The plugin also supports branded Chrome and Edge channels plus mobile and tablet device emulation.
Locators, waiting, and assertions
Prefer locators that describe what a user sees or interacts with:
page.get_by_role("button", name="Save")
page.get_by_label("Email")
page.get_by_text("Welcome")
page.get_by_placeholder("Search")
Use web-first assertions so Playwright waits for the expected state:
expect(page.get_by_role("status")).to_have_text("Saved")
expect(page.locator(".result")).to_be_visible()
expect(page).to_have_url("**/dashboard")
Playwright auto-waits for actionability and assertion conditions. Most tests do not need manual sleeps. If a page has a meaningful application event, wait for that event or a locator rather than an arbitrary delay.
Browser installation and version management
Browser binaries are coupled to the Playwright package version. After upgrading Playwright, run the browser installation command again when required.
# Install the default supported browsers
playwright install
# Install one browser
playwright install chromium
# Install Chromium and operating-system dependencies
playwright install --with-deps chromium
# See supported browser commands
playwright install --help
The browser guide also documents listing and uninstalling browser versions, moving the browser cache with PLAYWRIGHT_BROWSERS_PATH, and installing only the browsers required by your project. Pin Playwright in your dependency file so local and CI environments resolve the same driver and browser versions.
Contexts, isolation, and configuration
A browser context is an isolated session with its own cookies, local storage, permissions, and pages. Create a new context for independent users or test cases:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
admin = browser.new_context()
guest = browser.new_context()
admin_page = admin.new_page()
guest_page = guest.new_page()
admin_page.goto("https://example.com/admin")
guest_page.goto("https://example.com/")
admin.close()
guest.close()
browser.close()
Contexts can be configured with a viewport, locale, timezone, color scheme, geolocation, permissions, extra HTTP headers, storage state, and a user agent. Keep authentication state in a protected file and do not commit credentials.
Choosing browsers and execution modes
| Choice | When to use it |
|---|---|
| Chromium | Fast default coverage and Chromium-specific behavior |
| Firefox | Cross-engine checks for Gecko behavior |
| WebKit | Cross-engine checks related to Safari behavior |
| Headless | CI and repeatable automated runs |
| Headed | Local investigation and visual debugging |
| Branded Chrome or Edge channel | Validation against an installed branded browser |
Run a headed session while investigating a failure:
pytest --headed
Use the browser-selection and device options from the official pytest documentation instead of duplicating setup in each test.
Reliable test design
- Use role, label, text, and placeholder locators before CSS or XPath selectors.
- Assert with
expectafter navigation and important actions. - Wait for a stable application condition, such as a visible result or URL, instead of sleeping.
- Give each test a clean context through the pytest plugin or an explicit context.
- Keep tests independent so they can run in any order.
- Use explicit timeouts only where a known external operation needs more time.
Playwright’s API is not thread-safe. In multithreaded programs, create one Playwright instance per thread. For parallel pytest workers, let each worker manage its own browser resources.
Debug failing tests
Inspector
The Playwright Inspector can pause execution, step through API calls, inspect actionability logs, and help explore locators. Run a test in debug mode according to the debugging guide.

Codegen
Codegen records browser actions and generates an initial test. Treat generated locators as a starting point, then replace brittle selectors with user-facing roles and labels.
Trace Viewer
Record a trace around a failing test and open it with Trace Viewer. A trace can show screenshots, actions, network timing, and the page state around the failure, which is more useful than a final screenshot alone.
Common errors and fixes
| Error or symptom | Likely cause | Fix |
|---|---|---|
Executable doesn't exist |
Browser binaries were not installed or do not match the package. | Run playwright install; after an upgrade, run it again. |
| Browser fails to start in Linux CI | System libraries are missing. | Use playwright install --with-deps chromium on supported Linux images. |
| Locator times out | The selector is ambiguous, the element is not rendered, or the page is still loading. | Prefer a role or label locator, inspect with Inspector, and assert the expected state. |
| Click is intercepted | An overlay, animation, or disabled state blocks actionability. | Wait for the relevant overlay to disappear or assert that the target is enabled. |
| Tests pass locally but fail in CI | Different browser versions, viewport, timing, or dependencies. | Pin dependencies, install matching browsers in CI, and collect a trace. |
| Async code hangs on Windows | An incompatible event loop is used for the driver subprocess. | Use the compatible Proactor event loop described in the official library documentation. |
| Parallel runs interfere | Tests share cookies, storage, files, or a Playwright instance. | Use isolated contexts and one Playwright instance per thread. |
Performance, reliability, and maintenance
- Reuse a browser process while creating isolated contexts when many tests run in one worker.
- Run headless in CI and reserve headed mode for diagnosis.
- Install only the browser engines your matrix needs.
- Keep navigation and assertion timeouts aligned with real application behavior; excessive timeouts hide regressions.
- Capture traces on retries or failures so normal runs stay lighter.
- Run browser installation as an explicit CI step and cache the documented browser directory when your CI system supports safe caching.
- Review Playwright release notes before upgrades because browser binaries and behavior are version-coupled.
Or skip the browser setup
If your goal is a clean screenshot rather than interactive testing, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or PDF. The API accepts the URL and capture options, while the ScreenshotNeo documentation lists all parameters.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Before capture, ScreenshotNeo accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
There is a free allowance of 1,000 screenshots per month without a card. Paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
FAQ
Is Playwright only for end-to-end tests?
No. The Python library is also a general-purpose browser-automation tool with synchronous and asynchronous APIs.
Which browsers does Playwright support?
Playwright supports Chromium, WebKit, and Firefox, with documented options for branded Chrome and Edge channels and device emulation.
Do I need pytest-playwright?
No. Install playwright for standalone scripts. Install pytest-playwright when you want pytest fixtures and plugin configuration.
Why should I avoid manual sleeps?
Playwright auto-waits for actionability and web-first assertions wait for expected conditions. Locator and assertion waits are usually more stable than fixed delays.
Can I use Playwright from multiple threads?
Not with one shared instance. The official library documentation says the API is not thread-safe; create one Playwright instance per thread.
What should I do after upgrading Playwright?
Install the browser binaries for the new package version with playwright install, then run your browser matrix and review release notes.


