A high-level API to automate web browsers across Chromium, Firefox and WebKit with both synchronous and asynchronous execution models.
—
Advanced Playwright capabilities including WebSocket handling, video recording, accessibility testing, time manipulation, debugging tools, and specialized browser features.
Intercept and interact with WebSocket connections for real-time application testing.
class WebSocket:
"""WebSocket connection handler."""
@property
def url(self) -> str:
"""WebSocket URL."""
def wait_for_event(
self,
event: str,
predicate: Optional[Callable] = None,
timeout: Optional[float] = None
) -> Any:
"""Wait for WebSocket event."""
def is_closed(self) -> bool:
"""Check if WebSocket is closed."""
class WebSocketRoute:
"""WebSocket route for message interception."""
def connect_to_server(self) -> None:
"""Connect route to the actual WebSocket server."""
def send(self, message: Union[str, bytes]) -> None:
"""Send message through WebSocket."""
def close(self, code: Optional[int] = None, reason: Optional[str] = None) -> None:
"""Close WebSocket connection."""Record browser sessions as video files for debugging and documentation.
class Video:
"""Video recording handler."""
def path(self) -> pathlib.Path:
"""Get path to video file."""
def save_as(self, path: Union[str, pathlib.Path]) -> None:
"""Save video to specified path."""
def delete(self) -> None:
"""Delete video file."""Handle Web Worker threads in browser pages.
class Worker:
"""Web Worker handler."""
@property
def url(self) -> str:
"""Worker script URL."""
def evaluate(self, expression: str, arg: Any = None) -> Any:
"""Execute JavaScript in worker context."""
def evaluate_handle(self, expression: str, arg: Any = None) -> JSHandle:
"""Execute JavaScript and return handle."""Capture and analyze browser console output.
class ConsoleMessage:
"""Browser console message."""
@property
def type(self) -> str:
"""Message type: 'log', 'debug', 'info', 'error', 'warning', 'dir', etc."""
@property
def text(self) -> str:
"""Console message text."""
@property
def args(self) -> List[JSHandle]:
"""Message arguments as JavaScript handles."""
@property
def location(self) -> Dict:
"""Source location information."""Access browser accessibility tree for automated accessibility testing.
class Accessibility:
"""Accessibility tree access."""
def snapshot(
self,
root: Optional[ElementHandle] = None,
interesting_only: Optional[bool] = None
) -> Optional[Dict]:
"""
Capture accessibility tree snapshot.
Args:
root: Root element (defaults to page root)
interesting_only: Filter to only interesting nodes
Returns:
Dict: Accessibility tree data
"""Control browser time for consistent testing of time-dependent functionality.
class Clock:
"""Browser time manipulation."""
def fast_forward(self, ticks: Union[int, str]) -> None:
"""Advance time by specified amount."""
def install(self, time: Optional[Union[int, str, datetime.datetime]] = None) -> None:
"""Install fake timer at specified time."""
def pause_at(self, time: Union[int, str, datetime.datetime]) -> None:
"""Pause time at specific moment."""
def resume(self) -> None:
"""Resume normal time flow."""
def run_for(self, ticks: Union[int, str]) -> None:
"""Run time for specified duration."""
def set_fixed_time(self, time: Union[int, str, datetime.datetime]) -> None:
"""Set fixed time that doesn't advance."""
def set_system_time(self, time: Union[int, str, datetime.datetime]) -> None:
"""Set system time."""Capture performance traces for analysis and debugging.
class Tracing:
"""Performance tracing capabilities."""
def start(
self,
name: Optional[str] = None,
title: Optional[str] = None,
screenshots: Optional[bool] = None,
snapshots: Optional[bool] = None,
sources: Optional[bool] = None
) -> None:
"""Start recording trace."""
def start_chunk(
self,
name: Optional[str] = None,
title: Optional[str] = None
) -> None:
"""Start new trace chunk."""
def stop_chunk(self, path: Optional[Union[str, pathlib.Path]] = None) -> None:
"""Stop current trace chunk."""
def stop(self, path: Optional[Union[str, pathlib.Path]] = None) -> None:
"""Stop tracing and save to file."""Navigate and interact with iframes and nested frames.
class Frame:
"""Browser frame (main frame or iframe)."""
@property
def name(self) -> str:
"""Frame name attribute."""
@property
def url(self) -> str:
"""Frame URL."""
@property
def parent_frame(self) -> Optional[Frame]:
"""Parent frame (None for main frame)."""
@property
def child_frames(self) -> List[Frame]:
"""List of child frames."""
def locator(self, selector: str) -> Locator:
"""Create locator within this frame."""
def goto(self, url: str, **kwargs) -> Optional[Response]:
"""Navigate frame to URL."""
def evaluate(self, expression: str, arg: Any = None) -> Any:
"""Execute JavaScript in frame context."""
class FrameLocator:
"""Locator for elements within iframes."""
def locator(self, selector: str) -> FrameLocator:
"""Create nested locator within frame."""
def first(self) -> FrameLocator:
"""First matching frame."""
def last(self) -> FrameLocator:
"""Last matching frame."""
def nth(self, index: int) -> FrameLocator:
"""Frame at specific index."""Handle web errors and browser-specific error conditions.
class WebError:
"""Web error information."""
@property
def text(self) -> Optional[str]:
"""Error text description."""Advanced selector registration and custom selector engines.
class Selectors:
"""CSS selector engine management."""
def register(
self,
name: str,
script: str,
content_script: Optional[bool] = None
) -> None:
"""Register custom selector engine."""
def set_test_id_attribute(self, attribute_name: str) -> None:
"""Set attribute name for test ID selectors."""Usage examples:
# WebSocket interception
def handle_websocket(ws):
print(f"WebSocket opened: {ws.url}")
ws.on("framereceived", lambda payload: print(f"Received: {payload}"))
page.on("websocket", handle_websocket)
# Video recording
context = browser.new_context(record_video_dir="./videos")
page = context.new_page()
# ... perform actions ...
video = page.video
video.save_as("./test-recording.webm")
# Accessibility testing
accessibility_tree = page.accessibility.snapshot()
print(f"Page has {len(accessibility_tree.get('children', []))} accessible elements")
# Time manipulation
page.clock.install()
page.clock.pause_at("2024-01-01")
page.goto("https://example.com") # Page sees fixed time
# Frame handling
frame = page.frame_locator("iframe").first()
frame.locator("button").click()Install with Tessl CLI
npx tessl i tessl/pypi-playwright