looktap v0.2.1

Project

Benchmark

Measured on the same devices (iPhone 14 simulator, Pixel 9a emulator), 10 runs per action, median time. Full method, raw data and the earlier runs are in BENCHMARK.md.

ItemlooktapAppium (raw HTTP)Appium MCP
Setup before the first command0.04–0.13 s7–17 s23–39 s
Read the screen (Android · iOS)131 ms · 202 ms114 ms · 915 ms1.87 s · 1.21 s
…and its size~1 KB of text41–51 KB XML101–124 KB XML
Tap by label (Android · iOS)112 ms · 121 ms, 1 call77 ms · 1.51 s, 2 calls344 ms · 1.63 s, 2 calls
Fill a field (Android · iOS)792 ms · 782 ms1.32 s · 2.33 s513 ms · 2.51 s
Screenshot~130 ms, a ~70 B file path130 ms–1.7 s, 78–221 KB base64165–339 ms, 210–225 KB inline
Restart the app (Android · iOS)186 ms · 513 ms753 ms · 4.26 s735 ms · 4.81 s
Failed operations (of 123 per platform)2 · 0¹10 · 1012 · 10
Biometrics✓✓✗ no tool
Logs and crash reports✓via separate APIs✗

¹ Not counting hidekb on the iOS 26 search keyboard, which has no key to dismiss it: every tool fails there, and looktap is the only one that reports the failure instead of claiming success.

Raw Appium is slightly faster at reading and tapping on Android, because its helper app answers in-process. But it returns about 50× more bytes per read and needs two calls per tap.

Where Appium is still the better choice: it runs on real iOS devices, plugs into existing WebDriver test suites and CI grids, and supports many more platforms. looktap drives iOS simulators (not iPhones) and Android emulators and devices, and it isn't a test framework.

The full benchmark: looktap vs Appium vs Appium MCP: benchmark

Measured on 2026-10-15. All three tools ran the same actions on the same devices, 10 runs per feature.

TL;DR

Update, Run 4 (looktap's own helpers, no WebDriverAgent): Android ls dropped from 2.58 s to 131 ms, and iOS ls from 1.70 s to 202 ms. Taps now take 110–120 ms on both platforms, and screenshots ~130 ms. looktap is now the fastest of the three at almost every action. See Run 4. The summary below is from Run 3.

ItemlooktapAppium (raw HTTP)Appium MCP
Output returned for the whole scenario (10 runs × 13 features, bursts excluded)11 KB (Android) · 22 KB (iOS)1.9 MB · 2.6 MB2.7 MB · 3.2 MB
One screen read1–2 KB of text41–51 KB XML101–124 KB XML
One screenshot~100 B (a file path)78–221 KB base64210–225 KB base64, inline
Setup before the first command0.1–0.2 s7–17 s23–39 s
Per-action speedFastest for back, type, deep link, restart, hide keyboard. Slowest at reading the screen on Android (~2.5 s)Fastest at reading the screen and tapping on Android (it keeps a helper app running on the device)Close to raw Appium, plus MCP overhead
Failed operations (out of 123 per platform)2 · 210 · 1012 · 10
Biometrics✓✓✗ no tool

In one line:


What was compared

ToolHow it was drivenWhat it represents
looktap 0.1.0The CLI, spawned once per command: node bin/looktap.js …A person or agent typing commands
Appium (raw HTTP)Appium 3.6.0 server with xcuitest 12.3.4 / uiautomator2 8.4.0, called over W3C HTTP from Node with one persistent sessionAppium's own speed, with no agent layer on top
Appium MCPappium-mcp@latest, configured as an agent would use it, started over stdio and driven with MCP tools/callWhat an agent's tool calls actually cost

Devices:

App: the system Settings app. It has no sign-in and no real money is involved. The deep-link step opens a custom-scheme deep link in a second installed app, at whatever screen it is on, without typing anything.

iOS WebDriverAgent:

Scenario: one run

Every run started from a tool-neutral reset: a plain simctl/adb command to force-stop the apps and relaunch Settings at its root screen. The reset was not timed.

#FeatureWhat it does
1ls: read screenlooktap ls · Appium GET /source · MCP appium_get_page_source
2tap: by labelTap "General" (iOS) / "Network & internet" (Android). For Appium and MCP this is find-element + click (2 calls)
3backReturn to the previous screen
4tapxyTap the same row by coordinates (then back, untimed)
5swipeScroll the list (then scroll back, untimed)
6fillPut "wifi" in Settings search. On Android, search is opened first by a neutral adb tap
7typeType " x" into the focused field
8hidekbDismiss the keyboard
9shotScreenshot
10bioFace ID match / fingerprint 1, while Settings is in front
11openDeep link into a second installed app
12launchRestart Settings (terminate + launch)

After the 10 runs, each tool did:

What was measured


Run 4: looktap with its own native helpers

Measured on 2026-10-15, with the same devices, harness and scenario (10 runs). looktap no longer uses WebDriverAgent or uiautomator dump:

Only looktap was re-run. The Appium columns are Run 3's numbers, from the same devices and harness.

Android (Pixel 9a emulator)

Featurelooktap Run 3looktap Run 4Appium raw (Run 3)Appium MCP (Run 3)
ls (read screen)2.58 s131 ms · 975 B114 ms · 51 KB1.87 s · 124 KB
tap (by label)2.21 s · ⚠ 2/10112 ms · ⚠ 1/1077 ms · 2 calls · ⚠ 2/10344 ms · 2 calls
back84 ms84 ms610 ms88 ms
tapxy111 ms123 ms43 ms101 ms
swipe (300 ms gesture)418 ms398 ms433 ms543 ms
fill5.01 s792 ms · ⚠ 1/101.32 s · 3 calls · ⚠ 4/10513 ms · 2 calls · ⚠ 6/10
type252 ms132 ms905 ms · ⚠ 4/10917 ms · ⚠ 6/10
hidekb131 ms48 ms812 ms214 ms
shot539 ms138 ms · 69 B1.72 s · 78 KB339 ms · 210 KB
launch199 ms186 ms753 ms735 ms

iOS (iPhone 14 simulator)

Featurelooktap Run 3 (WDA)looktap Run 4Appium raw (Run 3)Appium MCP (Run 3)
setup193 ms39 ms17.37 s23.14 s
ls (read screen)1.70 s202 ms · 723 B915 ms · 41 KB1.21 s · 101 KB
tap (by label)1.84 s · ⚠ 1/10121 ms1.51 s · 2 calls1.63 s · 2 calls
back1.09 s · ⚠ 1/10187 ms1.15 s1.18 s
tapxy1.40 s112 ms1.05 s1.14 s
swipe2.10 s235 ms1.56 s1.96 s
fill3.69 s782 ms2.33 s · 3 calls2.51 s · 2 calls
type504 ms60 ms603 ms · 2 calls577 ms · 2 calls
hidekb (search keyboard)✗ false success✗ 10/10, reported correctly✗ 10/10✗ 10/10
shot411 ms124 ms · 65 B130 ms · 221 KB165 ms · 225 KB
launch570 ms513 ms4.26 s4.81 s

What changed:

Limits:

The Run 3 report follows unchanged, for reference.


Results: Android (Pixel 9a emulator)

FeaturelooktapAppium (raw HTTP)Appium MCP
setup130 ms · 78 B7.31 s · 927 B38.83 s · 6 KB · 2 calls
ls (read screen)2.58 s · 1014 B114 ms · 51 KB1.87 s · 124 KB
tap (by label)2.21 s · 39 B · ⚠ 2/10 failed77 ms · 151 B · 2 calls · ⚠ 2/10 failed344 ms · 421 B · 2 calls
back84 ms · 0 B610 ms · 14 B88 ms · 109 B
tapxy111 ms · 0 B43 ms · 14 B101 ms · 120 B
swipe418 ms · 0 B433 ms · 14 B543 ms · 139 B
fill5.01 s · 0 B1.32 s · 165 B · 3 calls · ⚠ 4/10 failed513 ms · 404 B · 2 calls · ⚠ 6/10 failed
type252 ms · 0 B905 ms · 151 B · 2 calls · ⚠ 4/10 failed917 ms · 363 B · 2 calls · ⚠ 6/10 failed
hidekb131 ms · 0 B812 ms · 14 B214 ms · 106 B
shot (screenshot)539 ms · 96 B1.72 s · 78 KB339 ms · 210 KB
bio67 ms · 0 B32 ms · 14 B— no tool
open (deep link)89 ms · 0 B5.03 s · 14 B2.16 s · 153 B
launch (restart app)199 ms · 0 B753 ms · 28 B · 2 calls735 ms · 220 B · 2 calls
burst 5 s4 frames · 121 B23 frames · 1.7 MB11 frames · 923 KB
teardown76 ms · 26 B466 ms · 14 B751 ms · 111 B

Results: iOS (iPhone 14 simulator)

FeaturelooktapAppium (raw HTTP)Appium MCP
setup193 ms · 40 B17.37 s · 578 B23.14 s · 7 KB · 3 calls
ls (read screen)1.70 s · 2 KB915 ms · 41 KB1.21 s · 101 KB
tap (by label)1.84 s · 17 B · ⚠ 1/10 failed1.51 s · 151 B · 2 calls1.63 s · 379 B · 2 calls
back1.09 s · 0 B · ⚠ 1/10 failed1.15 s · 14 B1.18 s · 109 B
tapxy1.40 s · 0 B1.05 s · 14 B1.14 s · 120 B
swipe2.10 s · 0 B1.56 s · 14 B1.96 s · 139 B
fill3.69 s · 0 B2.33 s · 165 B · 3 calls2.51 s · 437 B · 2 calls
type504 ms · 0 B603 ms · 151 B · 2 calls577 ms · 362 B · 2 calls
hidekb✗ 3.92 s, reported success but the keyboard stayed up (bug, see below)✗ failed 10/10✗ failed 10/10
shot (screenshot)411 ms · 92 B130 ms · 221 KB165 ms · 225 KB
bio558 ms · 0 B429 ms · 14 B— no tool
open (deep link)533 ms · 0 B210 ms · 14 B324 ms · 158 B
launch (restart app)570 ms · 0 B4.26 s · 28 B · 2 calls4.81 s · 222 B · 2 calls
burst 5 s9 frames · 117 B59 frames · 25.5 MB59 frames · 25.9 MB
teardown488 ms · 23 B154 ms · 14 B37 ms · 111 B

iOS times are higher across the board for all three tools. WebDriverAgent waits for the UI to go idle (animations finished) before it completes a tap or swipe.


What the numbers mean

For AI agents: output size dominates

An agent pays for every byte a tool returns, as context and tokens, and for every extra call, as a turn.

For raw speed: Appium's on-device helper wins at reading Android screens

On Android, looktap's ls, tap and fill take 2–5 s, because each calls uiautomator dump. That starts a fresh UiAutomation connection and waits for the UI to go idle, about 2 s every time. Appium installs a helper app that stays connected, so its screen reads take about 0.1 s.

Where no screen read is involved, looktap matches or beats both:

On iOS, all three tools go through WebDriverAgent, so action times are close. looktap adds around 0.3–0.5 s per command for starting Node and checking which device is booted.

Burst (screenshots in 5 s)

Appium and MCP take more frames per second (23–59 vs 4–9). But every frame comes back over the wire as base64: 25 MB on iOS in 5 seconds. looktap writes frames to disk and de-duplicates them, so it reports only how many frames are distinct.

Reliability

Across both platforms:

Most Appium and MCP failures were in fill/type on Android. They happened right after the app switched to Settings search, which runs in a different Android package (com.google.android.settings.intelligence): UiAutomator2 keeps reporting the previous window for about 2–3 s. A 4 s settle reduced these failures but didn't remove them. The few looktap failures were the first run after setup on iOS, and the screen not yet ready on Android.


Bugs found in looktap

#BugImpactStatus
1hidekb on iOS reported success when the keyboard stayed up. The iOS 26 search keyboard has no Done/Return key, WDA's dismiss failed, and looktap swallowed the errorSilent false success. Appium and MCP correctly reported failure✅ fixed: checks the keyboard afterwards and exits 2 if it's still up (verified in Run 4)
2tap fell back to "first label containing the text", so with the wrong screen up it could tap a different element and report successWrong element tapped silently✅ fixed: exact first, a fuzzy match only when it names one label, --exact, and tap prints what it hit
3No waiting: tap/back right after a navigation failed when the screen wasn't ready yetSpurious "not found"✅ fixed: --wait (default 3 s)
4Android fill dumped the screen twicefill took ~5 s instead of ~2.5 s✅ fixed, and with the helper fill takes ~0.8 s
5Fixed per-command overhead: every command re-lists all devices, even with -p and -d given+0.1–0.3 s on every command✅ fixed
6Android screen reads took about 2.5 s (uiautomator dump)Slow ls/tap/fill on Android✅ fixed in Run 4: a persistent helper run with app_process (nothing installed). Reads take ~130 ms

Benchmark history

These problems were found in the harness, not in the tools, and are kept here so the method can be trusted:

  1. Run 1 (discarded): the "reset" between runs force-stopped Settings but not its search screen, which lives in a separate package. Most runs started on the wrong screen. Fixed by stopping both packages and relaunching with a cleared task.
  2. Run 2 (discarded): a 1.5 s settle after opening Settings search was too short for UiAutomator2 (see Reliability above). Raised to 4 s for all tools.
  3. Run 3: looktap 0.1.0 with WebDriverAgent and uiautomator dump.
  4. Run 4: looktap with its own helpers. Only looktap was re-run (see above).

Reproduce

# 1. devices: boot exactly one simulator and one emulator
# 2. an Appium 3 server with both drivers:
npx appium driver install xcuitest && npx appium driver install uiautomator2
npx appium --port 4723 &
# 3. optional: an installed app with a deep link, for the deep-link step
export BENCH_DEEPLINK=myapp://home BENCH_DEEPLINK_APP=com.example.myapp
# 4. run (each platform takes ~20 min for all three tools, 10 runs each)
cd bench
node full.mjs android 10            # or: node full.mjs ios 10
node full.mjs ios 3 looktap        # one tool, fewer runs
python3 mdtable.py results/ios.json # → the markdown table above

Raw per-run numbers are in bench/results/android.json and bench/results/ios.json (Run 3), and in android-run4-looktap.json and ios-run4-looktap.json (Run 4). Set BENCH_TAG to keep a run's results separate. For Appium on iOS, BENCH_PREBUILT_WDA points at a built WebDriverAgentRunner-Runner.app so Appium skips its xcodebuild.

Generated from README.md and BENCHMARK.md. Edit it there.