How to Click a Button in Selenium Python (2026)

How to Click a Button in Selenium Python (2026)

In Selenium Python, click a button with element.click() after locating it with driver.find_element(). Always use explicit waits (WebDriverWait) before clicking to avoid ElementNotInteractableException. If .click() fails due to overlays or animations, use JavaScript click: driver.execute_script("arguments[0].click();", element).

Key Takeaways

Always wait before clicking. Clicking before an element is interactive causes ElementNotInteractableException. Use WebDriverWait with element_to_be_clickable condition before every click.

.click() fails on hidden or overlapped elements. If another element (overlay, modal, cookie banner) intercepts the click, use JavaScript click as a fallback or scroll the element into view first.

StaleElementReferenceException means the DOM changed. Find the element again after any page navigation, AJAX update, or DOM refresh before attempting to click.

CSS selectors are more reliable than XPath for buttons. button[type='submit'] or .btn-primary is less brittle than complex XPath expressions that break when layout changes.

element_to_be_clickable is not enough on SPAs. On React/Vue/Angular apps, even after the click condition is met, the event handler may not be attached yet. Add a short wait or verify the result after clicking.

Basic Button Click in Selenium Python

The simplest way to click a button:

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://example.com")

button = driver.find_element(By.CSS_SELECTOR, "button[type='submit']")
button.click()

This works when the button is already visible and interactive when the page loads. For dynamic pages (most modern web apps), you need explicit waits.

Clicking Buttons with Explicit Waits

Never click a button without waiting for it to be clickable:

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

driver = webdriver.Chrome()
driver.get("https://example.com/login")

wait = WebDriverWait(driver, 10)

# Wait until the button is clickable (visible + enabled)
submit_button = wait.until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, "button[type='submit']"))
)
submit_button.click()

element_to_be_clickable waits until the element is both visible and enabled. This handles most timing issues with dynamic content.

Finding Buttons by Different Locators

By ID

button = driver.find_element(By.ID, "submit-btn")
button.click()

By CSS Selector

# By button text using CSS (limited)
button = driver.find_element(By.CSS_SELECTOR, ".btn-primary")
button.click()

# By type attribute
button = driver.find_element(By.CSS_SELECTOR, "button[type='submit']")
button.click()

# By data attribute
button = driver.find_element(By.CSS_SELECTOR, "button[data-action='save']")
button.click()

By XPath (for text content)

# Click button by visible text
button = driver.find_element(By.XPATH, "//button[text()='Save Changes']")
button.click()

# Partial text match
button = driver.find_element(By.XPATH, "//button[contains(text(), 'Save')]")
button.click()
button = driver.find_element(By.LINK_TEXT, "Get Started")
button.click()

JavaScript Click: When .click() Fails

When a button is obscured by an overlay, sticky header, or cookie banner, .click() throws ElementClickInterceptedException. Use JavaScript click:

button = driver.find_element(By.CSS_SELECTOR, "#submit-button")
driver.execute_script("arguments[0].click();", button)

When to use JavaScript click:

  • Cookie consent banners blocking the element
  • Sticky navigation headers overlapping content
  • CSS animations still in progress
  • Shadow DOM elements
  • Elements with pointer-events: none that need to be clicked anyway (testing purposes)

Important: JavaScript click bypasses browser event propagation. Some event handlers attached via addEventListener may not fire. Prefer .click() when possible.

Scroll Into View Before Clicking

If a button is below the fold, scroll to it first:

button = driver.find_element(By.CSS_SELECTOR, "#bottom-submit")

# Scroll the element into view
driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", button)

# Wait a moment for any sticky elements to settle
import time
time.sleep(0.5)

button.click()

Or use ActionChains to move to the element before clicking:

from selenium.webdriver.common.action_chains import ActionChains

button = driver.find_element(By.CSS_SELECTOR, "#submit-btn")
ActionChains(driver).move_to_element(button).click().perform()

Common Errors and Fixes

ElementNotInteractableException

Cause: Button exists in DOM but is not visible or not enabled.

# Wrong - clicking before element is ready
button = driver.find_element(By.ID, "submit")
button.click()  # ElementNotInteractableException

# Right - wait for interactive state
button = wait.until(EC.element_to_be_clickable((By.ID, "submit")))
button.click()

ElementClickInterceptedException

Cause: Another element is covering the button.

from selenium.common.exceptions import ElementClickInterceptedException

try:
    button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#submit")))
    button.click()
except ElementClickInterceptedException:
    # Fallback to JavaScript click
    driver.execute_script("arguments[0].click();", button)

StaleElementReferenceException

Cause: The DOM refreshed between finding the element and clicking it.

from selenium.common.exceptions import StaleElementReferenceException
import time

max_retries = 3
for attempt in range(max_retries):
    try:
        button = wait.until(EC.element_to_be_clickable((By.ID, "submit")))
        button.click()
        break
    except StaleElementReferenceException:
        if attempt == max_retries - 1:
            raise
        time.sleep(0.5)

NoSuchElementException

Cause: The selector doesn't match any element.

from selenium.common.exceptions import NoSuchElementException

try:
    button = driver.find_element(By.CSS_SELECTOR, "#submit-btn")
    button.click()
except NoSuchElementException:
    print("Button not found - check your selector")
    # Use driver.page_source to inspect the DOM

Clicking Buttons in Forms

Complete form submission example:

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

driver = webdriver.Chrome()
driver.get("https://example.com/login")
wait = WebDriverWait(driver, 10)

# Fill form fields
email_field = wait.until(EC.presence_of_element_located((By.ID, "email")))
email_field.send_keys("user@example.com")

password_field = driver.find_element(By.ID, "password")
password_field.send_keys("secretpassword")

# Click submit button
submit_button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[type='submit']")))
submit_button.click()

# Verify successful login
wait.until(EC.url_contains("/dashboard"))
print("Login successful!")

Clicking Buttons in Modals and Dialogs

# Wait for modal to appear
modal = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".modal")))

# Click button inside the modal
confirm_button = wait.until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, ".modal .btn-confirm"))
)
confirm_button.click()

# Wait for modal to disappear
wait.until(EC.invisibility_of_element_located((By.CSS_SELECTOR, ".modal")))

Clicking Buttons by Index (Multiple Buttons)

# Get all matching buttons
buttons = driver.find_elements(By.CSS_SELECTOR, "button.action-btn")

# Click the first one
buttons[0].click()

# Click a specific one by index
buttons[2].click()

# Filter by text and click
for button in buttons:
    if button.text == "Delete":
        wait.until(EC.element_to_be_clickable(button))
        button.click()
        break

Verifying Button Click Worked

After clicking, always verify the expected outcome:

# Verify URL changed
submit_button.click()
wait.until(EC.url_to_be("https://example.com/success"))

# Verify element appeared
submit_button.click()
success_message = wait.until(
    EC.visibility_of_element_located((By.CSS_SELECTOR, ".success-toast"))
)
assert "saved" in success_message.text.lower()

# Verify element disappeared
delete_button.click()
wait.until(EC.staleness_of(item_element))

The Real Cost of Selenium Button Clicking

A reliable Selenium test that clicks a button requires:

  • Proper wait strategy (explicit wait with element_to_be_clickable)
  • Exception handling for ElementClickInterceptedException, StaleElementReferenceException
  • JavaScript click fallback for overlay issues
  • Scroll-into-view logic for off-screen buttons
  • Post-click verification

That's 20-40 lines of code for a single button click. And when the page's CSS changes — new sticky header, redesigned modal — your selectors break and you maintain it again.

Alternative: AI-Powered Testing

HelpMeTest handles button clicks with natural language:

Click the "Submit" button

The AI:

  • Finds the button by visual appearance and text, not brittle CSS selectors
  • Waits automatically until it's interactive
  • Handles overlays, scroll position, and timing without code
  • Self-heals when the UI changes

A full login test in HelpMeTest:

Go to https://example.com/login
Type "user@example.com" in the email field
Type "password123" in the password field
Click the "Sign In" button
Verify the dashboard page loads

No locators. No wait strategies. No exception handling. When the UI changes, the AI adapts automatically.

When Selenium button clicking makes sense:

  • Fine-grained control over event types (mousedown, mouseup separately)
  • Testing JavaScript event propagation specifically
  • Complex canvas or custom widget interactions
  • Existing large Selenium test suite you're maintaining

When HelpMeTest makes more sense:

  • User flow testing (login, checkout, signup)
  • Regression testing across UI changes
  • Teams without dedicated automation engineers
  • Rapid test creation for new features

Summary

Scenario Solution
Simple click element.click()
Click after page load WebDriverWait + element_to_be_clickable
Click intercepted by overlay JavaScript click
Element below fold scrollIntoView + click
DOM refreshed Retry with StaleElementReferenceException
Button not found Check selector with driver.page_source

The key to reliable button clicks in Selenium: always wait, always verify, always handle the exceptions.

Read more