Selectors
Flawright selectors are strings that describe how to find a UIA element. They map to FlaUI ConditionFactory calls under the hood.
Syntax
[prefix:]value
If no : is present, the entire string is treated as a name: match (UIA Name). If the string starts with #, it is treated as an AutomationId match. If the string is wrapped in [...], it uses the attribute selector syntax.
Prefix Reference
text: — UIA Name
Matches elements whose AutomationElement.Name equals the given string. This is the default when no prefix is supplied.
page.Locator("text:Save") // explicit
page.Locator("Save") // same — bare string falls back to Name match
Use this for labeled buttons, menu items, and static text controls.
name: — UIA Name (alias)
Identical to text:. Use whichever reads more naturally in context.
page.Locator("name:File")
page.Locator("name:OK")
page.Locator("name:Click Me") // spaces in the value are preserved
Values may contain spaces. The parser greedily reads everything up to the next >>
combinator (or end of the selector string) as the value. Leading and trailing whitespace
is trimmed, so name: Click Me is equivalent to name:Click Me.
If the value itself ever contains the literal string >>, use the quoted form instead:
page.Locator("name:\"Step >> Done\"") // quoted value with >> inside
# — AutomationId
Matches elements by AutomationElement.AutomationId. The # must be the first character.
page.Locator("#btn_ok")
page.Locator("#3") // Calculator digit buttons use numeric IDs
AutomationIds are set by the application developer. They are stable across application runs (unlike runtime-assigned element names) and are the preferred selector for anything that has one. Check with Accessibility Insights or inspect.exe.
automationid: — AutomationId (explicit)
Explicit form of the # shorthand. Prefer # for brevity; use this form if the ID contains special characters that could confuse parsing.
page.Locator("automationid:btn_ok")
class: or classname: — ClassName
Matches elements by AutomationElement.ClassName.
page.Locator("class:Button")
page.Locator("classname:RichTextBox")
role: — UIA ControlType
Matches by AutomationElement.ControlType. Use to select all controls of a given type, or when an element has no stable Name or AutomationId.
page.Locator("role:Button")
page.Locator("role:Edit")
page.Locator("role:ListItem")
controltype: — UIA ControlType (alias)
Identical to role:. Use whichever reads more naturally.
page.Locator("controltype:Button")
page.Locator("controltype:Edit")
page.Locator("controltype:ListItem")
[attr=value] — Attribute selector
Matches elements by a named UIA attribute. Supported attribute names: name, automationid, class, classname, role, controltype.
page.Locator("[name=OK]")
page.Locator("[automationid=btn_save]")
page.Locator("[class=Button]")
page.Locator("[role=Button]")
page.Locator("[controltype=Edit]")
Supported ControlType Values
| Selector value | UIA ControlType |
|---|---|
button |
ControlType.Button |
checkbox |
ControlType.CheckBox |
combobox, dropdown |
ControlType.ComboBox |
edit, textbox, input |
ControlType.Edit |
list |
ControlType.List |
listitem |
ControlType.ListItem |
menu |
ControlType.Menu |
menubar |
ControlType.MenuBar |
menuitem |
ControlType.MenuItem |
radiobutton |
ControlType.RadioButton |
tab |
ControlType.Tab |
tabitem |
ControlType.TabItem |
text, label |
ControlType.Text |
window |
ControlType.Window |
group |
ControlType.Group |
image |
ControlType.Image |
link, hyperlink |
ControlType.Hyperlink |
progressbar |
ControlType.ProgressBar |
scrollbar |
ControlType.ScrollBar |
slider |
ControlType.Slider |
spinner |
ControlType.Spinner |
statusbar |
ControlType.StatusBar |
table |
ControlType.Table |
toolbar |
ControlType.ToolBar |
tooltip |
ControlType.ToolTip |
tree |
ControlType.Tree |
treeitem |
ControlType.TreeItem |
separator |
ControlType.Separator |
pane |
ControlType.Pane |
document |
ControlType.Document |
header |
ControlType.Header |
headeritem |
ControlType.HeaderItem |
Any unrecognized value throws ArgumentException with a message listing the bad value and suggesting valid options. There is no Custom fallback — misspelled or unsupported values are surfaced immediately so the developer can correct them.
Fallback Rules
When no recognized prefix is found and the string does not start with # or [, the whole string is passed to the name: (Name match) branch. This means short strings like "OK" or "Cancel" resolve as Name matches without requiring the prefix.
An unknown colon-prefix (foo:bar) throws ArgumentException. The xpath: prefix explicitly throws NotSupportedException since UIA3 does not have an XPath-compatible tree.
When no element matches, locator actions throw FlawrightTimeoutException after the configured timeout (default 5 seconds).
Nth Element
When a selector matches multiple elements, .First resolves to the first one in UIA tree order (depth-first). To get a specific match by index (0-based):
// Second list item (index 1) — sync, returns a narrowed locator
var item = page.Locator("controltype:ListItem").Nth(1);
// Count total — no waiting, returns current count
var n = await page.Locator("controltype:Button").CountAsync();
// All matching elements — auto-waits for at least one
var all = await page.Locator("controltype:ListItem").AllAsync();
Filtering
Use Filter to narrow down a locator using LocatorFilterOptions. Available predicates include HasText, HasNotText, Has (a locator), and HasNot (a locator).
using Flawright.Locator; // for LocatorFilterOptions
// Only list items whose text contains "Save"
var saveItems = page.Locator("controltype:ListItem")
.Filter(new LocatorFilterOptions { HasText = "Save" });
var first = saveItems.First;
Filters compose: chaining multiple Filter calls ANDs the predicates.
Common Gotchas
class: vs controltype: are different properties
class: (or classname:) matches the Win32 ClassName property of the automation element — the window class name registered with RegisterClass. controltype: matches the UIA ControlType. These are not the same. For example, classic Notepad's textarea has Win32 ClassName Edit (so class:Edit works), but UIA promotes it to ControlType.Document because it is a multi-line edit (so controltype:Edit does not match). When targeting Win32 controls, inspect both properties with Accessibility Insights or inspect.exe and choose the selector prefix that matches what you see.
Localized control names
Windows localizes the names of standard controls in some applications. A button labelled "OK" in English may be different in other locales. Prefer AutomationId over Name for stability across locales.
Virtualized lists
Large list controls (e.g., ListView with virtualization) may not expose off-screen items via UIA. If CountAsync returns fewer items than expected, scroll the list first to materialize the elements.
Dynamic names
Some applications change an element's Name based on state (e.g., a toggle button that reads "Mute" / "Unmute"). Use controltype: or #id selectors when the name is unstable.
Foreground window stealing
If another window takes focus during a test, locator resolution against a specific window still works — FlaUI searches the UIA tree rooted at the recorded Window element, not the active foreground window. However, ClickAsync synthesizes input to the element's on-screen position, so the window should be visible when clicking.
XPath
xpath: selectors throw NotSupportedException. UIA3 does not expose an XPath-compatible tree.