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 by RTOForm.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 waitForSelector before click / 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.
  • getHtml is 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)).

ActionTypical payload fieldsNotes
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_FOUND or TIMEOUT.
  • If the element is inside an iframe, it will typically be unreachable (top-frame only).

Next