What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Start with the exception: InvalidSelectorException usually means the selector syntax or locator strategy is wrong; NoSuchElementException means Selenium found no match in the current search context at the moment it looked. For the second error, check page state, timing, and whether the element is inside an iframe or shadow root before rewriting the CSS.

Work through the checks below in order. They help separate a malformed selector from a valid selector being used too early, in the wrong document, or against an outdated element reference.

1. Read the exception before changing the selector

The two errors point to different problems. Fixing a timing issue by changing valid CSS can make a test harder to maintain; adding a wait will not repair invalid selector syntax.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Exception What it indicates First check
InvalidSelectorException The selector cannot be parsed or was passed using an incompatible locator strategy. Check the selector string and the By strategy together.
NoSuchElementException No matching element was available in the searched context at lookup time. Check the page, timing, DOM state, frame or shadow-root context, and locator freshness.

Selenium’s official error guidance identifies invalid characters or syntax, CSS passed as XPath (or the reverse), and a CSS or XPath query passed to an ID locator as causes of InvalidSelectorException. For NoSuchElementException, likely causes include looking on the wrong page, looking before an element exists, an unsuccessful action that should expose it, or a locator that no longer matches the markup.

Read the full exception and the line that failed. If the call itself rejects the selector, correct its syntax or strategy. If it is a lookup that returns no match, continue through the state and context checks below.

2. Match CSS syntax to Selenium’s locator strategy

Use By.CSS_SELECTOR for a CSS query. For example, this asks Selenium to find an element with class information somewhere inside a form:

from selenium.webdriver.common.by import By

element = driver.find_element(By.CSS_SELECTOR, "form .information")

Do not pass CSS syntax to a different locator strategy. For example, #login is a CSS selector, not an ID string for By.ID; use By.CSS_SELECTOR with #login, or use By.ID with login.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Compound classes need CSS

An element can have several classes, such as <button class="primary submit">. A class-name locator accepts one class name, not a space-separated compound class string. To require both classes, use CSS:

button = driver.find_element(By.CSS_SELECTOR, "button.primary.submit")

In CSS, the dot before each class joins the requirements on the same element. A space between selectors means a descendant relationship instead: .primary .submit looks for an element with class submit inside an element with class primary.

Check what the selector actually describes

Compare the selector with the live element’s tag, attributes, and classes. Common mistakes include missing the dot before a class, using a class where an ID is expected, quoting an attribute value incorrectly, or treating a descendant as a sibling. If you need to establish whether there are zero, one, or several matches, use find_elements and inspect the returned list rather than relying only on the first-match lookup.

matches = driver.find_elements(By.CSS_SELECTOR, "form .information")
print(len(matches))

find_element returns the first matching element. A successful call therefore does not prove that the selector is unique; if uniqueness matters to the test, check the match count or choose a more specific locator.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

3. Confirm the current page and live DOM

A syntactically correct selector can still match nothing because the test is on a different page or because the page has changed since the locator was written.

  • Check the current URL and confirm that navigation reached the expected page.
  • Inspect the live DOM in browser developer tools rather than relying on old markup or a saved page snapshot.
  • Verify that the action expected to reveal or create the element actually succeeded.
  • Check whether the element is conditional—for example, shown only after a menu opens, a form is submitted, or data finishes loading.

If the target is absent in the live DOM, a different selector is not the fix. Identify why the page state that should produce it was not reached, then correct the preceding navigation or interaction.

4. Wait for the state the next step needs

Page navigation reaching a document readyState does not guarantee that JavaScript-driven updates have completed. A single-page app may insert an element or reveal it after a click, so an immediate lookup can race with the update.

Use an explicit wait for the condition required by the next operation. For example, this waits up to 10 seconds for an element to be present in the DOM; choose a timeout appropriate to your application rather than treating 10 seconds as universal:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

element = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.CSS_SELECTOR, "form .information"))
)

Presence is suitable when the next step needs an element reference. If the next step needs to interact with the element, wait for the relevant condition instead—for example, visibility before reading or interacting with visible content, or clickability before clicking. An element can be present in the DOM but hidden or not yet interactable.

Avoid timing guesses

Selenium’s “Waiting Strategies” guidance says: “Warning: Do not mix implicit and explicit waits.” The default implicit wait is zero. Mixing an implicit wait with explicit waits can make the total wait unpredictable, so prefer a deliberate explicit wait for the state your test needs rather than layering both kinds of wait.

A fixed sleep is not a dependable general repair: it may still be too short on a slow run and wastes time when the page is ready sooner. Wait for a meaningful condition. If that condition times out, inspect whether the page action, selector, or context is wrong instead of simply increasing the delay repeatedly.

5. Search the right DOM context

Selenium looks in the top-level document by default. A valid selector cannot find content that belongs to a different lookup context.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For an iframe, switch into the frame

First locate the frame element in the current document, then switch to it before searching its contents. This example assumes the frame is a descendant of the element matched by #modal:

frame = driver.find_element(By.CSS_SELECTOR, "#modal iframe")
driver.switch_to.frame(frame)
button = driver.find_element(By.CSS_SELECTOR, "button.submit")

After completing work inside the frame, switch back when the next lookup belongs to the outer page:

driver.switch_to.default_content()

If the frame lookup itself fails, check that the frame exists in the current document and that the selector describes it. If the inner lookup fails after switching, check the frame’s live contents and wait for any dynamic content there to appear.

For shadow DOM, search from the shadow root

Shadow DOM content has its own lookup boundary. With Selenium 4 or later, locate the host, obtain its shadow root, and search from that root:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
host = driver.find_element(By.CSS_SELECTOR, "custom-checkbox-element")
shadow_root = host.shadow_root
checkbox = shadow_root.find_element(
    By.CSS_SELECTOR, "input[type='checkbox']"
)

A top-level lookup for the inner input is not equivalent to searching the shadow root. If finding the host fails, diagnose its selector and the page state first; if the host works but the inner lookup fails, check the actual shadow-root contents and the selector used within that root.

6. Re-find elements after navigation or DOM replacement

An element reference is tied to the DOM element Selenium located. Navigation, refreshes, or a framework rerender can replace that node. Selenium does not automatically relocate a stored reference after the page changes.

When a later operation uses an element found before a navigation or DOM replacement, locate it again in the current page and context. If the failure is instead a stale-element error, the old reference is no longer usable; re-find the target after the update rather than assuming that the original object tracks the new DOM.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

7. Make the locator easier to keep working

Once the immediate failure is fixed, reduce the chance of the same problem returning. Selenium’s locator guidance recommends a unique, predictable ID where one is available; otherwise, a well-written CSS selector is preferred.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Prefer a stable, readable selector over a long chain of structural relationships.
  • Use an ID only when it is present and predictable for the target.
  • Scope a lookup to a useful parent only when the target really is its descendant.
  • Use a scoped lookup to disambiguate repeated elements, not to hide that the test is in the wrong context.
  • After a page transition or rerender, find the current element again.

Short selectors are not automatically correct: they still need to identify the intended element in the current DOM. Check both whether the selector matches and whether it matches the right element.

8. A practical diagnosis order

  1. Classify the exception. Correct malformed CSS or a mismatched locator strategy for InvalidSelectorException; investigate an unavailable match for NoSuchElementException.
  2. Check the selector against live markup. Confirm the tag, ID, classes, attributes, and relationship being described.
  3. Check the page and preceding action. Verify the expected URL and that the action which should reveal the target succeeded.
  4. Wait for the required state. Use an explicit condition suited to the next operation.
  5. Check the search context. Switch into the correct iframe or search through the correct shadow root.
  6. Refresh the reference if the DOM changed. Locate the current element after navigation, refresh, or rerender.
  7. Make the working locator durable. Prefer a stable ID or compact, readable CSS and confirm it identifies the intended element.

9. Troubleshooting common failure patterns

Symptom Likely cause Repair
InvalidSelectorException immediately at lookup Malformed CSS, CSS passed to XPath/ID strategy, or another strategy mismatch. Validate the selector and pair it with By.CSS_SELECTOR when it is CSS.
Compound class lookup fails A space-separated class string was passed to the class-name strategy. Use CSS such as .primary.submit for both classes on one element.
Lookup fails just after a click or navigation The update is asynchronous, or the action did not produce the expected state. Verify the action, then wait for presence, visibility, or clickability as needed.
Target appears in developer tools but not to Selenium The target is in an iframe or shadow root rather than the top-level search context. Switch to the iframe or search from the host’s shadow root.
Lookup worked earlier but later use fails The page navigated or replaced the DOM node, leaving an old reference. Locate a fresh element in the current page and context.
Wait times out despite a plausible selector The waited-for state never occurred, the selector is wrong, or the lookup is in the wrong context. Check the live DOM and preceding action, then verify the state and context being waited on.

10. Or skip the browser setup

For a screenshot of the page you are diagnosing, ScreenshotNeo can capture it with one request. A screenshot can help document the visible page state, but it does not replace inspecting the DOM or establish why a Selenium locator failed. See the ScreenshotNeo API documentation for request options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

ScreenshotNeo removes cookie or consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and the response includes X-Page-Verdict and X-Billed headers. Its MCP server gives AI agents tools for screenshots, page information, and PDF capture. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. These are ScreenshotNeo plan allowances and prices, not Selenium wait or browser-performance figures.

Sign up for ScreenshotNeo free: 1,000 screenshots a month, no card required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Frequently Asked Questions

Should I use find_element or find_elements to debug a missing CSS match?

Use find_elements when you want a count or to inspect all matches without a no-match exception; use find_element when the test requires a matching element and should fail if none is available.

Does a successful CSS lookup prove the locator is unique?

No. find_element returns the first match. Check the number of matches if uniqueness is part of the test’s requirement.

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.