2025, Dec 27 13:00

SeleniumBase: Fix 'Element not found' when clicking a button by text with a well-formed XPath contains()

Fix SeleniumBase timeouts when clicking a button by text. The cause is an invalid XPath contains(text()) predicate—see one-character fix and locator debugging.

Clicking a button by visible text with SeleniumBase is straightforward when the locator is correct. The tricky part is that even a single missing character in an XPath breaks the selector and sends you down a rabbit hole of “element not found” errors. Here’s a concise walkthrough of a real-world failure and its minimal fix.

Problem statement

You attempt to click a button by its label using an XPath with contains(text(), ...). The run ends with a timeout even though the button clearly exists on the page.

Element {//button[contains(text(), "Sign up"]} was not found after 7 seconds!

Failing example

The following code reproduces the issue. The program opens a target URL, waits briefly, and tries to click the button by text. The click step does not succeed.

from seleniumbase import BaseCase

BaseCase.main(__name__, __file__)

class ParallelDriversSuite(BaseCase):
    def test_multi_sessions(self):
        TARGET = "https://invideo.io/perf/ga-ai-video-generator-web/?utm_source=google&utm_medium=cpc&utm_campaign=Top16_Search_Brand_Exact_EN&adset_name=InVideo&keyword=invideo&network=g&device=c&utm_term=invideo&utm_content=InVideo&matchtype=e&placement=g&campaign_id=18035330768&adset_id=140632017072&ad_id=616240030555&gad_source=1&gclid=Cj0KCQiAvvO7BhC-ARIsAGFyToWFf0L_8iqkB32qg9prKxVApsklZ8HA69LW2O0Z6XC1nbXXz9sCTTEaAinZEALw_wcB""https://invideo.io/perf/ga-ai-video-generator-web/?utm_source=google&utm_medium=cpc&utm_campaign=Top16_Search_Brand_Exact_EN&adset_name=InVideo&keyword=invideo&network=g&device=c&utm_term=invideo&utm_content=InVideo&matchtype=e&placement=g&campaign_id=18035330768&adset_id=140632017072&ad_id=616240030555&gad_source=1&gclid=Cj0KCQiAvvO7BhC-ARIsAGFyToWFf0L_8iqkB32qg9prKxVApsklZ8HA69LW2O0Z6XC1nbXXz9sCTTEaAinZEALw_wcB"
        self.activate_cdp_mode(TARGET)
        brw = self.driver
        brw.sleep(10)
        brw.click('//button[contains(text(), "Sign up"]')

Root cause

The XPath expression is syntactically invalid. The contains function requires a closing parenthesis before the closing bracket in the predicate. In the failing XPath, the ) is missing, so the selector parser can’t evaluate the expression and the element never matches. The timeout message is a consequence of the malformed XPath rather than a visibility or timing issue.

Solution

Close the contains function properly so the predicate is well-formed. With that single character added, the locator works as intended.

from seleniumbase import BaseCase

BaseCase.main(__name__, __file__)

class ParallelDriversSuite(BaseCase):
    def test_multi_sessions(self):
        TARGET = "https://invideo.io/perf/ga-ai-video-generator-web/?utm_source=google&utm_medium=cpc&utm_campaign=Top16_Search_Brand_Exact_EN&adset_name=InVideo&keyword=invideo&network=g&device=c&utm_term=invideo&utm_content=InVideo&matchtype=e&placement=g&campaign_id=18035330768&adset_id=140632017072&ad_id=616240030555&gad_source=1&gclid=Cj0KCQiAvvO7BhC-ARIsAGFyToWFf0L_8iqkB32qg9prKxVApsklZ8HA69LW2O0Z6XC1nbXXz9sCTTEaAinZEALw_wcB""https://invideo.io/perf/ga-ai-video-generator-web/?utm_source=google&utm_medium=cpc&utm_campaign=Top16_Search_Brand_Exact_EN&adset_name=InVideo&keyword=invideo&network=g&device=c&utm_term=invideo&utm_content=InVideo&matchtype=e&placement=g&campaign_id=18035330768&adset_id=140632017072&ad_id=616240030555&gad_source=1&gclid=Cj0KCQiAvvO7BhC-ARIsAGFyToWFf0L_8iqkB32qg9prKxVApsklZ8HA69LW2O0Z6XC1nbXXz9sCTTEaAinZEALw_wcB"
        self.activate_cdp_mode(TARGET)
        brw = self.driver
        brw.sleep(10)
        brw.click('//button[contains(text(), "Sign up")]')

If you want to validate what buttons are available and what text they expose, you can quickly inspect them and print their labels before clicking. This helps confirm you’re targeting the right element text.

buttons = brw.find_elements("xpath", "//button")
for el in buttons:
    print(el.text)

Why this matters

Selectors are the backbone of UI automation. A single missing parenthesis in XPath can look like a timing or flakiness problem, wasting time on retries and waits. Verifying the locator syntax and confirming the actual text rendered on buttons reduces false leads and speeds up debugging.

Conclusion

When clicking elements by text with SeleniumBase, pay close attention to XPath syntax, especially balanced parentheses and brackets in predicates like contains(text(), ...). If a click fails unexpectedly, first sanity-check the selector and, when in doubt, list the visible button texts to ensure you’re matching the right target. Small fixes in the locator often resolve what appears to be a bigger issue.