Recommended Free Tools
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use Selenium’s current Python locator syntax, driver.find_element(By.ID, "submit"), then call .click(). For a page that renders or enables the control asynchronously, wait for the condition you actually need—usually element_to_be_clickable—before clicking. The examples below show how to choose a locator, distinguish a single match from multiple matches, and diagnose common failures.
Locate and click a control
Import By from Selenium’s locator module, pass a locator strategy and value to find_element, then call click() on the returned WebElement:
from selenium.webdriver.common.by import By
button = driver.find_element(By.ID, "submit")
button.click()
This short version is suitable when the page is already loaded and the target is present and ready to interact with. For a dynamic page, use an explicit wait instead:
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
button = wait.until(
EC.element_to_be_clickable((By.ID, "submit"))
)
button.click()
The locator passed to the wait is a tuple: the strategy, followed by its value. The wait returns the matching element once the condition is met, so the returned WebElement can be clicked directly.
#1 Best Overall
Complete example
This script opens a page, waits for an element whose ID is submit to become clickable, clicks it, and closes the browser even if a step raises an exception. Replace the example URL and locator with the ones for your page. It assumes Selenium is installed and a compatible Chrome browser and driver setup is available.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
url = "https://example.com"
driver = webdriver.Chrome()
try:
driver.get(url)
wait = WebDriverWait(driver, 10)
button = wait.until(
EC.element_to_be_clickable((By.ID, "submit"))
)
button.click()
finally:
driver.quit()
Choose the locator that identifies the right element
Selenium supports several locator strategies through By. The best one is not necessarily the shortest: it should identify the intended control clearly and remain stable as the page changes.
| Strategy | Example | Useful when | Trade-off |
|---|---|---|---|
By.ID |
(By.ID, "submit") |
The page gives the control a unique, stable ID. | Only dependable if the ID is present and unique in the relevant page context. |
By.NAME |
(By.NAME, "email") |
A form control has a meaningful name attribute. | Several controls can share a name, so check whether the match is unique. |
By.CSS_SELECTOR |
(By.CSS_SELECTOR, "button[type='submit']") |
You need to match attributes, classes, or simple element structure concisely. | A long selector tied to incidental page structure can be hard to maintain. |
By.XPATH |
(By.XPATH, "//button[@type='submit']") |
You need a relationship between elements or a text-based condition. | Complex expressions are harder to read and can become brittle when the DOM changes. |
By.CLASS_NAME |
(By.CLASS_NAME, "primary") |
A useful class identifies the target. | Classes are often shared among many elements; this may return the wrong first match. |
By.TAG_NAME |
(By.TAG_NAME, "button") |
You intend to inspect or collect elements by HTML tag. | Usually too broad for locating one specific control on a page. |
By.LINK_TEXT / By.PARTIAL_LINK_TEXT |
(By.LINK_TEXT, "Continue") |
A link’s visible wording is a useful identifier. | Copy edits, localization, or repeated link labels can make the match fail or become ambiguous. |
Selenium also documents RelativeBy for relative element location. For ordinary click scripts, start with a stable unique attribute such as an ID when the application provides one. Use CSS for straightforward attribute and structure matches; choose XPath when a relationship or text condition genuinely helps. Keep either expression readable and anchored to meaningful attributes rather than a fragile chain of containers.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallRank #2
CSS selector and XPath examples
# CSS: a submit button
button = driver.find_element(
By.CSS_SELECTOR, "button[type='submit']"
)
# XPath: a button with a specific accessible page label
button = driver.find_element(
By.XPATH, "//button[normalize-space()='Continue']"
)
button.click()
Text-based lookup is convenient when the visible wording is distinctive, but it couples the script to that wording. For sites with multiple languages or frequently edited copy, a stable ID, name, or data attribute is usually a better anchor if available.
find_element versus find_elements
find_element(by, value) returns the first matching WebElement. Use it when your locator is intended to find one control. If there is no match, Selenium raises an exception rather than returning an empty value.
find_elements(by, value) returns a list of every matching WebElement; if there are no matches, the result is an empty list. Use it for repeated cards, rows, links, or controls, and make a deliberate choice instead of assuming the first item is the one you want.
Rank #3
buttons = driver.find_elements(By.CSS_SELECTOR, "button.action")
if not buttons:
raise RuntimeError("No action buttons were found")
# Click a chosen match only after confirming the selection rule.
buttons[0].click()
Indexing the first result is appropriate only when page order is itself a reliable selection rule. If the target has a distinguishing attribute or nearby context, narrow the locator rather than relying on list order.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Wait for the guarantee your click needs
A page can contain an element before it is visible or enabled. Choose an explicit-wait condition according to the state required for the next action:
| Condition | What it establishes | When to use it |
|---|---|---|
presence_of_element_located |
The element exists in the DOM. | When the next step only needs DOM presence; it does not establish visibility. |
visibility_of_element_located |
The element exists and is displayed with height and width greater than zero. | When the next step needs a visible target, but does not require that it be enabled. |
element_to_be_clickable |
The element is visible and enabled, and the wait returns it. | For a typical user-like click on a control that may appear or become enabled after rendering or validation. |
For example, use presence when waiting for a hidden element that a later step will inspect; use visibility when it must be displayed; use clickability when you intend to click. A presence wait alone does not mean the target is ready for a user-like interaction.
Rank #4
wait = WebDriverWait(driver, 10)
# Wait for a result panel to be inserted in the DOM.
panel = wait.until(
EC.presence_of_element_located((By.ID, "results"))
)
# Wait for a control to be displayed and enabled before clicking.
button = wait.until(
EC.element_to_be_clickable((By.ID, "submit"))
)
button.click()
Use an explicit wait when asynchronous rendering, a transition, or form validation determines when the target is ready. Pick a timeout appropriate to the application and environment; an explicit wait is a maximum wait, not a reason to pause for the full interval when its condition succeeds sooner.
Use the current Selenium Python API
Use driver.find_element(By.ID, "submit"), with By imported from selenium.webdriver.common.by. Older examples may show locator-specific calls such as find_element_by_id; Selenium’s Python guidance says those methods were being removed after Selenium 4.2. New scripts should use the By-based form rather than copy that older syntax.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Troubleshoot a click that fails
- No element found: Check the locator spelling and whether the page has reached the state where the element exists. If rendering is asynchronous, wait for presence or a stronger condition instead of looking up the element immediately.
- The wrong element was selected: Check whether the locator matches multiple controls. Use a more specific stable attribute, or retrieve all matches with
find_elementsand apply an explicit selection rule. - The element exists but is not usable: A presence check does not guarantee visibility or enabled state. Wait for visibility or clickability according to the action you need.
- Click intercepted by an overlay: A modal, banner, or other overlay may be covering the target. Wait for the overlay to disappear and then wait for the target to become clickable. Do not make JavaScript click the default workaround; it bypasses the normal user-like interaction and can conceal the actual page state.
- Element is inside an iframe: Switch WebDriver into the relevant frame before locating the element. After the interaction, switch back to the default content when subsequent work belongs to the main page.
- Stale element reference after a rerender: The DOM node you stored may have been replaced. Locate the element again after the rerender, then act on the fresh WebElement.
- Wait times out: Confirm that the locator is correct in the current frame and that the expected state can actually occur. If the control remains disabled until a field is valid, meet that prerequisite before waiting for clickability.
Or skip the browser setup
Selenium is the right fit when you need to interact with a page, including clicking a control. If your actual goal is only to save a page image or PDF, a screenshot API can avoid setting up a browser and WebDriver. ScreenshotNeo is a website screenshot API and MCP server, not a replacement for Selenium clicks. Its one-call endpoint returns a PNG, JPEG, WebP, or PDF screenshot for a URL.
Best Value
Python example, following the ScreenshotNeo API documentation:
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)
Equivalent cURL call:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Node.js example:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo accepts a cookie or consent banner as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. See ScreenshotNeo for the service and sign up for the free plan.
Frequently Asked Questions
Does click() wait for the page’s next navigation to finish?
Not necessarily. A successful click means Selenium issued the element interaction; it does not by itself confirm that the application reached the result you expect. For navigation or an in-page update, wait for a page-specific outcome such as the destination URL or a result element before continuing.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsShould I use JavaScript to click when Selenium reports an intercepted click?
Not as the first fix. An intercepted click usually indicates the target is covered or not yet in the expected state. Resolve the overlay or timing issue and retry a normal WebElement click; JavaScript can bypass behavior that the script should be testing.
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.

