Browser Dropdown Selection
SkillWeb & browsingSelect native and custom browser dropdown options.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Browser Dropdown Selection skill
What this skill tells your AI
The instructions your AI receives, as published by 7757/fan-browser-agent in skills/browser/browser-dropdown-selection/SKILL.md and read by ahel’s review.
Use the latest numbered snapshot and the flat fan.* API inside
browser_run. This is not Playwright: do not use selectors, roles as locator
methods, bare numbers, or legacy single-action browser tools.
Choose the Path
Dropdowns have two shapes:
- A native
<select>owns<option>records that usually have no separate page numbers. Select it directly through its numbered control. - A custom dropdown is a button,
div, combobox, or listbox whose options may appear only after it opens.
fan.select handles native selects and many recognized custom dropdowns by
visible text or value. Use that fast path first when the intended option is
known. The distinction matters only when a custom widget needs an
open-observe-click fallback.
Known Option
Use a current outer-snapshot number with fan.ref(N):
await fan.select(fan.ref(46), "Two");
return {selected: "Two"};
Do not click a native <select> first. Do not invent a number for one of its
options.
When the exact label or value is uncertain, inspect the available choices before selecting:
const target = fan.ref(46);
const menu = await fan.dropdownOptions(target);
const choice = fan.requireUnique(
menu.options.filter(option =>
option.text === "United States" || option.value === "US"
),
"Dropdown choice must be unique"
);
await fan.select(target, choice.text || choice.value);
return {selected: choice.text || choice.value};
fan.dropdownOptions supports native selects and many ARIA/custom widgets.
Never silently use menu.options[0].
Stable Multi-Step Form
Keep controls from the same snapshot in one transaction. This is the preferred path when no new semantic choice appears:
await fan.type(fan.ref(27), "Fan Browser E2E", {clear: true});
await fan.select(fan.ref(46), "Two");
await fan.click(fan.ref(96));
await fan.click(fan.ref(103));
await fan.settle();
return {submitted: true};
Do not observe between these actions merely to refresh numbers. Observe again only when navigation, opening a custom menu, or another dynamic change reveals new elements that were not in the original snapshot.
Custom Dropdown Fallback
If direct inspection or selection cannot resolve a custom widget, open it and use a fresh in-program observation:
const label = element => String(
element.name ||
element.text ||
element.attributes?.["aria-label"] ||
""
).trim();
await fan.click(fan.ref(72));
const opened = await fan.observe();
const option = fan.requireUnique(
opened.elements.filter(element => {
const role = String(
element.role || element.attributes?.role || ""
).toLowerCase();
const tag = String(element.tag || "").toLowerCase();
const optionLike = ["option", "menuitem"].includes(role) ||
["li", "button", "div"].includes(tag);
return optionLike &&
label(element) === "California";
}),
"Open dropdown option must be unique"
);
await fan.click(option);
return {selected: "California"};
Pass the fresh element object directly. Do not turn its index into
fan.ref(...): fan.ref(N) belongs to the outer snapshot generation.
For a searchable combobox, open it, observe the fresh input, type the filter, observe the filtered options, require one exact match, and click that element. Do not press Enter when it might submit the surrounding form.
For a long or virtualized menu, scroll its current observed container with
fan.scroll(container, {down: true, pages: 1}), observe again, and match the
newly rendered option. An option cannot be addressed before it is rendered.
Common Pitfalls
- Reusing
fan.ref(N)after navigation or a fresh observation. - Passing a bare number, CSS selector, or guessed locator to
fan.select. - Selecting by partial text when several options can match.
- Choosing the first candidate instead of calling
fan.requireUnique. - Clicking a native option that has no numbered page element.
- Pressing Enter inside a custom dropdown and submitting the form early.
- Claiming success without checking the final snapshot or returned value.
Verification Checklist
- The trigger came from the current numbered snapshot.
- The option label or value was exact and unique.
- Known controls stayed in one
browser_run. - Newly revealed options came from a fresh
fan.observe(). - The final state confirms the selected value or resulting page effect.
Signals
- GitHub stars
- 38
- Forks
- 6
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
browser-dropdown-selection- Source
- github.com/7757/fan-browser-agent