Skip to main content

Selectors

The WebdriverIO MCP server supports multiple selector strategies for locating elements on web pages and mobile apps.

info

For comprehensive selector documentation including all WebdriverIO selector strategies, see the main Selectors guide. This page focuses on selectors commonly used with the MCP server.

Web Selectorsโ€‹

For browser automation, the MCP server supports all standard WebdriverIO selectors. The most commonly used include:

SelectorExampleDescription
CSS#login-button, .submit-btnStandard CSS selectors
XPath//button[@id='submit']XPath expressions
Textbutton=Submit, a*=ClickWebdriverIO text selectors
ARIAaria/Submit ButtonAccessibility name selectors
Test ID[data-testid="submit"]Recommended for testing

For detailed examples and best practices, see the Selectors documentation.

Mobile Selectorsโ€‹

Mobile selectors work with both iOS and Android platforms through Appium.

Accessibility IDs are the most reliable cross-platform selector. They work on both iOS and Android and are stable across app updates.

# Syntax
~accessibilityId

# Examples
~loginButton
~submitForm
~usernameField
Best Practice

Always prefer accessibility IDs when available. They provide:

  • Cross-platform compatibility (iOS + Android)
  • Stability across UI changes
  • Better test maintainability
  • Improved accessibility of your app

Android Selectorsโ€‹

UiAutomatorโ€‹

UiAutomator selectors are powerful and fast for Android.

# By Text
android=new UiSelector().text("Login")

# By Partial Text
android=new UiSelector().textContains("Log")

# By Resource ID
android=new UiSelector().resourceId("com.example:id/login_button")

# By Class Name
android=new UiSelector().className("android.widget.Button")

# By Description (Accessibility)
android=new UiSelector().description("Login button")

# Combined Conditions
android=new UiSelector().className("android.widget.Button").text("Login")

# Scrollable Container
android=new UiScrollable(new UiSelector().scrollable(true)).scrollIntoView(new UiSelector().text("Item"))

Resource IDโ€‹

Resource IDs provide stable element identification on Android.

# Full Resource ID
id=com.example.app:id/login_button

# Partial ID (app package inferred)
id=login_button

XPath (Android)โ€‹

XPath works on Android but is slower than UiAutomator.

# By Class and Text
//android.widget.Button[@text='Login']

# By Resource ID
//android.widget.EditText[@resource-id='com.example:id/username']

# By Content Description
//android.widget.ImageButton[@content-desc='Menu']

# Hierarchical
//android.widget.LinearLayout/android.widget.Button[1]

iOS Selectorsโ€‹

Predicate Stringโ€‹

iOS Predicate Strings are fast and powerful for iOS automation.

# By Label
-ios predicate string:label == "Login"

# By Partial Label
-ios predicate string:label CONTAINS "Log"

# By Name
-ios predicate string:name == "loginButton"

# By Type
-ios predicate string:type == "XCUIElementTypeButton"

# By Value
-ios predicate string:value == "ON"

# Combined Conditions
-ios predicate string:type == "XCUIElementTypeButton" AND label == "Login"

# Visibility
-ios predicate string:label == "Login" AND visible == 1

# Case Insensitive
-ios predicate string:label ==[c] "login"

Predicate Operators:

OperatorDescription
==Equals
!=Not equals
CONTAINSContains substring
BEGINSWITHStarts with
ENDSWITHEnds with
LIKEWildcard match
MATCHESRegex match
ANDLogical AND
ORLogical OR

Class Chainโ€‹

iOS Class Chains provide hierarchical element location with good performance.

# Direct Child
-ios class chain:**/XCUIElementTypeButton[`label == "Login"`]

# Any Descendant
-ios class chain:**/XCUIElementTypeButton

# By Index
-ios class chain:**/XCUIElementTypeCell[3]

# Combined with Predicate
-ios class chain:**/XCUIElementTypeButton[`name == "submit" AND visible == 1`]

# Hierarchical
-ios class chain:**/XCUIElementTypeTable/XCUIElementTypeCell[`label == "Settings"`]

# Last Element
-ios class chain:**/XCUIElementTypeButton[-1]

XPath (iOS)โ€‹

XPath works on iOS but is slower than predicate strings.

# By Type and Label
//XCUIElementTypeButton[@label='Login']

# By Name
//XCUIElementTypeTextField[@name='username']

# By Value
//XCUIElementTypeSwitch[@value='1']

# Hierarchical
//XCUIElementTypeTable/XCUIElementTypeCell[1]

Cross-Platform Selector Strategyโ€‹

When writing tests that need to work on both iOS and Android, use this priority order:

1. Accessibility ID (Best)โ€‹

# Works on both platforms
~loginButton

2. Platform-Specific with Conditional Logicโ€‹

When accessibility IDs aren't available, use platform-specific selectors:

Android:

android=new UiSelector().text("Login")

iOS:

-ios predicate string:label == "Login"

3. XPath (Last Resort)โ€‹

XPath works on both platforms but with different element types:

Android:

//android.widget.Button[@text='Login']

iOS:

//XCUIElementTypeButton[@label='Login']

Element Types Referenceโ€‹

Android Element Typesโ€‹

TypeDescription
android.widget.ButtonButton
android.widget.EditTextText input
android.widget.TextViewText label
android.widget.ImageViewImage
android.widget.ImageButtonImage button
android.widget.CheckBoxCheckbox
android.widget.RadioButtonRadio button
android.widget.SwitchToggle switch
android.widget.SpinnerDropdown
android.widget.ListViewList view
android.widget.RecyclerViewRecycler view
android.widget.ScrollViewScroll container

iOS Element Typesโ€‹

TypeDescription
XCUIElementTypeButtonButton
XCUIElementTypeTextFieldText input
XCUIElementTypeSecureTextFieldPassword input
XCUIElementTypeStaticTextText label
XCUIElementTypeImageImage
XCUIElementTypeSwitchToggle switch
XCUIElementTypeSliderSlider
XCUIElementTypePickerPicker wheel
XCUIElementTypeTableTable view
XCUIElementTypeCellTable cell
XCUIElementTypeCollectionViewCollection view
XCUIElementTypeScrollViewScroll view

Best Practicesโ€‹

Doโ€‹

  • Use accessibility IDs for stable, cross-platform selectors
  • Add data-testid attributes to web elements for testing
  • Use resource IDs on Android when accessibility IDs aren't available
  • Prefer predicate strings over XPath on iOS
  • Keep selectors simple and specific

Don'tโ€‹

  • Avoid long XPath expressions - they're slow and fragile
  • Don't rely on indices for dynamic lists
  • Avoid text-based selectors for localized apps
  • Don't use absolute XPath (starting from root)

Examples of Good vs Bad Selectorsโ€‹

# Good - Stable accessibility ID
~loginButton

# Bad - Fragile XPath with indices
//div[3]/form/button[2]

# Good - Specific CSS with test ID
[data-testid="submit-button"]

# Bad - Class that might change
.btn-primary-lg-v2

# Good - UiAutomator with resource ID
android=new UiSelector().resourceId("com.app:id/submit")

# Bad - Text that might be localized
android=new UiSelector().text("Submit")

Debugging Selectorsโ€‹

Web (Chrome DevTools)โ€‹

  1. Open Chrome DevTools (F12)
  2. Use the Elements panel to inspect elements
  3. Right-click an element โ†’ Copy โ†’ Copy selector
  4. Test selectors in Console: document.querySelector('your-selector')

Mobile (Appium Inspector)โ€‹

  1. Start Appium Inspector
  2. Connect to your running session
  3. Click on elements to see all available attributes
  4. Use the "Search for element" feature to test selectors

Using get_elementsโ€‹

The MCP server's get_elements tool returns multiple selector strategies for each element:

Ask: "Get all visible elements on the screen"

This returns elements with pre-generated selectors you can use directly.

Advanced Optionsโ€‹

For more control over element discovery:

# Get only images and visual elements
Get visible elements with elementType "visual"

# Get elements with their coordinates for layout debugging
Get visible elements with includeBounds enabled

# Get the next 20 elements (pagination)
Get visible elements with limit 20 and offset 20

# Include layout containers for debugging
Get visible elements with includeContainers enabled

The tool returns a paginated response:

{
"total": 42,
"showing": 20,
"hasMore": true,
"elements": [...]
}

Using get_accessibility (Browser Only)โ€‹

For browser automation, the get_accessibility tool provides semantic information about page elements:

# Get all named accessibility nodes
Get accessibility tree

# Filter to only buttons and links
Get accessibility tree filtered to button and link roles

# Get next page of results
Get accessibility tree with limit 50 and offset 50

This is useful when get_elements doesn't return expected elements, as it queries the browser's native accessibility API.

Welcome! How can I help?

WebdriverIO AI Copilot