Features Documentation Examples Install Compatibility
Releases Discord
open source · rootless Sileo repo available Dopamine · Roothide · iOS 15–16.6.1

Touch anything. Automate everything.

ZXTouch Rootless is an open-source framework that simulates touch events at the system level — no per-app injection. Script it from any language over a socket, replay recorded gestures, match images, and read the screen with OCR. Now fully ported to rootless & roothide jailbreaks.

19-finger multitouch <1ms latency any language
SCRIPT RUNNING · :6000
TOUCH_MOVE (400, 512)
latency <1 ms · 5/19
image_match() ✓ 0.98
0

simultaneous fingers — true system multitouch

<0ms

event latency — fast enough for live remote

0

socket port — drive it from any language

0

apps injected — zero per-app hooks

Capabilities

Everything you need to automate iOS.

One tweak, one socket, a full automation toolkit. Every capability works across the entire OS — home screen, any app, any game.

True system-wide multitouch

Drive up to 19 simultaneous fingers with independent down / move / up phases. Pinch, rotate, drag and complex game gestures are first-class — batch them in a single frame with touch_with_list().

multitouch.py
device.touch(TOUCH_DOWN, 5, 400, 400)
device.touch(TOUCH_MOVE, 5, 400, 600)
device.touch(TOUCH_UP,   5, 400, 600)

Any language

A clean socket protocol on port 6000, plus a batteries-included Python module. If it can open a TCP socket, it can automate the device.

Record & playback

Capture real touch sessions and replay them perfectly — from the floating panel, the API, or iOS Shortcuts.

Image matching

Template-match on the live screen, Accelerate-framework fast. Find a button, tap it — no fragile coordinates.

On-device OCR

Read text straight off the screen — multi-language, accurate or fast modes. No cloud, nothing leaves the device.

Shortcuts integration

Trigger recorded scripts from iOS Shortcuts & automations — on a schedule, an NFC tag, or a tap.

Root shell

Run commands as root from your scripts with run_shell_command() and glue device state into automation.

Floating control panel — no computer needed

Double-click volume-down anywhere in iOS to summon an on-screen panel: run saved scripts, start/stop recording, and manage settings on the go.

Low-latency remote

Control the device live over the network — fast enough for real-time mirrored input from a computer.

Color picker & system UI

Read RGB at any pixel, fire native alert boxes & toasts, type into fields and move the cursor — all from a script.

Documentation

From zero to automated in minutes.

A complete reference for the Python client, the touch model, computer vision, and the on-device tools.

Quick start

Install the tweak (see Installation), make sure python3 from the Procursus repo is present, then connect to the daemon on port 6000. The zxtouch Python module ships with the tweak.

quickstart.py
from zxtouch.client import zxtouch
from zxtouch.touchtypes import *
import time

device = zxtouch("127.0.0.1")   # on-device, or your iPhone IP for remote

# a one-finger swipe down: down → move → up
device.touch(TOUCH_DOWN, 5, 400, 400)
time.sleep(0.4)
device.touch(TOUCH_MOVE, 5, 400, 600)
device.touch(TOUCH_UP,   5, 400, 600)

device.disconnect()

Connecting

The tweak runs a daemon listening on port 6000. Construct a client with the target IP — "127.0.0.1" when your script runs on the device itself, or the iPhone's LAN IP to drive it remotely from a computer.

  • Every call returns a standard tuple (success: bool, data_or_error) — check the first element before trusting the second.
  • Coordinates are in screen points; use get_screen_size() / get_screen_scale() to write resolution-independent scripts.
  • Call device.disconnect() when done to close the socket cleanly.

Touch model

Each touch carries a type (TOUCH_DOWN / TOUCH_MOVE / TOUCH_UP), a finger index from 1–19, and x, y coordinates. A gesture is a down, any number of moves, then an up on the same finger. For multi-finger gestures, dispatch several events in one frame with touch_with_list().

pinch.py — two fingers, pinch-to-zoom
device.touch_with_list([
    {"type": TOUCH_DOWN, "finger_index": 1, "x": 350, "y": 600},
    {"type": TOUCH_DOWN, "finger_index": 2, "x": 450, "y": 700},
])
for i in range(20):
    device.touch_with_list([
        {"type": TOUCH_MOVE, "finger_index": 1, "x": 350-i*8, "y": 600-i*8},
        {"type": TOUCH_MOVE, "finger_index": 2, "x": 450+i*8, "y": 700+i*8},
    ])
    device.accurate_usleep(16000)  # ≈ one 60fps frame, precise

Vision & OCR

Stop hardcoding coordinates. image_match() locates a template on the live screen and returns its bounding box; ocr() reads on-screen text so scripts react to real state. pick_color() samples a pixel's RGB.

find_and_tap.py
ok, m = device.image_match("/var/mobile/button.png",
                        acceptable_value=0.8, max_try_times=4)
if ok and float(m["width"]) > 0:        # width==0 means no match
    x = float(m["x"]) + float(m["width"])  / 2
    y = float(m["y"]) + float(m["height"]) / 2
    device.touch(TOUCH_DOWN, 1, x, y)
    device.touch(TOUCH_UP, 1, x, y)

# read a score region (x, y, w, h), accurate mode
ok, lines = device.ocr((40, 120, 300, 60), recognition_level=0)
print(lines)   # → ["Score: 1240"]

Text & system UI

Type into the focused field, nudge the cursor, switch apps, and surface native feedback — alert boxes and four styles of toast.

type_and_notify.py
from zxtouch.toasttypes import *

device.switch_to_app("com.apple.MobileSMS")
device.insert_text("sent by zxtouch")
device.insert_text("\b\b")              # backspace x2
device.move_cursor(-3)               # move left 3
device.show_toast(TOAST_SUCCESS, "Done!", 1.5)
device.show_alert_box("ZXTouch", "Message ready", 3)

Recording & the floating panel

Double-click volume-down anywhere in iOS to open the ZXTouch panel — run saved scripts, start/stop recording, and adjust settings without a computer. Recordings save as replayable ZXTouch scripts.

Programmatically, start_touch_recording() begins capture (double-click volume-down or call stop_touch_recording() to end), and play_script(path) replays one. Use force_stop_script_play() to abort.

Full API reference

zxtouch.client
Method & parametersDescription & returns
touch(type, finger_index, x, y)type = TOUCH_DOWN/MOVE/UP · finger_index 1–19 · x,y screen points. Fires one touch event. Returns None.
touch_with_list(touch_list)List of dicts {"type","finger_index","x","y"} dispatched in a single frame — the basis for multi-finger gestures. Returns None.
image_match(template_path, acceptable_value=0.8, max_try_times=4, scaleRatio=0.8)Template-match an image on the live screen. Returns (bool, dict) with x, y, width, height; width/height == 0 means no match.
ocr(region, custom_words=[], minimum_height="", recognition_level=0, languages=[], auto_correct=0, debug_image_path="")region = (x, y, w, h) · recognition_level 0 = accurate, 1 = fast. Returns (bool, [str, …]) of recognized lines.
get_supported_ocr_languages(recognition_level)List OCR language codes available for a recognition level. Returns (bool, [str, …]).
pick_color(x, y)Sample the pixel at x, y. Returns (bool, dict) with red, green, blue.
insert_text(text)Type into the focused field. Use "\b" per character to delete. Returns (bool, err).
move_cursor(offset)Move the text cursor — negative = left, positive = right. Returns (bool, err).
show_keyboard() / hide_keyboard()Force the software keyboard to show or hide. Returns (bool, err).
show_alert_box(title, content, duration)Display a native alert box for duration seconds. Returns (bool, err).
show_toast(toast_type, content, duration, position=0, fontSize=0)toast_type = TOAST_SUCCESS/ERROR/WARNING/MESSAGE. Returns (bool, err).
switch_to_app(bundle_identifier)Bring any installed app to the foreground by bundle id. Returns (bool, err).
play_script(script_absolute_path)Run a recorded or written ZXTouch script. Returns (bool, err).
force_stop_script_play()Abort the currently playing script. Returns (bool, err).
start_touch_recording() / stop_touch_recording()Begin / end capturing real touches into a replayable script. Returns (bool, err).
run_shell_command(command)Execute a shell command as root and capture output. Returns (bool, err).
accurate_usleep(microseconds)High-precision sleep — steadier frame pacing than time.sleep. Returns (bool, err).
get_screen_size()Returns (bool, dict) with width, height in points.
get_screen_scale()Returns (bool, scale) — the display's pixel scale factor.
get_screen_orientation()Returns (bool, orientation) as an integer code.
get_device_info()Returns (bool, dict): name, system_name, system_version, model, identifier_for_vendor.
get_battery_info()Returns (bool, dict): battery_state, battery_level, battery_state_string.
disconnect()Close the socket connection to the daemon. Call when finished.

Constants

from zxtouch.touchtypes import *

  • TOUCH_DOWN — finger lands
  • TOUCH_MOVE — finger drags
  • TOUCH_UP — finger lifts

from zxtouch.toasttypes import *

  • TOAST_SUCCESS · TOAST_ERROR
  • TOAST_WARNING · TOAST_MESSAGE
  • TOAST_BUTTOM — default position (0)
Examples

Copy, paste, automate.

auto_tapper.py — tap a spot every second
from zxtouch.client import zxtouch
from zxtouch.touchtypes import *
import time

device = zxtouch("127.0.0.1")
try:
    while True:
        device.touch(TOUCH_DOWN, 1, 390, 844)
        device.touch(TOUCH_UP, 1, 390, 844)
        time.sleep(1)
finally:
    device.disconnect()
watcher.py — wait for a button, then tap it
from zxtouch.client import zxtouch
from zxtouch.touchtypes import *
import time

device = zxtouch("127.0.0.1")
while True:
    ok, m = device.image_match("/var/mobile/claim.png")
    if ok and float(m["width"]) > 0:
        x = float(m["x"]) + float(m["width"])/2
        y = float(m["y"]) + float(m["height"])/2
        device.touch(TOUCH_DOWN, 1, x, y)
        device.touch(TOUCH_UP, 1, x, y)
        break
    time.sleep(0.5)
app_pilot.py — launch an app & type
from zxtouch.client import zxtouch
from zxtouch.toasttypes import *
import time

device = zxtouch("127.0.0.1")
device.switch_to_app("com.apple.MobileSMS")
time.sleep(2)
device.insert_text("sent by zxtouch")
device.show_toast(TOAST_SUCCESS, "Typed!", 1.5)
device.disconnect()
battery_guard.py — pause when low
from zxtouch.client import zxtouch

device = zxtouch("127.0.0.1")
ok, bat = device.get_battery_info()
if ok and float(bat["battery_level"]) < 0.2:
    device.show_alert_box("ZXTouch",
        "Battery under 20% — pausing.", 3)
else:
    device.play_script("/var/mobile/farm.zxs")
Installation

Two minutes to first touch.

Install from the Sileo repo (recommended) or grab a .deb from GitHub Releases. The repo ships both rootless and roothide builds.

https://epic0001.github.io/zxtouchrootless/

Add the repo in Sileo

Tap Add to Sileo above, or in Sileo go to Sources → + and add https://epic0001.github.io/zxtouchrootless/. Alternatively, download _rootless.deb from Releases.

Install & respring

In Sileo, install ZXTouch (rootless build), or over SSH / NewTerm:

terminal
$ dpkg -i zxtouch_*_rootless.deb
$ killall -9 SpringBoard

Install Python 3

Add the Procursus repo and install python3 — required to run scripts on-device.

Verify

Double-click volume-down — the floating panel appears. The daemon is now listening on 127.0.0.1:6000.

Compatibility

Tested where it matters.

JailbreakiOS versionsPackageStatus
Dopamine (rootless)16.4.1 · 16.6.1*_rootless.deb✓ TESTED
Roothide / Serotonin15.8 · 16.6.1*_roothide.deb✓ TESTED
Legacy (original ZXTouch)11.0 – 14.xupstream repoUPSTREAM

Other rootless setups on iOS 15–16.6.1 will likely work — reports welcome on GitHub or Discord.

Community

Build something unstoppable.

Join the community shaping iOS automation — share scripts, report device compatibility, and help bring ZXTouch to new jailbreaks.