Best practices

  • Choose CSS selectors that are both specific and stable to avoid selecting the wrong elements. Target IDs, data attributes, or uniquely structured paths whenever possible.

  • Prefer text selectors for buttons and links to make tests more readable and maintainable, as they mimic user interactions.

  • Utilize XPath for navigating complex DOM structures or when needing to perform more advanced element searches.

  • Combine CSS, text, or role-based selectors to fine-tune element targeting – especially helpful on dynamic pages where content or structure can shift frequently.

from playwright.sync_api import sync_playwright

# Start Playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()

# Navigate to the target page
page.goto('https://sandbox.oxylabs.io/products')

# Using CSS selectors
product_name = page.locator('css=.product-name').text_content()
print('Product Name:', product_name)

# Using text selectors
add_to_cart_button = page.locator('text=Add to Cart').click()

# Using XPath selectors
price = page.locator('xpath=//div[@class="price"]').text_content()
print('Price:', price)

# Combining selectors
description = page.locator('.description >> text=More Info').text_content()
print('Description:', description)

# Close browser
browser.close()

Common issues

  • Ensure that Playwright locators are updated if the structure of the web page changes, as stale selectors can cause tests to fail.

  • Always verify that a locator matches only one element unless your test logic expects multiple. Selecting multiple unintended elements can cause test failures or flaky behavior.

  • Use Playwright's auto-wait feature by default to handle elements that might take time to appear or become interactable, avoiding flaky tests.

  • The Playwright Inspector is an invaluable tool for troubleshooting. Use it to explore the page structure, validate selectors, and try out locators interactively in the browser.

# Incorrect: Using a non-unique selector that might match multiple elements
button = page.locator('button').click()

# Correct: Using a unique selector to ensure the correct element is targeted
button = page.locator('button#submit').click()

# Incorrect: Assuming element is immediately available without waiting
product_details = page.locator('div.product-details').text_content()

# Correct: Using auto-wait to ensure element is loaded and interactable
product_details = page.locator('div.product-details').wait_for(state='visible').text_content()

# Incorrect: Using a hardcoded XPath that is brittle and likely to break with UI changes
login_button = page.locator('xpath=/html/body/div[2]/div[1]/button').click()

# Correct: Using a more robust and readable CSS selector or relative XPath
login_button = page.locator('css=button.login').click()

# Incorrect: Not checking if the locator matches any element, leading to potential errors
price = page.locator('div.price').text_content()

# Correct: First check if the locator finds any element before proceeding
if page.locator('div.price').count() > 0:
price = page.locator('div.price').text_content()
else:
print("Price element not found")

Try Oyxlabs' Proxies & Scraper API

Residential Proxies

Self-Service

Human-like scraping without IP blocking

From

8

Datacenter Proxies

Self-Service

Fast and reliable proxies for cost-efficient scraping

From

1.2

Web scraper API

Self-Service

Public data delivery from a majority of websites

From

49

Useful resources

24 Best Website Testing Tools To Use In 2025
24 Best Website Testing Tools To Use In 2025
vytenis kaubre avatar

Vytenis Kaubrė

2025-01-02

Playwright Web Scraping Tutorial for 2025
Playwright Web Scraping Tutorial for 2025
Iveta Vistorskyte avatar

Iveta Vistorskyte

2025-01-02

How to Bypass CAPTCHA With Playwright
How to Bypass CAPTCHA With Playwright
author avatar

Yelyzaveta Nechytailo

2024-10-11

Get the latest news from data gathering world

I'm interested