Interactive Elements
Detect all clickable and interactive elements on a page.
The interactive element detector finds every clickable/interactive element on a page — including those without ARIA roles, like JS onclick handlers and cursor:pointer styled elements.
Usage
import { detectInteractiveElements } from "feedstock";
// Requires a Playwright Page object
crawler.setHook("beforeReturnHtml", async (page) => {
const elements = await detectInteractiveElements(page);
for (const el of elements) {
console.log(`${el.tag} "${el.text}" (${el.role ?? el.type ?? "clickable"})`);
// a "About Us" (link)
// button "Submit" (button)
// div "Click me" (clickable)
// input "" (email)
}
});What's Detected
- Standard interactive elements:
<a>,<button>,<input>,<textarea>,<select> - ARIA roles:
[role="button"],[role="link"],[role="tab"], etc. - Tabindex elements:
[tabindex] - Contenteditable:
[contenteditable="true"] - Cursor-pointer CSS: Elements with
cursor: pointer(catches styled divs/spans with JS handlers) - onclick handlers: Elements with
onclickattribute
Element Shape
interface InteractiveElement {
tag: string; // "a", "button", "div", etc.
text: string; // visible text (truncated to 100 chars)
href: string | null; // for links
role: string | null; // ARIA role if present
type: string | null; // input type if present
selector: string; // CSS selector for targeting
}Deduplication
- Elements found via multiple selectors are only reported once
- Inherited
cursor: pointerfrom parents is excluded (only the actual interactive element is reported) - Hidden elements (
offsetParent === null) are excluded