Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
In Selenium, find the element with driver.find_element(By.CSS_SELECTOR, selector) and call .click(). In Playwright, use page.locator(selector).click(). The selector identifies the target; the click API performs the action. For dynamic pages, the key difference is synchronization: Playwright’s locator click includes actionability checks, while Selenium scripts typically need you to choose a wait strategy.
Click an element with CSS in Selenium Python
Import Selenium’s By locator strategy, pass a CSS selector to find_element, then click the returned element:
from selenium.webdriver.common.by import By
button = driver.find_element(By.CSS_SELECTOR, "button.submit")
button.click()
This uses Selenium’s synchronous WebDriver API. The call to find_element returns one matching element; .click() acts on that element. If your selector matches several controls, make it more specific rather than relying on which match happens to be returned.
Common CSS selectors
# ID
button = driver.find_element(By.CSS_SELECTOR, "#login")
button.click()
# Class
button = driver.find_element(By.CSS_SELECTOR, ".primary-button")
button.click()
# Attribute
button = driver.find_element(By.CSS_SELECTOR, "button[data-testid='save']")
button.click()
# Descendant: submit button inside the profile form
button = driver.find_element(
By.CSS_SELECTOR,
"form#profile button[type='submit']"
)
button.click()
Use the selector that best expresses the intended control. An ID, a deliberate data-* attribute, or a meaningful form-and-button combination is usually easier to understand and maintain than a generated class name or a long chain of nested elements.
#1 Best Overall
Use an explicit wait when the element is added later
A page may still be loading or rendering when your script searches for a control. In that case, a direct lookup can fail even when the selector is correct. Wait for the page’s relevant state, then locate the element as close as practical to the click. Choose a condition and timeout that fit the page; there is no single timeout that is right for every site.
Do not treat a wait as a cure for a bad selector. First confirm that the intended element exists and that the selector identifies it. If a page is dynamic, waiting for the relevant element to become available is more useful than adding an arbitrary pause that may be too short on a slow run and wasteful on a fast one.
Click an element with CSS in Playwright Python
Playwright’s locator API accepts CSS selectors. Create a locator and call its click method:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #2
button = page.locator("button.submit")
button.click()
The asynchronous form uses the same locator and awaits the action:
button = page.locator("button.submit")
await button.click()
Use the form that matches how the rest of your Playwright script is written; do not omit await in an asynchronous function. A locator click performs actionability checks and scrolls the target into view before attempting the action. It can retry checks when the element changes during them. That built-in handling is useful on changing pages, but it cannot make an incorrect selector point to the right control.
Prefer user-facing locators where they fit
CSS is useful when the application exposes a stable attribute or when the target is naturally described by its markup. When the goal is to identify a control as a user would, a role locator can be clearer:
page.get_by_role("button", name="Save").click()
If your application provides an explicit test ID, that can serve as a stable testing contract:
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →page.locator("[data-testid='save-button']").click()
Playwright cautions that CSS and XPath selectors tied to DOM structure can become fragile as the DOM changes. Prefer a role-based locator when it describes the intended control; use a test ID when the application defines a deliberate selector contract. CSS remains appropriate when its target is stable and unambiguous.
Choose a selector that survives page changes
A click can work today and break after a redesign if the selector depends on incidental implementation details. The most reliable selector is not necessarily the shortest one; it is the one that continues to identify the same intended control when unrelated markup changes.
- Prefer meaningful, stable attributes. Use a stable ID, a deliberate
data-testid, or another attribute intended to identify the control. - Avoid generated class names. Build tools and stylesheets can change them without changing the user-facing button.
- Keep structure selectors shallow. A selector depending on several nested wrappers can break when a container is inserted or moved.
- Constrain repeated controls. If a page has several Save buttons, scope the selector to a meaningful form or container, or use a role locator with the accessible name.
- Check the target, not just the syntax. A valid CSS selector can still match the wrong element or multiple elements.
For example, form#profile button[type='submit'] describes a submit button in a named form. A long selector that names every wrapper between the page root and that button may be more specific but less resilient.
Selenium and Playwright: what changes?
| Concern | Selenium Python | Playwright Python |
|---|---|---|
| CSS lookup and click | driver.find_element(By.CSS_SELECTOR, selector).click() |
page.locator(selector).click() |
| Synchronization | Choose a wait strategy for dynamic content; a direct lookup can happen before the element is available. | Locator clicks include actionability checks, scroll the element into view, and retry checks when the element changes. |
| Python style | The examples use synchronous WebDriver calls. | Both synchronous and asynchronous locator-click forms are available. |
| Selector resilience | Favor stable IDs, names, or deliberate data-* attributes over generated classes and deep chains. |
CSS works, but Playwright advises against selectors coupled to changing DOM structure; role and test-ID locators are alternatives. |
The practical choice is not simply “CSS versus no CSS”: both tools accept CSS. Decide whether the target has a durable CSS hook, whether the page is dynamic, and whether a user-facing role or explicit test contract better communicates what the test intends to click.
Troubleshoot a CSS-selector click
| Symptom | Likely cause | What to check or change |
|---|---|---|
Selenium raises NoSuchElementException |
The element is not in the DOM yet, the selector is wrong, or the target is in a frame or shadow root. | Verify the selector and page state. Wait until the relevant element is available, then locate it again immediately before clicking. Check whether the target is inside a frame or shadow root. |
| Playwright click times out | The locator did not resolve to an actionable element within the configured limit. | Check the selector, visibility, overlays, frames, and whether the locator describes the intended unique control. |
| The click goes to the wrong control | The selector matches multiple similar elements or is scoped too broadly. | Narrow it with a stable attribute or a meaningful container; in Playwright, consider a role locator with the control’s name. |
| The test breaks after a UI change | The selector depends on generated classes or DOM structure that changed. | Replace it with a stable ID, deliberate test attribute, or user-facing role locator where appropriate. |
| The target appears on screen, but lookup fails | It may be rendered in a frame or shadow root rather than the document context being searched. | Confirm the element’s browsing context and use the framework’s support for that context before trying the CSS click again. |
| The click is attempted while the page is still changing | The script reaches the action before the target is ready. | Synchronize on the relevant page state instead of adding an unexplained fixed delay. Playwright locator clicks include actionability handling; in Selenium, select an explicit wait suited to the page. |
When diagnosing a failure, separate three questions: does the selector match the intended element, is that element available in the context being searched, and is it ready to receive a click? Changing the selector will not fix a frame-context issue, and adding a wait will not fix a selector that points at the wrong control.
Best Value
Or skip the browser setup
If your goal is to capture a page rather than build a browser test, ScreenshotNeo is a website screenshot API and MCP server. Its API can click an element before capture, but for a page interaction that requires inspecting results or making decisions, use Selenium or Playwright. For a screenshot request, a Python call looks like this; see the ScreenshotNeo API documentation for the request options:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
Before a capture, ScreenshotNeo accepts cookie or consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each of those steps can be turned off. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers. Its MCP server gives Claude, Cursor, and other MCP clients the tools take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.
Sign up for 1,000 free screenshots a month, with no card required.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsOfficial guidance
Selenium’s locator guide documents By.CSS_SELECTOR for CSS-based element selection. Playwright’s locator guidance documents CSS support and the behavior of locator clicks, and recommends selectors less coupled to DOM structure. Those principles explain why the two short click examples are similar while their synchronization behavior differs.
Frequently Asked Questions
Can I use a CSS selector to click a link as well as a button?
Yes. CSS selects elements by their markup and attributes, not by whether they are buttons or links. Choose a selector that identifies the intended link uniquely.
Does a successful click prove that the page action completed?
No. A click call performs the interaction; your script should separately check the page state or result that matters to the task.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →

