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.

Use Selenium’s Select helper only when the control is an actual HTML <select>. A dropdown rendered from <div> or <li> elements needs ordinary element interactions: locate and click its trigger, wait for the desired option, click it, then verify the resulting state. The exact locators and verification depend on the page’s DOM.

First confirm that the control is not a native select

A control can look like a dropdown without being an HTML select. The underlying markup determines which Selenium interaction is appropriate. Selenium’s Select wrapper is for native <select> elements; it does not operate JavaScript overlays built from <div> or <li> elements. The Selenium guide to select list elements makes that distinction explicit.

What you find in the DOM Interaction What to synchronize
A native <select> containing <option> elements Use Selenium’s Select wrapper and its selection methods, such as selecting by visible text or value. Wait for the select to be available if the page renders it dynamically.
A custom trigger and menu built from elements such as <div> or <li> Locate and click the trigger, then locate and click the rendered option. Wait for the menu or option to become visible and clickable.

Inspect the live DOM rather than guessing from the control’s appearance. Find the clickable trigger, determine how options are represented, and look for stable identifying attributes, text, or accessible state. A tag name alone cannot tell you which selector will work on a particular site.

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

Why Select fails on a custom dropdown

The wrapper checks that the element is a SELECT. Passing a div or another custom element to it is not a workaround: the helper’s operations apply to native select controls and options, not to arbitrary clickable elements. For a custom widget, use WebDriver element lookup and click methods against the actual rendered markup.

Inspect the widget and choose stable locators

Before writing interaction code, open the target page in a browser and inspect the control in its closed and open states. The menu may not exist in the DOM until the trigger is clicked, or it may exist but be hidden. Identify:

  • The trigger element a user clicks to open the menu.
  • The option element corresponding to the desired choice.
  • A stable selector or attribute for each element, such as a page-provided test attribute, meaningful role or label, or the option’s exact text.
  • A state change that can confirm success, such as a selected class, accessible state, displayed value, or resulting application behavior.

Prefer a selector tied to the widget’s meaning over a positional selector such as “the third div.” Positional selectors can silently target a different element if the page inserts a new item or changes its layout. Use position only when order is part of the page’s intended contract and you have verified that assumption.

Text locators also need care. The same label might appear in a hidden menu, a heading, or another part of the page. Scope the option locator to the menu container when the DOM allows it. If the option has a stable attribute, that may be more reliable than matching broad page text. The site-specific selector cannot be determined without that site’s DOM.

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

Open, wait, click, and verify with explicit waits

Custom controls often update asynchronously: clicking the trigger can cause JavaScript to create or reveal the menu. A click followed immediately by an option lookup may race ahead of that update. Selenium’s explicit waits allow the script to wait for the condition it needs. The expected condition element_to_be_clickable checks that an element is visible and enabled.

This pattern deliberately uses example selectors. Replace them with locators confirmed against the target page, and replace the verification assertion with one that reflects the widget’s real state:

from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

# Assumes `driver` is an already-created Selenium WebDriver
# with the target page loaded.
wait = WebDriverWait(driver, 10)

# Replace with a stable selector from the target page.
trigger = wait.until(
    EC.element_to_be_clickable(
        (By.CSS_SELECTOR, "[data-testid='dropdown-trigger']")
    )
)
trigger.click()

# Replace the text and, ideally, scope this locator to the open menu.
option = wait.until(
    EC.element_to_be_clickable(
        (By.XPATH, "//*[normalize-space()='Desired option']")
    )
)
option.click()

# Verify the actual selected state for this widget.
# For example, inspect its displayed value, selected class,
# accessible state, or an application outcome.

The example does not claim that a page has a data-testid attribute, uses that exact label, or exposes a particular selected-state element. Those details are page-specific. The timeout of 10 seconds is an example wait setting, not a guarantee that every site will load within that time.

Choosing the right wait condition

  • Use element_to_be_clickable for the trigger or option when it must be both visible and enabled before a click.
  • If the menu’s appearance is the important transition, wait for the menu or option to become visible before attempting to interact with it.
  • If the widget updates a displayed value or state after the click, wait for that state to change before asserting success.

Use one synchronization strategy consistently. Selenium warns that mixing implicit and explicit waits can produce unpredictable timeout durations. For this interaction, an explicit wait tied to the menu and selected state makes the sequence easier to reason about than a fixed sleep.

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

Verify selection instead of assuming the click worked

A click completing does not prove that the intended option was selected. The click could have hit the wrong element, the menu could have closed without changing the value, or the application may still be processing the selection. Choose a post-click check based on the widget:

  • Displayed value: confirm the trigger or selection display now shows the intended option.
  • Selected class: confirm the intended option receives the page’s selected-state class, if the widget uses one.
  • Accessible state: check the relevant state exposed in the markup, when present.
  • Application outcome: confirm a dependent field, result, or page behavior changed as expected.

Do not assert against a class name or attribute merely because it appears plausible. Inspect the real markup and identify the state the application actually updates. For a multi-select widget, selection may leave the menu open; for a single-select widget, it may close. Neither behavior can be assumed without examining the page.

Handle asynchronous, hidden, and unusual menus

Options appear only after opening the menu

Locate and click the trigger first, then wait for the relevant option. Trying to wait for a hidden option to be clickable before opening the menu can time out because it is not yet visible or enabled for interaction.

The option is present but not clickable

Check whether the menu is still animating, whether another element overlays it, and whether the target is disabled. Wait for the page’s actual clickable state instead of adding a fixed delay. If the option is outside the visible area, inspect the widget’s behavior and DOM before changing the interaction; the correct remedy depends on its implementation.

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

Repeated labels or nested elements

If the same text appears in multiple places, narrow the locator to the open menu or the relevant widget container. A broad XPath that matches text anywhere in the page is easy to misdirect. If the visible text is nested inside a clickable option element, identify and click the correct option container from the DOM.

Virtualized or framework-managed options

Some controls render only the options currently needed, or alter markup as the user interacts. The available information here does not establish whether a particular page virtualizes options or which framework it uses. Inspect the live DOM and accessible roles and attributes, then wait for the desired option to exist and become actionable. Avoid assuming every choice is present in the document from the start.

Common failures and practical fixes

Symptom Likely cause Fix
Select rejects the element The target is a custom element, not a native <select>. Inspect the DOM and interact with the custom trigger and option elements instead.
The option lookup fails immediately after opening The menu has not yet appeared or become visible. Wait explicitly for the option or menu’s relevant visible state after clicking the trigger.
The click raises an interaction error or has no effect The element may not yet be visible and enabled, or another part of the page may be intercepting interaction. Wait for clickability and inspect the open menu and overlays in the live page.
The wrong matching label is clicked The locator matches duplicate text elsewhere on the page. Scope the locator to the dropdown menu or use a stable option attribute.
The script times out inconsistently The page’s asynchronous state is not being waited on, or implicit and explicit waits are mixed. Wait for the specific state needed at each step and avoid combining the two wait styles.
The click succeeds but the test reports the wrong result The assertion does not match the widget’s real selected-state model. Inspect the post-selection DOM or application behavior and assert against that observable outcome.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance and reliability considerations

Explicit waits add time only while their condition remains unmet, up to the configured timeout; a fixed sleep always delays execution for its full duration, whether the menu is ready earlier or not. Keep waits close to the state transition they protect: trigger click, option readiness, then selection confirmation. This makes failures easier to diagnose and avoids proceeding on assumptions.

A timeout should be long enough for the target environment’s ordinary load behavior but finite so a broken page does not stall a run indefinitely. The example’s value is not a universal recommendation. If a wait expires, inspect whether the page loaded, whether the menu actually opened, and whether the locator matches the current DOM before increasing the timeout.

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

Stable locators and state-based checks usually make a script less sensitive to layout changes than positional selection or arbitrary delays. Reliability still depends on the site: without its URL and DOM, no exact selector, single- versus multi-select behavior, or post-selection assertion can be guaranteed.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server, not a Selenium dropdown-selection replacement. A screenshot can help inspect the rendered page, but it cannot choose an option for your Selenium test. If a visual snapshot is all you need, its one-request API can capture a URL. Replace the example URL with the page you want to capture and use your API key. See the ScreenshotNeo documentation for API details.

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 and Node.js requests:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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 removes supported cookie banners, newsletter popups, and chat widgets before capture; those steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers say which page verdict and billing outcome applied. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents and MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Learn about ScreenshotNeo or sign up for 1,000 free screenshots a month with no card.

Frequently Asked Questions

Can Selenium’s Select class choose an option in a div-based dropdown?

No. It is for native HTML <select> elements. For a custom dropdown, locate and interact with its rendered trigger and option elements.

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.

Why does the example use placeholder selectors?

The target page and its DOM were not specified. Replace the sample selectors and option text with stable locators confirmed from the actual widget.

Does ScreenshotNeo select dropdown options?

No. It captures screenshots and provides page-information and PDF tools; use Selenium or another browser interaction method to select the option.

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.