A high-level API to automate web browsers across Chromium, Firefox and WebKit with both synchronous and asynchronous execution models.
—
Modern element location and interaction using the Locator API with built-in auto-waiting, retry logic, and robust element interaction methods. The Locator API is the recommended approach for element interaction in Playwright.
Create locators using various strategies including CSS selectors, text content, ARIA roles, and semantic attributes.
class Page:
def locator(self, selector: str) -> Locator:
"""
Create locator for elements matching selector.
Args:
selector: CSS selector, text selector, or XPath
Returns:
Locator: Element locator with auto-waiting
"""
def get_by_role(
self,
role: str,
checked: Optional[bool] = None,
disabled: Optional[bool] = None,
expanded: Optional[bool] = None,
include_hidden: Optional[bool] = None,
level: Optional[int] = None,
name: Union[str, Pattern, None] = None,
pressed: Optional[bool] = None,
selected: Optional[bool] = None,
exact: Optional[bool] = None
) -> Locator:
"""
Create locator by ARIA role.
Args:
role: ARIA role (button, textbox, heading, etc.)
checked: Checkbox/radio checked state
disabled: Element disabled state
expanded: Element expanded state
include_hidden: Include hidden elements
level: Heading level for heading role
name: Accessible name pattern
pressed: Button pressed state
selected: Option selected state
exact: Exact name match
Returns:
Locator: Role-based locator
"""
def get_by_text(
self,
text: Union[str, Pattern],
exact: Optional[bool] = None
) -> Locator:
"""
Create locator by text content.
Args:
text: Text content or pattern
exact: Exact text match
Returns:
Locator: Text-based locator
"""
def get_by_label(
self,
text: Union[str, Pattern],
exact: Optional[bool] = None
) -> Locator:
"""
Create locator by associated label text.
Args:
text: Label text or pattern
exact: Exact text match
Returns:
Locator: Label-based locator
"""
def get_by_placeholder(
self,
text: Union[str, Pattern],
exact: Optional[bool] = None
) -> Locator:
"""
Create locator by placeholder text.
Args:
text: Placeholder text or pattern
exact: Exact text match
Returns:
Locator: Placeholder-based locator
"""
def get_by_alt_text(
self,
text: Union[str, Pattern],
exact: Optional[bool] = None
) -> Locator:
"""
Create locator by alt text attribute.
Args:
text: Alt text or pattern
exact: Exact text match
Returns:
Locator: Alt text-based locator
"""
def get_by_title(
self,
text: Union[str, Pattern],
exact: Optional[bool] = None
) -> Locator:
"""
Create locator by title attribute.
Args:
text: Title text or pattern
exact: Exact text match
Returns:
Locator: Title-based locator
"""
def get_by_test_id(self, test_id: str) -> Locator:
"""
Create locator by test ID attribute.
Args:
test_id: Test identifier value
Returns:
Locator: Test ID-based locator
"""
def frame_locator(self, selector: str) -> FrameLocator:
"""
Create frame locator for iframe elements.
Args:
selector: Frame selector
Returns:
FrameLocator: Frame locator
"""Interact with elements through locators with automatic waiting and retry logic.
class Locator:
page: Page
first: Locator
last: Locator
def click(
self,
modifiers: Optional[List[str]] = None,
position: Optional[Position] = None,
delay: Optional[float] = None,
button: Optional[str] = None,
click_count: Optional[int] = None,
timeout: Optional[float] = None,
force: Optional[bool] = None,
no_wait_after: Optional[bool] = None,
trial: Optional[bool] = None
) -> None:
"""
Click element.
Args:
modifiers: Modifier keys ('Alt', 'Control', 'Meta', 'Shift')
position: Click position relative to element
delay: Delay between mousedown and mouseup
button: Mouse button ('left', 'right', 'middle')
click_count: Number of clicks
timeout: Action timeout in milliseconds
force: Skip actionability checks
no_wait_after: Don't wait for navigation
trial: Perform checks without action
"""
def dblclick(
self,
modifiers: Optional[List[str]] = None,
position: Optional[Position] = None,
delay: Optional[float] = None,
button: Optional[str] = None,
timeout: Optional[float] = None,
force: Optional[bool] = None,
no_wait_after: Optional[bool] = None,
trial: Optional[bool] = None
) -> None:
"""Double-click element."""
def fill(
self,
value: str,
timeout: Optional[float] = None,
no_wait_after: Optional[bool] = None,
force: Optional[bool] = None
) -> None:
"""
Fill input element with value.
Args:
value: Value to fill
timeout: Action timeout in milliseconds
no_wait_after: Don't wait for navigation
force: Skip actionability checks
"""
def type(
self,
text: str,
delay: Optional[float] = None,
timeout: Optional[float] = None,
no_wait_after: Optional[bool] = None
) -> None:
"""
Type text character by character.
Args:
text: Text to type
delay: Delay between keystrokes
timeout: Action timeout in milliseconds
no_wait_after: Don't wait for navigation
"""
def press(
self,
key: str,
delay: Optional[float] = None,
timeout: Optional[float] = None,
no_wait_after: Optional[bool] = None
) -> None:
"""
Press key on element.
Args:
key: Key to press ('Enter', 'Escape', etc.)
delay: Delay between keydown and keyup
timeout: Action timeout in milliseconds
no_wait_after: Don't wait for navigation
"""
def check(
self,
timeout: Optional[float] = None,
force: Optional[bool] = None,
no_wait_after: Optional[bool] = None,
trial: Optional[bool] = None
) -> None:
"""Check checkbox or radio button."""
def uncheck(
self,
timeout: Optional[float] = None,
force: Optional[bool] = None,
no_wait_after: Optional[bool] = None,
trial: Optional[bool] = None
) -> None:
"""Uncheck checkbox."""
def select_option(
self,
value: Union[str, List[str], None] = None,
index: Union[int, List[int], None] = None,
label: Union[str, List[str], None] = None,
element: Union[ElementHandle, List[ElementHandle], None] = None,
timeout: Optional[float] = None,
force: Optional[bool] = None,
no_wait_after: Optional[bool] = None
) -> List[str]:
"""
Select option(s) in select element.
Returns:
List[str]: Selected option values
"""
def set_input_files(
self,
files: Union[str, List[str], FilePayload, List[FilePayload]],
timeout: Optional[float] = None,
no_wait_after: Optional[bool] = None
) -> None:
"""Set files for file input element."""
def hover(
self,
modifiers: Optional[List[str]] = None,
position: Optional[Position] = None,
timeout: Optional[float] = None,
force: Optional[bool] = None,
trial: Optional[bool] = None
) -> None:
"""Hover over element."""
def focus(
self,
timeout: Optional[float] = None
) -> None:
"""Focus element."""
def clear(
self,
timeout: Optional[float] = None,
no_wait_after: Optional[bool] = None,
force: Optional[bool] = None
) -> None:
"""Clear input element."""
def scroll_into_view_if_needed(
self,
timeout: Optional[float] = None
) -> None:
"""Scroll element into view if needed."""Refine and combine locators for precise element targeting.
class Locator:
def nth(self, index: int) -> Locator:
"""
Get nth matching element.
Args:
index: Element index (0-based)
Returns:
Locator: Nth element locator
"""
def filter(
self,
has_text: Union[str, Pattern, None] = None,
has_not_text: Union[str, Pattern, None] = None,
has: Optional[Locator] = None,
has_not: Optional[Locator] = None
) -> Locator:
"""
Filter locator by additional criteria.
Args:
has_text: Element must contain text
has_not_text: Element must not contain text
has: Element must contain descendant
has_not: Element must not contain descendant
Returns:
Locator: Filtered locator
"""
def and_(self, locator: Locator) -> Locator:
"""
Logical AND with another locator.
Args:
locator: Locator to combine with AND
Returns:
Locator: Combined locator
"""
def or_(self, locator: Locator) -> Locator:
"""
Logical OR with another locator.
Args:
locator: Locator to combine with OR
Returns:
Locator: Combined locator
"""
def locator(self, selector: str) -> Locator:
"""
Find locator relative to this locator.
Args:
selector: Relative selector
Returns:
Locator: Relative locator
"""Check element states with automatic waiting and retry.
class Locator:
def is_checked(
self,
timeout: Optional[float] = None
) -> bool:
"""
Check if element is checked.
Args:
timeout: Query timeout in milliseconds
Returns:
bool: True if checked
"""
def is_disabled(
self,
timeout: Optional[float] = None
) -> bool:
"""Check if element is disabled."""
def is_editable(
self,
timeout: Optional[float] = None
) -> bool:
"""Check if element is editable."""
def is_enabled(
self,
timeout: Optional[float] = None
) -> bool:
"""Check if element is enabled."""
def is_hidden(
self,
timeout: Optional[float] = None
) -> bool:
"""Check if element is hidden."""
def is_visible(
self,
timeout: Optional[float] = None
) -> bool:
"""Check if element is visible."""
def count(self) -> int:
"""
Get number of matching elements.
Returns:
int: Element count
"""Get element content and attributes.
class Locator:
def text_content(
self,
timeout: Optional[float] = None
) -> Optional[str]:
"""
Get element text content.
Args:
timeout: Query timeout in milliseconds
Returns:
Optional[str]: Text content
"""
def inner_text(
self,
timeout: Optional[float] = None
) -> str:
"""
Get element inner text.
Args:
timeout: Query timeout in milliseconds
Returns:
str: Inner text
"""
def inner_html(
self,
timeout: Optional[float] = None
) -> str:
"""Get element inner HTML."""
def input_value(
self,
timeout: Optional[float] = None
) -> str:
"""Get input element value."""
def get_attribute(
self,
name: str,
timeout: Optional[float] = None
) -> Optional[str]:
"""
Get element attribute value.
Args:
name: Attribute name
timeout: Query timeout in milliseconds
Returns:
Optional[str]: Attribute value
"""
def all_text_contents(self) -> List[str]:
"""
Get text content of all matching elements.
Returns:
List[str]: Text contents
"""
def all_inner_texts(self) -> List[str]:
"""
Get inner text of all matching elements.
Returns:
List[str]: Inner texts
"""Additional locator utilities for waiting and screenshots.
class Locator:
def wait_for(
self,
state: Optional[str] = None,
timeout: Optional[float] = None
) -> None:
"""
Wait for locator to reach state.
Args:
state: Element state ('attached', 'detached', 'visible', 'hidden')
timeout: Wait timeout in milliseconds
"""
def bounding_box(
self,
timeout: Optional[float] = None
) -> Optional[FloatRect]:
"""
Get element bounding box.
Args:
timeout: Query timeout in milliseconds
Returns:
Optional[FloatRect]: Element bounds
"""
def screenshot(
self,
timeout: Optional[float] = None,
type: Optional[str] = None,
path: Optional[str] = None,
quality: Optional[int] = None,
omit_background: Optional[bool] = None,
animations: Optional[str] = None,
caret: Optional[str] = None,
scale: Optional[str] = None,
mask: Optional[List[Locator]] = None
) -> bytes:
"""
Take element screenshot.
Args:
timeout: Screenshot timeout in milliseconds
type: Image type ('png', 'jpeg')
path: File path to save screenshot
quality: JPEG quality (0-100)
omit_background: Hide default background
animations: Handle animations ('disabled', 'allow')
caret: Handle text caret ('hide', 'initial')
scale: Viewport scale ('css', 'device')
mask: Elements to mask in screenshot
Returns:
bytes: Screenshot data
"""from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://example.com")
# Locate by role and name
submit_button = page.get_by_role("button", name="Submit")
submit_button.click()
# Locate by text content
error_message = page.get_by_text("Please fill required fields")
assert error_message.is_visible()
# Locate by label
email_input = page.get_by_label("Email Address")
email_input.fill("user@example.com")
# Locate by placeholder
search_input = page.get_by_placeholder("Search...")
search_input.type("playwright")
browser.close()with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://example.com/products")
# Filter products by text
product_cards = page.locator(".product-card")
laptop_cards = product_cards.filter(has_text="Laptop")
# Get specific product
first_laptop = laptop_cards.first
first_laptop.click()
# Combine locators
form_inputs = page.locator("form").locator("input")
required_inputs = form_inputs.and_(page.locator("[required]"))
# Fill all required inputs
for i in range(required_inputs.count()):
input_locator = required_inputs.nth(i)
input_locator.fill("test value")
browser.close()with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://example.com/app")
# Multi-step form interaction
page.get_by_label("First Name").fill("John")
page.get_by_label("Last Name").fill("Doe")
# Select from dropdown
country_select = page.get_by_label("Country")
country_select.select_option(label="United States")
# Check multiple checkboxes
interests = ["Technology", "Sports", "Music"]
for interest in interests:
page.get_by_role("checkbox", name=interest).check()
# Upload file
file_input = page.get_by_label("Profile Picture")
file_input.set_input_files("profile.jpg")
# Submit with confirmation
submit_btn = page.get_by_role("button", name="Create Account")
# Wait for confirmation dialog
with page.expect_event("dialog") as dialog_info:
submit_btn.click()
dialog = dialog_info.value
dialog.accept()
browser.close()with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://example.com/form")
# Check initial states
submit_btn = page.get_by_role("button", name="Submit")
assert submit_btn.is_disabled()
# Fill required field
email_input = page.get_by_label("Email")
email_input.fill("test@example.com")
# Verify button becomes enabled
assert submit_btn.is_enabled()
# Check visibility of elements
error_message = page.get_by_text("Email is required")
assert error_message.is_hidden()
# Clear field to trigger validation
email_input.clear()
assert error_message.is_visible()
browser.close()Install with Tessl CLI
npx tessl i tessl/pypi-playwright