A high-level API to automate web browsers across Chromium, Firefox and WebKit with both synchronous and asynchronous execution models.
—
Comprehensive page navigation, content manipulation, and interaction capabilities for automating web applications. Includes navigation methods, JavaScript execution, form handling, and advanced page state management.
Navigate between pages, handle redirects, and manage page loading states.
class Page:
url: str
main_frame: Frame
frames: List[Frame]
context: BrowserContext
def goto(
self,
url: str,
timeout: Optional[float] = None,
wait_until: Optional[str] = None,
referer: Optional[str] = None
) -> Optional[Response]:
"""
Navigate to URL.
Args:
url: Target URL
timeout: Navigation timeout in milliseconds
wait_until: When to consider navigation complete
('load', 'domcontentloaded', 'networkidle', 'commit')
referer: Referer header value
Returns:
Optional[Response]: Main resource response (None for data URLs)
"""
def go_back(
self,
timeout: Optional[float] = None,
wait_until: Optional[str] = None
) -> Optional[Response]:
"""
Navigate back in browser history.
Args:
timeout: Navigation timeout in milliseconds
wait_until: Load completion criteria
Returns:
Optional[Response]: Response if navigation occurred
"""
def go_forward(
self,
timeout: Optional[float] = None,
wait_until: Optional[str] = None
) -> Optional[Response]:
"""
Navigate forward in browser history.
Args:
timeout: Navigation timeout in milliseconds
wait_until: Load completion criteria
Returns:
Optional[Response]: Response if navigation occurred
"""
def reload(
self,
timeout: Optional[float] = None,
wait_until: Optional[str] = None
) -> Optional[Response]:
"""
Reload current page.
Args:
timeout: Navigation timeout in milliseconds
wait_until: Load completion criteria
Returns:
Optional[Response]: Main resource response
"""
def wait_for_load_state(
self,
state: Optional[str] = None,
timeout: Optional[float] = None
) -> None:
"""
Wait for page to reach specified load state.
Args:
state: Load state ('load', 'domcontentloaded', 'networkidle')
timeout: Wait timeout in milliseconds
"""
def wait_for_url(
self,
url: Union[str, Pattern, Callable[[str], bool]],
timeout: Optional[float] = None,
wait_until: Optional[str] = None
) -> None:
"""
Wait for page URL to match pattern.
Args:
url: URL pattern to match
timeout: Wait timeout in milliseconds
wait_until: Load completion criteria
"""Get and set page content, execute JavaScript, and manipulate page state.
class Page:
def content(self) -> str:
"""
Get HTML content of the page.
Returns:
str: Full HTML content
"""
def set_content(
self,
html: str,
timeout: Optional[float] = None,
wait_until: Optional[str] = None
) -> None:
"""
Set HTML content of the page.
Args:
html: HTML content to set
timeout: Load timeout in milliseconds
wait_until: Load completion criteria
"""
def title(self) -> str:
"""
Get page title.
Returns:
str: Page title
"""
def evaluate(
self,
expression: str,
arg: Any = None
) -> Any:
"""
Execute JavaScript expression in page context.
Args:
expression: JavaScript expression to evaluate
arg: Argument to pass to expression
Returns:
Any: Expression result (serializable values only)
"""
def evaluate_handle(
self,
expression: str,
arg: Any = None
) -> JSHandle:
"""
Execute JavaScript and return object handle.
Args:
expression: JavaScript expression to evaluate
arg: Argument to pass to expression
Returns:
JSHandle: Handle to JavaScript object
"""
def add_script_tag(
self,
url: Optional[str] = None,
path: Optional[str] = None,
content: Optional[str] = None,
type: Optional[str] = None
) -> ElementHandle:
"""
Add script tag to page.
Args:
url: Script URL
path: Path to script file
content: Script content
type: Script type attribute
Returns:
ElementHandle: Script element handle
"""
def add_style_tag(
self,
url: Optional[str] = None,
path: Optional[str] = None,
content: Optional[str] = None
) -> ElementHandle:
"""
Add style tag to page.
Args:
url: Stylesheet URL
path: Path to stylesheet file
content: CSS content
Returns:
ElementHandle: Style element handle
"""Direct element interaction methods using CSS selectors. Note: Modern applications should prefer the Locator API.
class Page:
def click(
self,
selector: str,
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,
strict: Optional[bool] = None
) -> None:
"""
Click element matching selector.
Args:
selector: Element selector
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 (1 for single, 2 for double)
timeout: Action timeout in milliseconds
force: Skip actionability checks
no_wait_after: Don't wait for navigation
trial: Perform all checks without action
strict: Throw on multiple matches
"""
def dblclick(
self,
selector: str,
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,
strict: Optional[bool] = None
) -> None:
"""
Double-click element matching selector.
Args:
selector: Element selector
modifiers: Modifier keys
position: Click position
delay: Delay between clicks
button: Mouse button
timeout: Action timeout in milliseconds
force: Skip actionability checks
no_wait_after: Don't wait for navigation
trial: Perform checks without action
strict: Throw on multiple matches
"""
def fill(
self,
selector: str,
value: str,
timeout: Optional[float] = None,
no_wait_after: Optional[bool] = None,
force: Optional[bool] = None,
strict: Optional[bool] = None
) -> None:
"""
Fill input field with value.
Args:
selector: Input element selector
value: Value to fill
timeout: Action timeout in milliseconds
no_wait_after: Don't wait for navigation
force: Skip actionability checks
strict: Throw on multiple matches
"""
def type(
self,
selector: str,
text: str,
delay: Optional[float] = None,
timeout: Optional[float] = None,
no_wait_after: Optional[bool] = None,
strict: Optional[bool] = None
) -> None:
"""
Type text into element character by character.
Args:
selector: Element selector
text: Text to type
delay: Delay between keystrokes in milliseconds
timeout: Action timeout in milliseconds
no_wait_after: Don't wait for navigation
strict: Throw on multiple matches
"""
def press(
self,
selector: str,
key: str,
delay: Optional[float] = None,
timeout: Optional[float] = None,
no_wait_after: Optional[bool] = None,
strict: Optional[bool] = None
) -> None:
"""
Press key on element.
Args:
selector: Element selector
key: Key to press ('Enter', 'Escape', 'Tab', etc.)
delay: Delay between keydown and keyup
timeout: Action timeout in milliseconds
no_wait_after: Don't wait for navigation
strict: Throw on multiple matches
"""
def check(
self,
selector: str,
timeout: Optional[float] = None,
force: Optional[bool] = None,
no_wait_after: Optional[bool] = None,
trial: Optional[bool] = None,
strict: Optional[bool] = None
) -> None:
"""
Check checkbox or radio button.
Args:
selector: Element selector
timeout: Action timeout in milliseconds
force: Skip actionability checks
no_wait_after: Don't wait for navigation
trial: Perform checks without action
strict: Throw on multiple matches
"""
def uncheck(
self,
selector: str,
timeout: Optional[float] = None,
force: Optional[bool] = None,
no_wait_after: Optional[bool] = None,
trial: Optional[bool] = None,
strict: Optional[bool] = None
) -> None:
"""
Uncheck checkbox.
Args:
selector: Element selector
timeout: Action timeout in milliseconds
force: Skip actionability checks
no_wait_after: Don't wait for navigation
trial: Perform checks without action
strict: Throw on multiple matches
"""
def select_option(
self,
selector: str,
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,
strict: Optional[bool] = None
) -> List[str]:
"""
Select option(s) in select element.
Args:
selector: Select element selector
value: Option value(s) to select
index: Option index(es) to select
label: Option label(s) to select
element: Option element(s) to select
timeout: Action timeout in milliseconds
force: Skip actionability checks
no_wait_after: Don't wait for navigation
strict: Throw on multiple matches
Returns:
List[str]: Selected option values
"""
def set_input_files(
self,
selector: str,
files: Union[str, List[str], FilePayload, List[FilePayload]],
timeout: Optional[float] = None,
no_wait_after: Optional[bool] = None,
strict: Optional[bool] = None
) -> None:
"""
Set files for file input element.
Args:
selector: File input selector
files: File path(s) or file payload(s)
timeout: Action timeout in milliseconds
no_wait_after: Don't wait for navigation
strict: Throw on multiple matches
"""
def hover(
self,
selector: str,
modifiers: Optional[List[str]] = None,
position: Optional[Position] = None,
timeout: Optional[float] = None,
force: Optional[bool] = None,
trial: Optional[bool] = None,
strict: Optional[bool] = None
) -> None:
"""
Hover over element.
Args:
selector: Element selector
modifiers: Modifier keys
position: Hover position
timeout: Action timeout in milliseconds
force: Skip actionability checks
trial: Perform checks without action
strict: Throw on multiple matches
"""
def focus(
self,
selector: str,
timeout: Optional[float] = None,
strict: Optional[bool] = None
) -> None:
"""
Focus element.
Args:
selector: Element selector
timeout: Action timeout in milliseconds
strict: Throw on multiple matches
"""
def drag_and_drop(
self,
source: str,
target: str,
force: Optional[bool] = None,
no_wait_after: Optional[bool] = None,
timeout: Optional[float] = None,
trial: Optional[bool] = None,
strict: Optional[bool] = None,
source_position: Optional[Position] = None,
target_position: Optional[Position] = None
) -> None:
"""
Drag element from source to target.
Args:
source: Source element selector
target: Target element selector
force: Skip actionability checks
no_wait_after: Don't wait for navigation
timeout: Action timeout in milliseconds
trial: Perform checks without action
strict: Throw on multiple matches
source_position: Drag start position
target_position: Drop position
"""Check element states using CSS selectors.
class Page:
def is_checked(
self,
selector: str,
timeout: Optional[float] = None,
strict: Optional[bool] = None
) -> bool:
"""
Check if element is checked.
Args:
selector: Element selector
timeout: Query timeout in milliseconds
strict: Throw on multiple matches
Returns:
bool: True if checked
"""
def is_disabled(
self,
selector: str,
timeout: Optional[float] = None,
strict: Optional[bool] = None
) -> bool:
"""
Check if element is disabled.
Args:
selector: Element selector
timeout: Query timeout in milliseconds
strict: Throw on multiple matches
Returns:
bool: True if disabled
"""
def is_editable(
self,
selector: str,
timeout: Optional[float] = None,
strict: Optional[bool] = None
) -> bool:
"""
Check if element is editable.
Args:
selector: Element selector
timeout: Query timeout in milliseconds
strict: Throw on multiple matches
Returns:
bool: True if editable
"""
def is_enabled(
self,
selector: str,
timeout: Optional[float] = None,
strict: Optional[bool] = None
) -> bool:
"""
Check if element is enabled.
Args:
selector: Element selector
timeout: Query timeout in milliseconds
strict: Throw on multiple matches
Returns:
bool: True if enabled
"""
def is_hidden(
self,
selector: str,
timeout: Optional[float] = None,
strict: Optional[bool] = None
) -> bool:
"""
Check if element is hidden.
Args:
selector: Element selector
timeout: Query timeout in milliseconds
strict: Throw on multiple matches
Returns:
bool: True if hidden
"""
def is_visible(
self,
selector: str,
timeout: Optional[float] = None,
strict: Optional[bool] = None
) -> bool:
"""
Check if element is visible.
Args:
selector: Element selector
timeout: Query timeout in milliseconds
strict: Throw on multiple matches
Returns:
bool: True if visible
"""Wait for various page conditions and events.
class Page:
def wait_for_selector(
self,
selector: str,
timeout: Optional[float] = None,
state: Optional[str] = None,
strict: Optional[bool] = None
) -> Optional[ElementHandle]:
"""
Wait for element matching selector.
Args:
selector: Element selector
timeout: Wait timeout in milliseconds
state: Element state ('attached', 'detached', 'visible', 'hidden')
strict: Throw on multiple matches
Returns:
Optional[ElementHandle]: Element handle (None if detached)
"""
def wait_for_function(
self,
expression: str,
arg: Any = None,
timeout: Optional[float] = None,
polling: Union[float, str, None] = None
) -> JSHandle:
"""
Wait for JavaScript function to return truthy value.
Args:
expression: JavaScript function to evaluate
arg: Argument to pass to function
timeout: Wait timeout in milliseconds
polling: Polling interval ('raf' or milliseconds)
Returns:
JSHandle: Function result handle
"""
def wait_for_timeout(self, timeout: float) -> None:
"""
Wait for specified time.
Args:
timeout: Wait time in milliseconds
"""
def wait_for_event(
self,
event: str,
predicate: Optional[Callable] = None,
timeout: Optional[float] = None
) -> Any:
"""
Wait for page event.
Args:
event: Event name ('dialog', 'download', 'filechooser', etc.)
predicate: Event filter function
timeout: Wait timeout in milliseconds
Returns:
Any: Event data
"""
def expect_event(
self,
event: str,
predicate: Optional[Callable] = None,
timeout: Optional[float] = None
) -> EventContextManager:
"""
Expect page event with context manager.
Args:
event: Event name
predicate: Event filter function
timeout: Wait timeout in milliseconds
Returns:
EventContextManager: Event context manager
"""Capture page content as images or PDFs.
class Page:
def screenshot(
self,
timeout: Optional[float] = None,
type: Optional[str] = None,
path: Optional[str] = None,
quality: Optional[int] = None,
omit_background: Optional[bool] = None,
full_page: Optional[bool] = None,
clip: Optional[FloatRect] = None,
animations: Optional[str] = None,
caret: Optional[str] = None,
scale: Optional[str] = None,
mask: Optional[List[Locator]] = None
) -> bytes:
"""
Take page 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
full_page: Capture full scrollable page
clip: Capture specific area
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
"""
def pdf(
self,
scale: Optional[float] = None,
display_header_footer: Optional[bool] = None,
header_template: Optional[str] = None,
footer_template: Optional[str] = None,
print_background: Optional[bool] = None,
landscape: Optional[bool] = None,
page_ranges: Optional[str] = None,
format: Optional[str] = None,
width: Optional[str] = None,
height: Optional[str] = None,
margin: Optional[PdfMargins] = None,
path: Optional[str] = None,
prefer_css_page_size: Optional[bool] = None,
tagged: Optional[bool] = None,
outline: Optional[bool] = None
) -> bytes:
"""
Generate PDF of page.
Args:
scale: Scale factor (0.1-2)
display_header_footer: Show header/footer
header_template: HTML template for header
footer_template: HTML template for footer
print_background: Include background graphics
landscape: Landscape orientation
page_ranges: Page ranges to print
format: Paper format ('A4', 'Letter', etc.)
width: Paper width
height: Paper height
margin: Page margins
path: File path to save PDF
prefer_css_page_size: Use CSS page size
tagged: Generate tagged PDF
outline: Generate PDF outline
Returns:
bytes: PDF data
"""Direct access to keyboard, mouse, and touch input.
class Page:
keyboard: Keyboard
mouse: Mouse
touchscreen: Touchscreen
class Keyboard:
def down(self, key: str) -> None:
"""Press key down."""
def up(self, key: str) -> None:
"""Release key."""
def press(
self,
key: str,
delay: Optional[float] = None
) -> None:
"""Press and release key."""
def insert_text(self, text: str) -> None:
"""Insert text without key events."""
def type(
self,
text: str,
delay: Optional[float] = None
) -> None:
"""Type text with key events."""
class Mouse:
def move(
self,
x: float,
y: float,
steps: Optional[int] = None
) -> None:
"""Move mouse to coordinates."""
def down(
self,
button: Optional[str] = None,
click_count: Optional[int] = None
) -> None:
"""Press mouse button."""
def up(
self,
button: Optional[str] = None,
click_count: Optional[int] = None
) -> None:
"""Release mouse button."""
def click(
self,
x: float,
y: float,
delay: Optional[float] = None,
button: Optional[str] = None,
click_count: Optional[int] = None
) -> None:
"""Click at coordinates."""
def dblclick(
self,
x: float,
y: float,
delay: Optional[float] = None,
button: Optional[str] = None
) -> None:
"""Double-click at coordinates."""
def wheel(self, delta_x: float, delta_y: float) -> None:
"""Scroll mouse wheel."""
class Touchscreen:
def tap(self, x: float, y: float) -> None:
"""Tap at coordinates."""from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
# Navigate and wait for load
response = page.goto("https://example.com")
print(f"Status: {response.status}")
# Navigate with specific wait condition
page.goto("https://spa-app.com", wait_until="networkidle")
# Browser navigation
page.go_back()
page.go_forward()
page.reload()
browser.close()with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://example.com/form")
# Fill form fields
page.fill("#name", "John Doe")
page.fill("#email", "john@example.com")
page.type("#message", "Hello world!", delay=100)
# Select options
page.select_option("#country", "US")
page.check("#subscribe")
# Submit form
page.click("button[type=submit]")
page.wait_for_load_state("networkidle")
browser.close()with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://example.com")
# Execute JavaScript
title = page.evaluate("document.title")
print(f"Title: {title}")
# Pass arguments
result = page.evaluate("(x, y) => x + y", {"x": 5, "y": 3})
print(f"Result: {result}")
# Get object handle
window_handle = page.evaluate_handle("window")
print(f"Window: {window_handle}")
browser.close()with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://dynamic-app.com")
# Wait for element
page.wait_for_selector(".loading", state="detached")
element = page.wait_for_selector(".results")
# Wait for function
page.wait_for_function("window.dataLoaded === true")
# Wait for event
with page.expect_event("dialog") as dialog_info:
page.click("#show-alert")
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")
# Full page screenshot
page.screenshot(path="page.png", full_page=True)
# Specific element area
page.screenshot(
path="header.png",
clip={"x": 0, "y": 0, "width": 800, "height": 100}
)
# Generate PDF
page.pdf(
path="page.pdf",
format="A4",
margin={"top": "1in", "bottom": "1in"}
)
browser.close()Handle browser dialog boxes including alerts, confirmations, and prompts.
class Dialog:
"""Browser dialog (alert, confirm, prompt) handler."""
@property
def type(self) -> str:
"""Dialog type: 'alert', 'beforeunload', 'confirm', or 'prompt'."""
@property
def message(self) -> str:
"""Message displayed in the dialog."""
@property
def default_value(self) -> str:
"""Default value for prompt dialogs."""
def accept(self, prompt_text: Optional[str] = None) -> None:
"""Accept the dialog, optionally providing text for prompts."""
def dismiss(self) -> None:
"""Dismiss the dialog."""Handle file upload dialogs and file selection.
class FileChooser:
"""File upload dialog handler."""
@property
def page(self) -> Page:
"""Page that opened the file chooser."""
@property
def element(self) -> ElementHandle:
"""Element that triggered the file chooser."""
@property
def is_multiple(self) -> bool:
"""Whether multiple files can be selected."""
def set_files(
self,
files: Union[str, pathlib.Path, List[Union[str, pathlib.Path]]],
timeout: Optional[float] = None
) -> None:
"""Set files for upload."""Manage file downloads triggered by user actions.
class Download:
"""File download handler."""
@property
def page(self) -> Page:
"""Page that initiated the download."""
@property
def url(self) -> str:
"""Download URL."""
@property
def suggested_filename(self) -> str:
"""Browser-suggested filename."""
def path(self) -> Optional[pathlib.Path]:
"""Download file path (None for cancelled downloads)."""
def save_as(self, path: Union[str, pathlib.Path]) -> None:
"""Save download to specific path."""
def delete(self) -> None:
"""Delete downloaded file."""
def cancel(self) -> None:
"""Cancel the download."""
def failure(self) -> Optional[str]:
"""Download failure reason if failed."""Handle JavaScript objects and values from page evaluation.
class JSHandle:
"""Handle to JavaScript object in page context."""
def evaluate(
self,
expression: str,
arg: Any = None
) -> Any:
"""Evaluate JavaScript with this handle as context."""
def evaluate_handle(
self,
expression: str,
arg: Any = None
) -> JSHandle:
"""Evaluate JavaScript and return handle to result."""
def get_property(self, property_name: str) -> JSHandle:
"""Get handle to object property."""
def get_properties(self) -> Dict[str, JSHandle]:
"""Get all object properties as handles."""
def as_element(self) -> Optional[ElementHandle]:
"""Convert to ElementHandle if this is a DOM element."""
def dispose(self) -> None:
"""Dispose the handle and release memory."""
def json_value(self) -> Any:
"""JSON representation of the object."""Usage examples:
# Dialog handling
def handle_alert(dialog):
print(f"Alert: {dialog.message}")
dialog.accept()
page.on("dialog", handle_alert)
page.click("button[onclick='alert()']")
# File upload
with page.expect_file_chooser() as fc_info:
page.click("input[type=file]")
file_chooser = fc_info.value
file_chooser.set_files("document.pdf")
# Download handling
with page.expect_download() as download_info:
page.click("a[download]")
download = download_info.value
download.save_as("./downloads/file.pdf")Install with Tessl CLI
npx tessl i tessl/pypi-playwright