API Reference
This page is the working overview — what each call does and how it maps per platform. Full signatures, every keyword parameter, and the result objects are in the Method Reference.
Simple actions (AI-located)
Lightweight vision-based element location — fast and low-cost:
# Click on an element by description
bot.click(page, "Login button")
# Auto-wait: poll until the element looks present (up to timeout) before
# clicking, else raise QirabotTimeoutError. Works on every framework.
# `wait` overrides the auto-derived assertion. (Also on type_text/double_click.)
bot.click(page, "Login button", timeout=15.0, interval=2.0)
# Modifier-click: hold modifier key(s) around the click (desktop only)
bot.click(target, "enemy unit", modifier="alt") # alt+click (games)
bot.click(target, "file row", modifier="ctrl+shift") # join several with "+"
# Type text into an input field
bot.type_text(page, "Email input", "user@example.com")
# Extract data from the screen
text = bot.extract(page, "Get the main heading")
# Verify a visual assertion — a failed check doesn't raise, it returns a
# falsy VerifyResult (with a .reason); truthy when the check passes
ok = bot.verify(page, "The success message is visible")
# Wait for a condition (acts as a gate): returns when met, else raises
# QirabotTimeoutError. Use verify() for a non-raising bool check.
bot.wait_for(page, "Page has finished loading", timeout=15.0, interval=2.0)click, type_text, and double_click return the current target (the same kind you passed in). When an action opens a link in a new tab, the return value is that new tab — reassign it to keep operating on the active page:
page = bot.click(page, "Open the first video") # may switch to a new tabMulti-step AI — bot.ai()
result = bot.ai(page, "Search for SpaceX and summarize the first result", max_steps=10)
print(result.success, result.status, result.output)Full coverage — step callbacks, custom_tools, exclude_tools — in AI Tasks & Custom Tools; run outcomes in Error Handling.
Navigation, scrolling & keys (no AI, no billing)
Direct actions that don't need AI element location. go_back, navigate, close_tab, and press_key return the current page/target (may differ after the action); scroll returns None.
bot.navigate(page, "example.com") # scheme optional; "https://" prepended
bot.go_back(page) # back to the previous page (smart, see below)
page = bot.close_tab(page) # close current tab, return to previous tab
bot.scroll(page, "down", 3) # scroll at viewport center
bot.scroll(page, "up", distance=5, x=640, y=400) # scroll at a point
bot.press_key(page, "Enter") # a single key
bot.press_key(page, "ctrl+c") # a combo (join with "+")
bot.press_key(target, "w", duration_seconds=2) # hold for 2s (desktop only)
page = bot.press_key(page, "ctrl+w") # closes the tab, switches to another — reassign
bot.type_text(page, "", "hello", press_enter=True) # empty locate: type into the
# focused element directly (no AI, no billing)Direct typing. type_text with an empty locate skips AI location and types into whatever currently has keyboard focus — for when focus is already where you want it (a game chat box opened with Enter, a field reached via Tab). Making sure focus is right is your responsibility; press_enter / clear_before_typing still work, timeout/wait are ignored.
press_key — what you can pass. One name works on every backend; each maps it to its own vocabulary:
| Category | Examples | Notes |
|---|---|---|
| Single keys | Enter Escape Tab Backspace Delete Space | |
| Arrows / paging | ArrowUp/Down/Left/Right PageUp PageDown Home End | |
| Combos (desktop/browser) | ctrl+c ctrl+a alt+tab ctrl+shift+t | modifiers ctrl alt shift cmd (= meta/win); join with + |
| Mobile (Android/iOS) | Back Home Menu Enter | single keys only, no combos. Back/Menu are Android-only; iOS (WDA) supports Home, Enter, volume and lock keys and raises NotImplementedError for the rest |
| Hold (desktop) | duration_seconds=2 (float > 0, capped at 10) | holds the key(s) that long before releasing — quantified in-game movement (w, shift+w). pyautogui + Windows window backend only; web/mobile ignore it and tap |
So bot.press_key(t, "Enter") becomes an adb keycode on Android and a DirectInput scancode on the Windows window backend automatically.
Smart go_back (Playwright): if the current page has back history it goes back in place; if it doesn't — e.g. a click opened a link in a new tab, which starts with no history — and another tab is open, it closes the current tab and returns to the previous one:
for i in range(4):
page = bot.click(page, f"open video {i + 1}") # opens a new tab
bot.screenshot(page)
page = bot.go_back(page) # closes it, back to the listReach for close_tab to force-close the current tab regardless of history.
Platform support matrix
| Action | Playwright | Selenium | Appium (mobile) | pyautogui (desktop) | adb (Android) | WDA (iOS) | Window (Windows) |
|---|---|---|---|---|---|---|---|
click | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
double_click | ✅ | ✅ | ✅ ᵃ | ✅ | ✅ ᵃ | ✅ | ✅ |
right_click | ✅ | ✅ | = tap ᵇ | ✅ | = tap ᵇ | = tap ᵇ | ✅ |
hover | ✅ | ✅ | no-op ᶜ | ✅ | no-op ᶜ | no-op ᶜ | ✅ |
type_text | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
clear_text | ✅ | ✅ | ✅ | ✅ | ✅ ᵈ | ✅ ᵈ | ✅ |
press_key | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ ᵉ |
scroll | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
drag | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
long_press | ❌ ᶠ | ❌ ᶠ | ✅ | ❌ ᶠ | ✅ | ✅ | ❌ ᶠ |
mouse_down | ❌ ᵍ | ❌ ᵍ | ❌ ᵍ | ✅ | ❌ ᵍ | ❌ ᵍ | ✅ |
mouse_up | ❌ ᵍ | ❌ ᵍ | ❌ ᵍ | ✅ | ❌ ᵍ | ❌ ᵍ | ✅ |
key_down | ❌ ᵍ | ❌ ᵍ | ❌ ᵍ | ✅ | ❌ ᵍ | ❌ ᵍ | ✅ |
key_up | ❌ ᵍ | ❌ ᵍ | ❌ ᵍ | ✅ | ❌ ᵍ | ❌ ᵍ | ✅ |
navigate | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
go_back | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ ʰ | ❌ |
close_tab | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
screenshot | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
AI-located actions (click, type_text, double_click) and the AI operations (extract, verify, wait_for, ai) work on every framework — the matrix shows how each underlying action maps per platform.
- ᵃ Touch platforms emulate
double_clickas two quick taps. - ᵇ Mobile has no right-click: it degrades to a tap.
- ᶜ Touch targets have no hover: it's a no-op on mobile.
- ᵈ No element model over raw adb/WDA;
clear_textis best-effort (caret-to-end + repeated delete on Android, backspace burst on iOS). - ᵉ The Windows window backend sends DirectInput scancodes (real hardware-level keys, incl.
ctrl/alt/wincombos); characters outside the scancode table are injected as unicode key events.duration_seconds(hold) works on pyautogui + the Windows window backend only; elsewhere it degrades to an instant tap. - ᶠ
long_pressis a touch-only gesture (Android/iOS). Browser/desktop adapters raiseNotImplementedError. - ᵍ
mouse_down/mouse_up/key_down/key_upare desktop-only split press/release primitives (pyautogui + the Windows window backend) for holding an input across other actions. Pair each press with its release; any input still held is auto-released at the end of anai()run and onclose().mouse_up's locate is optional (omit to release at the current cursor — deterministic, no AI, no billing). Browser/mobile adapters raiseNotImplementedError. - ʰ iOS has no back button;
go_backperforms the universal left-edge swipe gesture.
navigate/go_back raise NotImplementedError where unsupported; close_tab is Playwright-only, so the new-tab fallback inside go_back applies to Playwright only — on Selenium/Appium go_back is always history-back, and on Android it maps to keyevent BACK.
Screenshot (no AI)
Saves to report_dir/screenshots/ and returns the saved path (or None when report=False):
path = bot.screenshot(page)Launch a desktop app (no AI)
pyautogui can drive the mouse and keyboard but cannot open an application. launch_app shells out to the OS so desktop runs start from a known app:
bot.launch_app("WeChat") # macOS app name (or bundle id)
# launch_app("notepad") # Windows: exe path, registered name, or UWP AppUserModelID
# launch_app("/path/to/app", wait=3) # wait seconds for the window to appear (default 2)On macOS it uses open -a/open -b (activating an already-running app), on Windows os.startfile/start/explorer.exe shell:AppsFolder, on Linux the executable directly. Also available standalone: from qirabot import launch_app.
Task lifecycle
Each Qirabot instance manages a server-side task that tracks all operations: created on construction (pass an existing task_id to attach instead), every click() / extract() / ai() recorded as a step, marked complete on close() or context-manager exit:
with Qirabot(task_name="my automation") as bot:
page = bot.open("https://example.com")
print(bot.extract(page, "Get the main heading"))
# bot.close() is called automaticallyIf close() is never called, atexit cleans up on script exit. While the process is alive, a background heartbeat keeps the server task marked live (so sleeping between steps is safe); once the process dies silently, the server's orphan cleaner times the task out after ~5 minutes.
Two more lifecycle calls when you need a terminal status other than "completed": bot.fail("what went wrong") reports the task as failed, and bot.cancel("why") reports it as cancelled — both before/instead of the success-complete that close() records by default.
See also: Configuration (constructor options, model aliases, settle delay) · Error Handling · Custom Adapters (bind(), DeviceAdapter)