From Selenium-derived Commands to the uiv.* API

Ui.Vision's classic table macros are Selenium-derived: the command | target | value format, the command names (click, type, storeText, verifyText...) and the locators all come from the Selenium IDE heritage. That made Ui.Vision instantly familiar to a generation of Selenium users — and it still works today.

The modern automation API takes the next step: a macro is a plain JavaScript program built on the uiv.* API. Loops, conditions, retries and calculations are real JavaScript — no more gotoIf label jumping, no !csvLine magic variables, no counting end commands. Finders auto-wait, matches feed input tiers, and errors are ordinary exceptions.

Your existing Selenium-style macros keep working — nothing is removed or broken. And most users will never convert by hand: the built-in AI sidebar converts a classic macro to a JS script automatically when you ask it to fix or extend one (the original table macro file is never modified; the converted copy is saved to the "AI Generated" folder). This page is for everyone who wants to understand the new API coming from the Selenium world — every classic command and its modern translation.

The Big Five Differences

Selenium-derived (classic) Modern uiv.* API Comment
Variables: ${myvar}, created with store Plain JavaScript variables: const price = 42; uiv.getVar('!URL') / uiv.setVar(...) read and write the same pool the classic commands use — internal !-variables included.
Flow control commands: if / while / times / forEach / label / gotoIf / gotoLabel / end Real JavaScript: if / else, for, while, for...of, functions Reads top to bottom instead of jumping between labels.
Errors: !errorignore, !statusOK, onError try { ... } catch (e) { ... } and throw new Error('...') A failed uiv call throws a real exception — the catch block can say exactly what to do next.
Waiting: waitForElementVisible, pause commands Finders auto-wait: uiv.$('css=.results') waits up to !TIMEOUT_WAIT, then throws Finding an element IS the wait. uiv.open() waits for the page load, a click that navigates is waited for automatically.
Frames: selectFrame | index=2 before every access Not needed — uiv.$() finds elements in ALL frames, even cross-origin iframes, and in open shadow roots The selectFrame concept does not exist in the modern API.

A Complete Example, Side by Side

A typical search flow — Selenium-style on the left, modern API on the right:

Selenium-derived (classic) Modern uiv.* API
open       | https://en.wikipedia.org
type       | id=searchInput | Solar cell
sendKeys   | id=searchInput | ${KEY_ENTER}
waitForElementVisible | id=firstHeading
storeText  | id=firstHeading | myresult
echo       | Landed on: ${myresult}
uiv.open('https://en.wikipedia.org');
uiv.page.type('id=searchInput', 'Solar cell');
uiv.browser.type('${KEY_ENTER}', {nav: true});
const h1 = uiv.$('css=#firstHeading'); // auto-waits
uiv.log(`Landed on: ${h1.text}`, 'green');

Input Commands: Three Explicit Tiers

Selenium WebDriver has one way to click. The modern API names how the input reaches the page — because that is what decides whether it works: uiv.page.* (fast synthetic DOM events, like Selenium), uiv.browser.* (trusted browser input via the debugger API — for canvas apps, drag & drop and sites that ignore synthetic clicks; Chrome/Edge, no XModule needed) and uiv.desktop.* (real OS input via the XModule — reaches OS dialogs and other apps).

Selenium-derived (classic) Modern uiv.* API Comment
click | id=buy uiv.page.click('id=buy') Locators work unchanged: css= id= name= link= xpath=. If a synthetic click is ignored, escalate to uiv.browser.click('id=buy') — a trusted event.
type | id=email | [email protected] uiv.page.type('id=email', '[email protected]') Fills the field in one call, no click-to-focus needed.
sendKeys | id=q | ${KEY_ENTER} uiv.browser.type('${KEY_ENTER}', {nav: true}) Keystrokes go to the focused element. {nav: true} waits for a navigation the keystroke causes.
select | id=cars | label=Volvo uiv.page.select('id=cars', 'Volvo') Also 'value=...' / 'index=N'. Works even when the select is hidden behind a styled skin.
check / uncheck | id=box uiv.page.click('id=box') plus a read-back of the checked state via uiv.eval  
mouseOver | css=.menu uiv.browser.move('css=.menu') A real hover, so CSS hover menus open.
dragAndDropToObject uiv.browser.down(start); uiv.browser.up(end) Press, move, release. Every uiv.browser.move between down and up drags. Works on canvas apps and sliders that ignore synthetic drag events.
clickAt (deprecated) uiv.browser.click(x, y) Coordinates in viewport CSS pixels — or better, click a match from a finder.
editContent | css=.editor | text uiv.browser.click('css=.editor'); uiv.browser.type('text') Rich text editors (contenteditable) want real keystrokes.
XClick / XType / XMove / XMouseWheel uiv.desktop.click(...) / .type(...) / .move(...) Real OS input in screen pixels, via the XModule. For OS dialogs and desktop apps. Visual targets: uiv.desktop.click(uiv.findImage('ok.png', {scope: 'desktop'})).

Finding Things: DOM, Vision, OCR and AI

The modern API separates finding from acting. Every finder returns a match {x, y, rect, text, value, ...} that feeds any input tier — and every finder auto-waits. This goes beyond Selenium: images, OCR text and AI-located elements are found the same way DOM elements are.

Selenium-derived (classic) Modern uiv.* API Comment
(locator in a command's Target) uiv.$('css=#buy') — first match; uiv.$$('css=tr') — all matches Finds in all frames and open shadow roots. @POS=3 becomes an array index: uiv.$$('link=read more')[2].
visualSearch / visualAssert | button.png uiv.findImage('button.png') / uiv.findImages(...) [email protected]#2 becomes uiv.findImages('button.png', {minScore: 0.8})[1]. The finder throws if nothing appears — that IS the assert.
OCRSearch | Checkout | n uiv.ocr.findTexts('Checkout', {required: false}).length And uiv.ocr.findText(...) returns the first match to click or hover: uiv.browser.click(uiv.ocr.findText('Checkout')).
OCRExtract / OCRExtractRelative uiv.ocr.read() for the viewport, uiv.ocr.read({area: ...}) for a region "The number next to 'Total'": find the anchor with uiv.ocr.findText('Total'), then read an area next to its rect.
Relative targets: word#R120,0 and green/pink relative images uiv.offset(match, dx, dy) Compose it: uiv.browser.click(uiv.offset(uiv.ocr.findText('Email:'), 120, 0)). With an image anchor, fractions of the anchor's own rect make the offset scale-proof.
visionLimitSearchArea {area: match | rect} option on any visual finder Per-call instead of hidden state: uiv.findImage('handle.png', {area: uiv.$('css=#slider')}).
aiPrompt / aiScreenXY / aiComputerUse uiv.ai.ask(prompt, {images, json}) / uiv.ai.find('the blue Buy button') / uiv.ai.computerUse(task) uiv.ai.find returns a match like any finder: uiv.browser.click(uiv.ai.find('the search icon')).

Reading & Scraping

Selenium-derived (classic) Modern uiv.* API Comment
storeText | css=h1 | myvar const title = uiv.$('css=h1').text The match already carries the text.
storeValue | id=email | myvar uiv.$('id=email').value  
storeAttribute | id=link@href | myvar uiv.eval("return document.querySelector('#link').href") uiv.eval runs JavaScript inside the website and returns the result.
storeTitle uiv.eval('return document.title')  
storeXpathCount uiv.$$('xpath=...').length Also the clean existence test: 0 means not present, no error.
storeChecked uiv.eval("return document.querySelector('#box').checked")  
sourceSearch / sourceExtract uiv.eval('return document.documentElement.outerHTML') + a JS regex One fetch of the source, then normal String/RegExp methods.
executeScript / executeScript_Sandbox / storeEval Plain JavaScript — or uiv.eval(code) when the code must run inside the page Most executeScript_Sandbox commands simply disappear: the script IS JavaScript.
assertText / assertTitle / assertValue / assert... if (h1.text !== 'expected') throw new Error('...') An if plus throw — and the error message can include the actual value.

Data: CSV, Downloads, Screenshots

Selenium-derived (classic) Modern uiv.* API Comment
csvRead + !COL1..N + !csvReadLineNumber loop const rows = uiv.csv.read('data.csv') The whole file as a 2D array — loop with for (const row of rows). No line-number bookkeeping.
store into !csvLine + csvSave uiv.csv.append('log.csv', [timestamp, value]) A row is just an array. uiv.csv.write(...) overwrites, uiv.csv.read(...) reads back.
csvReadArray / csvSaveArray uiv.csv.read(...) / uiv.csv.write(...) Arrays are native to JavaScript.
onDownload + saveItem const file = uiv.download('css=a.installer', {as: 'setup.exe'}) Downloads, renames, waits for completion and returns the on-disk name. Also takes a plain URL, or a trigger function for JS-generated downloads.
captureScreenshot uiv.shot.viewport('name')  
captureEntirePageScreenshot uiv.shot.page('name') Whole page, scroll-stitched. Pipes into OCR: uiv.ocr.read({image: uiv.shot.page()}).
storeImage | locator | name uiv.shot.element('css=#chart', 'name')  
captureDesktopScreenshot uiv.shot.desktop('name') Needs the XModule.
localStorageExport uiv.exportToDownloads(name) Copies a .png, .csv or 'log' from Ui.Vision storage into the browser's Downloads folder.

Tabs, Windows, Waiting, Logging

Selenium-derived (classic) Modern uiv.* API Comment
selectWindow | tab=1 / tab=open / tab=close uiv.tabs.select(n) / uiv.tabs.open(url) / uiv.tabs.close() / uiv.tabs.list() Indexes are absolute (1..N, what the tab bar shows) and every call returns {index, title, url} so the script can verify where it landed. For title=... matching the classic form remains available via uiv.run.
selectFrame (not needed) Finders pierce all frames automatically.
waitForElementVisible / waitForElementPresent uiv.$(locator) — auto-waits and throws on timeout Optional elements: uiv.$(loc, {required: false, timeout: 2}) returns null instead of throwing.
waitForElementNotVisible poll: uiv.findElements(loc, {required: false, timeout: 1}).length === 0  
pause | 3000 uiv.sleep(3000) or uiv.sleep('3s') Last resort — finders auto-wait, so most pauses simply disappear in conversion.
echo | hello | green uiv.log('hello', 'green') Same colors, including '#shownotification'.
prompt | Enter value uiv.banner('Your turn: ...') + a poll loop The on-page banner asks the human without blocking the page; the script polls until the input is complete. Great for attended automation and captcha hand-offs.
comment // a JS comment  
throwError | message throw new Error('message')  
run | subMacro // @include path/to/Sub.js + a function call The include is spliced in before the script compiles; uiv.main is true only in the file that was started, so an included file's self-test does not run.

The Legacy Bridge: uiv.run()

A few rarely-used commands have no dedicated uiv.* method — by design, because they are one-liners either way. uiv.run(command, target, value) runs any classic command from inside a script: uiv.run('setProxy', ...), uiv.run('XRun', ...), uiv.run('deleteCookies'), uiv.run('bringBrowserToForeground'), uiv.run('visualGetPixelColor', '100,200', 'px'), uiv.run('selectWindow', 'title=Invoice*'). So the conversion table above is complete by construction — anything not listed rides through uiv.run unchanged.

Try It: Ask the AI to Convert Your Macro

The fastest conversion is no conversion at all: open your classic macro in Ui.Vision, open the AI sidebar and ask it to "fix" or "convert this macro to a JS script". The AI reads the table, translates every command to the uiv.* API (keeping your targeting technique — visual macros stay visual), runs the result and verifies it. Your original table macro is never touched: the JS version is saved as a new copy in the "AI Generated" folder.

If a conversion question is not answered here — or you find a Selenium-style construct that resists translation — please post it in the RPA forum. We read everything and expand this page from your feedback.

See also

The uiv.* API overview, Ui.Vision RPA docs, Selenium IDE style command reference, iMacros to Ui.Vision migration, XModules for desktop automation, AI integration docs

Anything wrong or missing on this page? Suggestions?

...then please contact us.

Fresh from the Ui.Vision Forum: The Latest 3 Topics.

← Meet the Ui.Vision team and users in our forums.