Hoppa till huvudinnehåll

Custom Scripts

The built-in scripts cover the common flows. When you need something they do not — a step in a different order, a screen they never touch, or an app that is not TikTok or Instagram — you can write it yourself in any language and let TikMatrix hand you the phone.

Requirements

License Requirement

Custom scripts require a Pro, Team, or Business plan. Starter plan does not have access.

Your plan's device count is also the concurrency limit: a Pro plan (20 devices) can drive 20 phones at once, whether through built-in tasks, custom scripts, or a mix of both.

Two ways to run a script

Standalone

You run your program yourself. TikMatrix just lends you devices.

from tikmatrix import TikMatrix

client = TikMatrix()

for device in client.devices():
if device["busy"]:
continue
with client.device(device["serial"], label="my crawler") as d:
d.press("home")
print(d.info())

Good for one-off jobs, data collection, and anything you want to run from your own scheduler.

Managed

You register the program in TikMatrix and it becomes a task like any other. It gets the task queue, per-plan concurrency, automatic retries, the task log, and schedule templates. TikMatrix leases the device before starting your program and passes the lease id in its environment.

from tikmatrix import TikMatrix

with TikMatrix.from_env() as d: # device already leased
d.click(text="Log in")
print("done") # this line lands in the task log

Good for anything you want to run repeatedly, on a schedule, or across many devices.

Getting started

1. Install the client library

pip install requests

Then copy tikmatrix.py from the SDK directory next to your script. The library is a single file with no other dependencies.

You do not have to use it — the API is plain JSON over HTTP, and the raw endpoints are documented below.

2. Write your script

from tikmatrix import TikMatrix

client = TikMatrix()
with client.device("192.168.1.5:5555") as d:
d.press("home")
d.adb("shell", "am", "start", "-a", "android.settings.SETTINGS")
d.wait_for(text="Settings", timeout=15)
d.screenshot("settings.png")

3. Register it (managed mode only)

Go to Devices → Custom Scripts → Add Script:

FieldMeaning
NameShown in the script list and the task log
CommandThe program line to run, e.g. python C:/scripts/my_flow.py
Working directoryOptional. Where the program starts
PlatformSee platform modes below
TimeoutSeconds before the script is killed and the task marked failed. Default 1800
Extra environment variablesOptional JSON object merged into the program's environment

Then press ▶ on the script row and pick your devices, exactly like a built-in script.

Device leases

A phone can only be driven by one thing at a time. Leasing it tells TikMatrix the device is busy, so:

  • the task queue will not dispatch a task onto the same screen, and
  • your JSON-RPC calls report agent health exactly as a built-in script does, so the watchdog sees a busy agent rather than a silent one.

A lease also consumes one device slot from your plan.

Leases expire — 120 seconds by default, 600 maximum. The Python library renews yours on a background thread and releases it when the with block ends, so a crashed script frees its device within seconds instead of holding it until you restart the app. If you are calling the API directly, you must send heartbeats yourself.

You can see every live lease, and force-release one, under Settings → Developer API → Active device sessions.

Platform modes

A registered script declares what it targets:

Generic — the device is handed over untouched. No app is started, no account switching, no input-method check, and nothing is closed afterwards. Use this to automate anything that is not TikTok or Instagram.

TikTok / Instagram — the app is opened and the account switched before your program starts, and the app is closed when it finishes, exactly as for a built-in script. TIKMATRIX_PACKAGE tells you which package was resolved. Use this to add a step the built-in scripts do not cover.

Environment variables

A managed script receives:

VariableMeaning
TIKMATRIX_API_BASEServer URL, e.g. http://127.0.0.1:50809
TIKMATRIX_SESSION_IDThe lease already held on your behalf
TIKMATRIX_SERIALThe device this task was dispatched to
TIKMATRIX_PACKAGEResolved app package
TIKMATRIX_PLATFORMtiktok, instagram, or generic

TikMatrix.from_env() reads all of these for you.

Standalone scripts get none of them — lease a device explicitly instead.

Common operations

d.info() # device info
d.window_size() # (width, height)
d.screenshot("shot.png") # PNG bytes, optionally saved

d.find(text="Following") # matching nodes with bounds + center
d.exists(resource_id="com.app:id/login")
d.wait_for(text="Home", timeout=15) # block until it appears
d.click(text="Log in") # wait, then tap the centre

d.click_xy(540, 1200)
d.swipe(540, 1600, 540, 600)
d.press("back") # back / home / recent / enter
d.input_text("hello") # types via the bundled input method

d.jsonrpc("deviceInfo") # any UIAutomator2 method
d.adb("shell", "pm", "list", "packages") # ADB, once enabled in Settings

find matches against the dumped UI tree, so when a selector misses you can print(d.hierarchy()) and look at exactly what it searched. The Element Inspector in the device view shows the same tree visually, which is usually the fastest way to find a resource-id.

HTTP endpoints

Device operations need an x-session-id header naming a live lease. There is no API key: like the rest of the local API, these endpoints are unauthenticated — reaching the machine on the network is the access control. They send no CORS headers, so call them from a program (curl, Python, anything server-side) rather than from a page in a browser.

MethodPathPurpose
GET/api/v1/rpc/devicesList online devices and whether each is busy
POST/api/v1/rpc/sessionLease a device → session_id
POST/api/v1/rpc/session/{id}/heartbeatExtend the lease
DELETE/api/v1/rpc/session/{id}Release the lease
GET/api/v1/rpc/sessionList live leases
POST/api/v1/rpc/jsonrpcCall a UIAutomator2 method
POST/api/v1/rpc/adbRun an ADB command
GET/api/v1/rpc/hierarchy?serial=Current UI tree as XML
GET/api/v1/rpc/screenshot?serial=Current screen as PNG

Example

# Lease a device
curl -X POST http://127.0.0.1:50809/api/v1/rpc/session \
-H "Content-Type: application/json" \
-d '{"serial":"192.168.1.5:5555","label":"curl test","ttl_secs":120}'

# {"code":0,"message":"success","data":{"session_id":"ff3ae079-...","serial":"192.168.1.5:5555", ...}}

# Drive it
curl -X POST http://127.0.0.1:50809/api/v1/rpc/jsonrpc \
-H "x-session-id: ff3ae079-..." \
-H "Content-Type: application/json" \
-d '{"serial":"192.168.1.5:5555","method":"deviceInfo","params":[]}'

# Give it back
curl -X DELETE http://127.0.0.1:50809/api/v1/rpc/session/ff3ae079-...

Errors

StatusMeaning
403Plan below Pro, no lease, lease expired, or ADB access disabled
409Device already leased, or your plan has no free device slot

Triggering a custom script from the API

Registered scripts can also be started through the Task Management API, so one script can queue follow-up work:

curl -X POST http://127.0.0.1:50809/api/v1/task \
-H "Content-Type: application/json" \
-d '{
"serials": ["192.168.1.5:5555"],
"script_name": "custom_script",
"script_config": {
"custom_script_id": 1,
"custom_script_platform": "generic"
}
}'

custom_script_id is the id of the script you registered.

ADB access

/api/v1/rpc/adb gives your scripts a device shell — you need it for pushing media, installing APKs, and changing system settings. Because it is a full shell on an endpoint that has no API key, it ships turned off. Enable it under Settings → Developer API → Allow ADB commands when you have a script that needs it; UI automation over /rpc/jsonrpc works without it.

While it is off, /api/v1/rpc/adb answers 403 and the rest of the API keeps working. Every ADB command a script runs is written to your log file.

Notes and limits

  • The command is executed directly, not through a shell, so && and | are treated as arguments rather than operators. Register cmd /c "..." (Windows) or sh -c "..." (macOS) if you want shell behaviour.
  • Quote paths that contain spaces: "C:/Program Files/Python/python.exe" my_script.py.
  • A script that exceeds its timeout is terminated and the task is marked failed.
  • A non-zero exit code marks the task failed; everything the script writes to stdout and stderr lands in the task log.
  • Scripts run with the same permissions as TikMatrix itself. Only register programs you wrote or trust.

Next steps