Skip to main content

Run existing Selenium WebDriver Python scripts using Playwright as the browser backend — no ChromeDriver required.

Project description

playwright-webdriver-py

Run existing Selenium WebDriver Python scripts using Playwright as the browser backend — no ChromeDriver or browser binary installation required.

playwright-webdriver-py is a drop-in compatibility layer that implements the Selenium WebDriver Python API over Playwright's synchronous API. Drop it in and your existing webdriver.Chrome() scripts run backed by Playwright; faster, more reliable, and without the ChromeDriver version-matching headache.


Features

  • Zero script changes — existing Selenium scripts run as-is
  • No ChromeDriver — Playwright manages its own browser binaries
  • Full WebDriverWait / expected_conditions support — unchanged from Selenium
  • Chromium, Firefox, and WebKit backends via PlaywrightBrowserType
  • CLI runner — execute any .py Selenium script directly from the command line
  • PlaywrightBy — opt-in raw Playwright selector strings for power users

Installation

pip install playwright-webdriver-py
playwright install  # downloads browser binaries (first time only)

Or with Poetry:

poetry add playwright-webdriver-py
playwright install

Requirements: Python 3.12+


Quick Start

Run an existing Selenium script unchanged

# my_existing_script.py  — written for standard Selenium, runs on Playwright
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
wait = WebDriverWait(driver, 10)

driver.get("https://www.wikipedia.org")
search = wait.until(EC.presence_of_element_located((By.ID, "searchInput")))
search.send_keys("Playwright (software)")
search.submit()

heading = wait.until(EC.presence_of_element_located((By.ID, "firstHeading")))
print(heading.text)

driver.quit()

Via the CLI runner (intercepts webdriver.Chrome() transparently):

python -m playwright_webdriver.runner my_existing_script.py
python -m playwright_webdriver.runner my_existing_script.py --headless

Via the Python API (same interception, callable from your own code):

from playwright_webdriver.runner import run_selenium_script

run_selenium_script("my_existing_script.py", headless=True)

Use PlaywrightWebDriver directly

from playwright_webdriver import PlaywrightWebDriver, PlaywrightBrowserType
from selenium.webdriver.common.by import By

with PlaywrightWebDriver.create(
    browser_type=PlaywrightBrowserType.CHROMIUM,
    launch_options={"headless": True},
) as driver:
    driver.get("https://example.com")
    heading = driver.find_element(By.TAG_NAME, "h1")
    print(heading.text)  # "Example Domain"

Supported Selenium API

PlaywrightWebDriver

Method / Property Notes
driver.get(url) Navigates to URL
driver.find_element(by, value) Returns PlaywrightWebElement
driver.find_elements(by, value) Returns list[PlaywrightWebElement]
driver.execute_script(script, *args) Full JS execution; arguments[N] supported
driver.current_url Current page URL
driver.title Page title
driver.page_source Full HTML source
driver.maximize_window() Sets viewport to 1920×1080
driver.close() Closes current tab
driver.quit() Closes browser and releases all resources
driver.navigate() Returns navigation object (back, forward, refresh, to)
driver.switch_to() Returns target locator (frame, window, alert, default_content)
driver.manage() Returns options object (cookies, timeouts, window)
driver.current_window_handle Handle for the current window/tab
driver.window_handles All open window/tab handles

PlaywrightWebElement

Method / Property Notes
element.click() Clicks the element
element.send_keys(*value) Text input; Selenium Keys constants supported
element.clear() Clears a text field
element.submit() Submits the form containing the element
element.find_element(by, value) Scoped element search
element.find_elements(by, value) Scoped element list
element.get_attribute(name) HTML attribute value
element.get_property(name) DOM property value
element.get_dom_attribute(name) DOM attribute (no fallback to property)
element.text Visible text content
element.tag_name Element tag name
element.is_displayed() True if the element is visible
element.is_enabled() True if the element is enabled
element.is_selected() True if a checkbox/radio is checked

Locator strategies

All standard Selenium By strategies are supported:

By constant Playwright selector
By.ID #value
By.NAME [name='value']
By.CLASS_NAME .value
By.CSS_SELECTOR css=value
By.XPATH xpath=value
By.TAG_NAME bare tag selector
By.LINK_TEXT a:visible:text-is("value") (visible only, matching Selenium semantics)
By.PARTIAL_LINK_TEXT a:visible:has-text("value") (visible only, matching Selenium semantics)

In addition, PlaywrightBy.selector(string) passes a raw Playwright selector string through unchanged, giving you access to Playwright-specific features like role=, text=, and :visible filters:

from playwright_webdriver import PlaywrightBy

btn = driver.find_element(PlaywrightBy.selector("role=button[name='Submit']"))

Running Tests

The test suite is a Python port of the original C# NUnit test suite from Selenium.PlaywrightDriver.

# Install dev dependencies
poetry install

# Run the full suite (19 tests, all headless)
pytest tests/

All tests use local HTML fixtures and an ephemeral HTTP server — no internet connection required.


Examples

The examples/ directory contains real-world Selenium scripts that run unmodified through the CLI runner:

python -m playwright_webdriver.runner examples/wikipedia_smoke_test.py
python -m playwright_webdriver.runner examples/apple_homepod_test.py
python -m playwright_webdriver.runner examples/skyscanner_one_way_search_test.py

How It Works

The CLI runner monkey-patches selenium.webdriver.Chrome (and Firefox, Edge, Remote, etc.) on the real selenium.webdriver module before exec()-ing the script. This means:

  • WebDriverWait, expected_conditions, Keys, and all other Selenium helpers continue to import from the real Selenium package — nothing breaks.
  • The only substitution is the browser factory: webdriver.Chrome() returns a PlaywrightWebDriver instance backed by Playwright's Chromium.
  • All patches are restored in a finally block, so running multiple scripts in the same process is safe.

License

MIT © 2026 HappyPath. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

playwright_webdriver_py-0.1.0.tar.gz (20.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

playwright_webdriver_py-0.1.0-py3-none-any.whl (21.3 kB view details)

Uploaded Python 3

File details

Details for the file playwright_webdriver_py-0.1.0.tar.gz.

File metadata

  • Download URL: playwright_webdriver_py-0.1.0.tar.gz
  • Upload date:
  • Size: 20.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for playwright_webdriver_py-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3c063642677e327aa9f2949da4bcc6c92fc83779837b4dc197663a88e0a396cd
MD5 14e23b693a8c5a626c66242533311331
BLAKE2b-256 a4c571a1216a0b2383f9c0ccbb7168d6765c8b88a491396f7b3c02468dbec52c

See more details on using hashes here.

Provenance

The following attestation bundles were made for playwright_webdriver_py-0.1.0.tar.gz:

Publisher: publish-to-pypi.yml on happypath-team/playwright-webdriver-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file playwright_webdriver_py-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for playwright_webdriver_py-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 eedbf26ab41c8a10df08b0b2f90f2ca39764338ae8851cd845dda2aaed3f5c09
MD5 5998febd8fd87facda675338971559e2
BLAKE2b-256 e76c0c21f80642ce4d09c9bd60837ea4d1177612d408a7941c84c4c4e85361f2

See more details on using hashes here.

Provenance

The following attestation bundles were made for playwright_webdriver_py-0.1.0-py3-none-any.whl:

Publisher: publish-to-pypi.yml on happypath-team/playwright-webdriver-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page