DOM automation API
Run safe, named DOM actions inside a controlled tab (no arbitrary code execution).
Docs updated: 2026-03-24
Basics
- DOM actions are sent as
type:"command"messages (wrapped byRTOForm.command({ action: "...", ... }, opts)). - Most actions require
{ tabKey, selector }in the payload. - Top-frame only: DOM actions run in the controlled tab’s top frame (iframes are intentionally ignored).
- For dynamic pages, always call
waitForSelectorbeforeclick/getText/setValue.
Safety rules you will see in errors
PROTECTED_ELEMENT: the extension blocks touching its own injected UI/protected nodes.- Sensitive fields are blocked: password/hidden inputs and common credit-card/iban/password-like names.
getHtmlis sanitized/redacted and typically truncated (for safety + size limits).
Supported actions (canonical)
These are the named actions handled by the content script (called via RTOForm.command({ action: "...", ... }, opts)).
| Action | Typical payload fields | Notes |
|---|---|---|
waitForSelector | { selector, timeoutMs?, pollMs? } | Wait until an element exists. |
click | { selector } | Clicks an element (protected nodes blocked). |
focusElement | { selector } | Focus an element. |
submit | { selector } | selector must target a <form>. |
setValue | { selector, value } | Inputs/textareas/selects/contentEditable; sensitive blocked. |
typeText | { selector, text, clear?, delayMs? } | Simulated typing; sensitive blocked. |
pressKey | { key, selector? } | Dispatches key events; focuses selector if provided. |
getText | { selector, timeoutMs?, pollMs? } | Returns text; supports wait loop. |
getValue | { selector, timeoutMs?, pollMs? } | Reads value if present (protected blocked). |
getAttr | { selector, name, timeoutMs?, pollMs? } | Reads an attribute (protected blocked). |
getHtml | { selector?, property?, allowBodyFallback? } | Sanitized outerHTML; redacts inputs; typically truncated. |
setInnerHtml | { selector, html } | Sanitizes: removes scripts/iframes/handlers/javascript: URLs. |
setChecked | { selector, checked } | Checkbox/radio only. |
selectOption | { selector, value? , label? , index? , values? } | Supports multi-select via values. |
selectSetValue | { selector, value } | Set a <select> by value. |
highlight | { selector, color?, ms?, clear?, mode? } | Debug highlight, can clear. |
domSetStyle | { selector, style } | Allow-list of safe CSS props only. |
injectCss | { css } | Injects a style tag. |
addClass | { selector, className } | Adds a class. |
overlayCreate | { x?, y?, size?, color?, pulse?, appearance? } | Creates cursor overlay (debug). |
overlayStyle | { appearance } | Change overlay appearance. |
overlayMove | { x1,y1,x2,y2,durationMs?,easing?,appearance? } | Animated move. |
overlayMoveTo | { selector, pad?, durationMs?, easing? } | Moves overlay to selector center. |
overlayMoveToWait | { selector, timeoutMs?, pollMs?, pad?, durationMs?, easing?, appearance? } | Waits then moves. |
overlayLabel | { text?, placement?, dx?, dy?, bg?, color?, persist?, show? } | Shows/hides label; can persist defaults. |
overlayHide | { destroy? } | Hides or destroys overlay. |
domExtractBlock | { selector?, selectorList?, nth?, ascend?, root?, rootStrategy?, allowTags?, allowAttrs?, maxDepth?, maxNodes?, maxChars?, visibleOnly?, avoid?, preWait?, timeoutMs?, pollMs? } | Extracts a safe HTML/text block. |
Note: The JS helpers (like
RTO_DOM_actions.js) may add convenience wrappers to RTOForm, but the authoritative list is the action names above.
Common examples
Login pattern
const tabKey = "app";
await RTOForm.waitForSelector({ tabKey: tabKey, selector: "#email" }, { timeoutMs: 8000 });
await RTOForm.setValue({ tabKey: tabKey, selector: "#email", value: "user@example.com" });
// If the target is a password field, it may be blocked by design.
// Prefer manual login or a non-sensitive auth mechanism.
await RTOForm.setValue({ tabKey: tabKey, selector: "#password", value: "••••••••" });
await RTOForm.click({ tabKey: tabKey, selector: "button[type=submit]" });
await RTOForm.waitForSelector({ tabKey: tabKey, selector: "#dashboard" }, { timeoutMs: 15000 });
Read + write HTML
const tabKey = "app";
// Read HTML (property can be "outerHTML", "innerText", "textContent", "value", etc.)
const res = await RTOForm.getHtml({ tabKey: tabKey, selector: "#content", prop: "outerHTML" });
console.log("result:", res);
// Write HTML (sanitized: scripts/handlers/iframes removed)
await RTOForm.setInnerHtml({ tabKey: tabKey, selector: "#content", html: "Hello" });
Overlay (debug)
const tabKey = "app";
await RTOForm.command(
{ action: "overlayCreate", appearance: { kind: "ring", size: 22, color: "#111", pulse: true } },
{ tabKey: tabKey }
);
await RTOForm.command(
{ action: "overlayLabel", text: "Click here", placement: "top" },
{ tabKey: tabKey }
);
await RTOForm.command(
{ action: "overlayMoveTo", selector: "#submit", durationMs: 800, easing: "easeInOut" },
{ tabKey: tabKey }
);
await RTOForm.command(
{ action: "overlayHide" },
{ tabKey: tabKey }
);
Selector tips
- Prefer stable IDs:
#login,#submit. - Prefer semantic attributes:
[name=email],[data-test=submit],[data-testid]. - Avoid fragile selectors:
div:nth-child(3) > span. - If a selector fails, you will often see
ELEMENT_NOT_FOUNDorTIMEOUT. - If the element is inside an iframe, it will typically be unreachable (top-frame only).