Command reference
Every Droidline command with its parameters, return value, errors and the same call in Python, Node.js, the CLI and HTTP.
Each entry shows what the command does, its parameters, what it returns and which errors it can raise, then the same call in every interface. Pick a language in any example and the whole page follows. The Python examples assume d = connect() (dl = Droidline() for server commands), and the Node.js examples assume const d = await connect() (const dl = new Droidline()).
Screen
dump
Return the current screen as a node tree
| Name | Type | Default | Meaning |
|---|---|---|---|
path | string | Save the tree as JSON to this local file | |
all_windows | bool | false | Include system windows such as the status bar and keyboard |
Returns: an object with package, activity, width, height, tree
d.dump("screen.json") # saved on your PCawait d.dump("screen.json"); // saved on your PCdroidline dump screen.jsoncurl -s -X POST localhost:8780/devices/_/dump \
-H 'content-type: application/json' > screen.json{"id":1,"cmd":"dump"}screenshot
Capture the screen
Android 11+ uses the accessibility screenshot. Android 9-10 asks once for screen capture permission.
| Name | Type | Default | Meaning |
|---|---|---|---|
path | string | Save the image to this local file. The extension picks png or jpeg | |
format | string png | jpeg | "jpeg" | Image format |
quality | int | 80 | JPEG quality 1-100 |
scale | number | 1 | Resize factor 0.1-1.0, useful on mobile data |
Returns: an object with format, width, height, data
d.screenshot("shot.png") # saved on your PCawait d.screenshot("shot.png"); // saved on your PCdroidline screenshot shot.pngcurl -s localhost:8780/devices/_/screenshot.png -o shot.png{"id":1,"cmd":"screenshot"}current
Foreground package and activity
Returns: an object with package, activity
d.current()await d.current();droidline currentcurl -s -X POST localhost:8780/devices/_/current \
-H 'content-type: application/json'{"id":1,"cmd":"current"}Coordinates
tap
Tap a screen coordinate
| Name | Type | Default | Meaning |
|---|---|---|---|
x | int | required | X in screen pixels |
y | int | required | Y in screen pixels |
Returns: an object with ms
d.tap(540, 1200)await d.tap(540, 1200);droidline tap 540 1200curl -s -X POST localhost:8780/devices/_/tap \
-H 'content-type: application/json' \
-d '{"x":540,"y":1200}'{"id":1,"cmd":"tap","x":540,"y":1200}long_tap
Press and hold a coordinate
| Name | Type | Default | Meaning |
|---|---|---|---|
x | int | required | X in screen pixels |
y | int | required | Y in screen pixels |
ms | int | 800 | Hold time in milliseconds |
Returns: an object with ms
d.long_tap(540, 1200, 800)await d.longTap(540, 1200, 800);droidline long_tap 540 1200 800curl -s -X POST localhost:8780/devices/_/long_tap \
-H 'content-type: application/json' \
-d '{"x":540,"y":1200,"ms":800}'{"id":1,"cmd":"long_tap","x":540,"y":1200,"ms":800}swipe
Swipe between two points, or in a direction
| Name | Type | Default | Meaning |
|---|---|---|---|
x1 | int|string | required | Start X, or a direction: up, down, left, right |
y1 | int | Start Y | |
x2 | int | End X | |
y2 | int | End Y | |
ms | int | 300 | Duration in milliseconds |
Returns: an object with ms
d.swipe(540, 1600, 540, 400, 300)await d.swipe(540, 1600, 540, 400, 300);droidline swipe 540 1600 540 400 300curl -s -X POST localhost:8780/devices/_/swipe \
-H 'content-type: application/json' \
-d '{"x1":540,"y1":1600,"x2":540,"y2":400,"ms":300}'{"id":1,"cmd":"swipe","x1":540,"y1":1600,"x2":540,"y2":400,"ms":300}Elements
touch
Wait for an element and tap it
If the node refuses the click, the center of its bounds is tapped instead. via tells which path worked: node, parent or gesture.
| Name | Type | Default | Meaning |
|---|---|---|---|
by | selector | required | Which dump field to match: text, textContains, id, desc, descContains, class |
value | string | required | The value to match |
nth | int | 0 | Index when several elements match, starting at 0 |
timeout | number | 10 s | Seconds to wait for the target to appear |
Returns: an object with via, ms
Shorthand: touchById(value), touchByText(value), touchByDesc(value)
Errors: NOT_FOUND, NOT_CLICKABLE, NO_ACCESSIBILITY
d.touch("text", "Log in")await d.touch("text", "Log in");droidline touch text "Log in"curl -s -X POST localhost:8780/devices/_/touch \
-H 'content-type: application/json' \
-d '{"by":"text","value":"Log in"}'{"id":1,"cmd":"touch","by":"text","value":"Log in"}long_touch
Wait for an element and press and hold it
| Name | Type | Default | Meaning |
|---|---|---|---|
by | selector | required | Which dump field to match: text, textContains, id, desc, descContains, class |
value | string | required | The value to match |
ms | int | 800 | Hold time in milliseconds |
nth | int | 0 | Index when several elements match, starting at 0 |
timeout | number | 10 s | Seconds to wait for the target to appear |
Returns: an object with via, ms
d.long_touch("text", "Message")await d.longTouch("text", "Message");droidline long_touch text Messagecurl -s -X POST localhost:8780/devices/_/long_touch \
-H 'content-type: application/json' \
-d '{"by":"text","value":"Message"}'{"id":1,"cmd":"long_touch","by":"text","value":"Message"}scroll_to
Scroll until an element is visible
| Name | Type | Default | Meaning |
|---|---|---|---|
by | selector | required | Which dump field to match: text, textContains, id, desc, descContains, class |
value | string | required | The value to match |
direction | string down | up | left | right | "down" | Direction the content moves toward |
max_swipes | int | 20 | Give up after this many swipes |
nth | int | 0 | Index when several elements match, starting at 0 |
Returns: an object with swipes
d.scroll_to("text", "Settings")await d.scrollTo("text", "Settings");droidline scroll_to text Settingscurl -s -X POST localhost:8780/devices/_/scroll_to \
-H 'content-type: application/json' \
-d '{"by":"text","value":"Settings"}'{"id":1,"cmd":"scroll_to","by":"text","value":"Settings"}Input
input
Wait for a field and set its text
Uses the accessibility set-text action. Fields that ignore it fall back to the Droidline keyboard when it is selected.
| Name | Type | Default | Meaning |
|---|---|---|---|
by | selector | required | Which dump field to match: text, textContains, id, desc, descContains, class |
value | string | required | The value to match |
text | string | required | Text to enter |
append | bool | false | Keep existing text and add to the end |
nth | int | 0 | Index when several elements match, starting at 0 |
timeout | number | 10 s | Seconds to wait for the target to appear |
Returns: an object with via, ms
d.input("id", "email", "me@example.com")await d.input("id", "email", "me@example.com");droidline input id email me@example.comcurl -s -X POST localhost:8780/devices/_/input \
-H 'content-type: application/json' \
-d '{"by":"id","value":"email","text":"me@example.com"}'{"id":1,"cmd":"input","by":"id","value":"email","text":"me@example.com"}clear
Empty a text field
| Name | Type | Default | Meaning |
|---|---|---|---|
by | selector | required | Which dump field to match: text, textContains, id, desc, descContains, class |
value | string | required | The value to match |
nth | int | 0 | Index when several elements match, starting at 0 |
timeout | number | 10 s | Seconds to wait for the target to appear |
Returns: an object with ms
d.clear("id", "email")await d.clear("id", "email");droidline clear id emailcurl -s -X POST localhost:8780/devices/_/clear \
-H 'content-type: application/json' \
-d '{"by":"id","value":"email"}'{"id":1,"cmd":"clear","by":"id","value":"email"}sendkey
Send a key name, a key code, or text
back, home, recents, notifications, quick_settings and lock use accessibility global actions. Other keys and text go through the Droidline keyboard to the focused field.
| Name | Type | Default | Meaning |
|---|---|---|---|
key | string|int | Key name (enter, tab, del, space, escape, up, down, left, right, back, home...), Android key code, or text to type | |
text | string | Type this text literally, even if it equals a key name |
Returns: an object with via
d.sendkey("enter")await d.sendkey("enter");droidline sendkey entercurl -s -X POST localhost:8780/devices/_/sendkey \
-H 'content-type: application/json' \
-d '{"key":"enter"}'{"id":1,"cmd":"sendkey","key":"enter"}Checks
exists
Whether an element is on screen right now. Never waits
| Name | Type | Default | Meaning |
|---|---|---|---|
by | selector | required | Which dump field to match: text, textContains, id, desc, descContains, class |
value | string | required | The value to match |
nth | int | 0 | Index when several elements match, starting at 0 |
Returns: a value of type bool
d.exists("text", "Close ad")await d.exists("text", "Close ad");droidline exists text "Close ad"curl -s -X POST localhost:8780/devices/_/exists \
-H 'content-type: application/json' \
-d '{"by":"text","value":"Close ad"}'{"id":1,"cmd":"exists","by":"text","value":"Close ad"}wait
Wait until an element appears
| Name | Type | Default | Meaning |
|---|---|---|---|
by | selector | required | Which dump field to match: text, textContains, id, desc, descContains, class |
value | string | required | The value to match |
timeout | number | 10 s | Seconds to wait for the target to appear |
nth | int | 0 | Index when several elements match, starting at 0 |
Returns: an object with ms
Errors: NOT_FOUND
d.wait("text", "Done", timeout=30)await d.wait("text", "Done", { timeout: 30 });droidline wait text Done --timeout 30curl -s -X POST localhost:8780/devices/_/wait \
-H 'content-type: application/json' \
-d '{"by":"text","value":"Done","timeout":30}'{"id":1,"cmd":"wait","by":"text","value":"Done","timeout":30}wait_gone
Wait until an element disappears
| Name | Type | Default | Meaning |
|---|---|---|---|
by | selector | required | Which dump field to match: text, textContains, id, desc, descContains, class |
value | string | required | The value to match |
timeout | number | 10 s | Seconds to wait for the target to appear |
Returns: an object with ms
Errors: TIMEOUT
d.wait_gone("text", "Loading")await d.waitGone("text", "Loading");droidline wait_gone text Loadingcurl -s -X POST localhost:8780/devices/_/wait_gone \
-H 'content-type: application/json' \
-d '{"by":"text","value":"Loading"}'{"id":1,"cmd":"wait_gone","by":"text","value":"Loading"}get_text
Text of an element, or an empty string
| Name | Type | Default | Meaning |
|---|---|---|---|
by | selector | required | Which dump field to match: text, textContains, id, desc, descContains, class |
value | string | required | The value to match |
nth | int | 0 | Index when several elements match, starting at 0 |
Returns: a value of type string
d.get_text("id", "balance")await d.getText("id", "balance");droidline get_text id balancecurl -s -X POST localhost:8780/devices/_/get_text \
-H 'content-type: application/json' \
-d '{"by":"id","value":"balance"}'{"id":1,"cmd":"get_text","by":"id","value":"balance"}Conditions
checkedenabledselectedcountwhichin_appkeyboard_shownlast_toastcolor
checked
true if a switch or checkbox is on
| Name | Type | Default | Meaning |
|---|---|---|---|
by | selector | required | Which dump field to match: text, textContains, id, desc, descContains, class |
value | string | required | The value to match |
nth | int | 0 | Index when several elements match, starting at 0 |
Returns: a value of type bool
d.checked("id", "auto_login")await d.checked("id", "auto_login");droidline checked id auto_logincurl -s -X POST localhost:8780/devices/_/checked \
-H 'content-type: application/json' \
-d '{"by":"id","value":"auto_login"}'{"id":1,"cmd":"checked","by":"id","value":"auto_login"}enabled
true if the element can be pressed
| Name | Type | Default | Meaning |
|---|---|---|---|
by | selector | required | Which dump field to match: text, textContains, id, desc, descContains, class |
value | string | required | The value to match |
nth | int | 0 | Index when several elements match, starting at 0 |
Returns: a value of type bool
d.enabled("text", "Next")await d.enabled("text", "Next");droidline enabled text Nextcurl -s -X POST localhost:8780/devices/_/enabled \
-H 'content-type: application/json' \
-d '{"by":"text","value":"Next"}'{"id":1,"cmd":"enabled","by":"text","value":"Next"}selected
true if a tab or item is selected
| Name | Type | Default | Meaning |
|---|---|---|---|
by | selector | required | Which dump field to match: text, textContains, id, desc, descContains, class |
value | string | required | The value to match |
nth | int | 0 | Index when several elements match, starting at 0 |
Returns: a value of type bool
d.selected("text", "Home")await d.selected("text", "Home");droidline selected text Homecurl -s -X POST localhost:8780/devices/_/selected \
-H 'content-type: application/json' \
-d '{"by":"text","value":"Home"}'{"id":1,"cmd":"selected","by":"text","value":"Home"}count
Number of matching elements
| Name | Type | Default | Meaning |
|---|---|---|---|
by | selector | required | Which dump field to match: text, textContains, id, desc, descContains, class |
value | string | required | The value to match |
Returns: a value of type int
d.count("class", "android.widget.CheckBox")await d.count("class", "android.widget.CheckBox");droidline count class android.widget.CheckBoxcurl -s -X POST localhost:8780/devices/_/count \
-H 'content-type: application/json' \
-d '{"by":"class","value":"android.widget.CheckBox"}'{"id":1,"cmd":"count","by":"class","value":"android.widget.CheckBox"}which
Index of the first candidate to appear, or -1
| Name | Type | Default | Meaning |
|---|---|---|---|
candidates | list<selector_pair> | required | List of [by, value] pairs |
timeout | number | 10 s | Seconds to wait for any candidate |
Returns: a value of type int
d.which([("text", "Log in"), ("id", "main_tab")], timeout=15)await d.which([["text", "Log in"], ["id", "main_tab"]], { timeout: 15 });droidline which text="Log in" id=main_tab --timeout 15curl -s -X POST localhost:8780/devices/_/which \
-H 'content-type: application/json' \
-d '{"candidates":[["text","Log in"],["id","main_tab"]],"timeout":15}'{"id":1,"cmd":"which","candidates":[["text","Log in"],["id","main_tab"]],"timeout":15}in_app
true if that app is in the foreground
| Name | Type | Default | Meaning |
|---|---|---|---|
package | string | required | Package name, for example com.android.chrome |
Returns: a value of type bool
d.in_app("com.android.chrome")await d.inApp("com.android.chrome");droidline in_app com.android.chromecurl -s -X POST localhost:8780/devices/_/in_app \
-H 'content-type: application/json' \
-d '{"package":"com.android.chrome"}'{"id":1,"cmd":"in_app","package":"com.android.chrome"}keyboard_shown
true if a soft keyboard is showing
Returns: a value of type bool
d.keyboard_shown()await d.keyboardShown();droidline keyboard_showncurl -s -X POST localhost:8780/devices/_/keyboard_shown \
-H 'content-type: application/json'{"id":1,"cmd":"keyboard_shown"}last_toast
Text of the most recent toast, or an empty string
| Name | Type | Default | Meaning |
|---|---|---|---|
max_age | number | 30 s | Ignore toasts older than this many seconds |
Returns: a value of type string
d.last_toast()await d.lastToast();droidline last_toastcurl -s -X POST localhost:8780/devices/_/last_toast \
-H 'content-type: application/json'{"id":1,"cmd":"last_toast"}color
Pixel color at a coordinate as #RRGGBB
For screens without accessibility nodes, such as games.
| Name | Type | Default | Meaning |
|---|---|---|---|
x | int | required | X in screen pixels |
y | int | required | Y in screen pixels |
Returns: a value of type string
d.color(540, 1200)await d.color(540, 1200);droidline color 540 1200curl -s -X POST localhost:8780/devices/_/color \
-H 'content-type: application/json' \
-d '{"x":540,"y":1200}'{"id":1,"cmd":"color","x":540,"y":1200}Device
screen_onlockedwakelockbatteryorientationinfo
screen_on
true if the screen is on
Returns: a value of type bool
d.screen_on()await d.screenOn();droidline screen_oncurl -s -X POST localhost:8780/devices/_/screen_on \
-H 'content-type: application/json'{"id":1,"cmd":"screen_on"}locked
true if the lock screen is showing
Returns: a value of type bool
d.locked()await d.locked();droidline lockedcurl -s -X POST localhost:8780/devices/_/locked \
-H 'content-type: application/json'{"id":1,"cmd":"locked"}wake
Turn the screen on and dismiss a lock screen that has no PIN
Gestures fail while the screen is off. A PIN, pattern or password lock cannot be dismissed without the user.
Returns: an object with screen_on, locked
d.wake()await d.wake();droidline wakecurl -s -X POST localhost:8780/devices/_/wake \
-H 'content-type: application/json'{"id":1,"cmd":"wake"}lock
Turn the screen off and lock
Returns: nothing
d.lock()await d.lock();droidline lockcurl -s -X POST localhost:8780/devices/_/lock \
-H 'content-type: application/json'{"id":1,"cmd":"lock"}battery
Battery level and charging state
Returns: an object with level, charging, temperature
d.battery()await d.battery();droidline batterycurl -s -X POST localhost:8780/devices/_/battery \
-H 'content-type: application/json'{"id":1,"cmd":"battery"}orientation
portrait or landscape
Returns: a value of type string
d.orientation()await d.orientation();droidline orientationcurl -s -X POST localhost:8780/devices/_/orientation \
-H 'content-type: application/json'{"id":1,"cmd":"orientation"}info
Model, Android version, screen size and permission readiness
Returns: an object with model, manufacturer, sdk, release, agent, width, height, ready
d.info()await d.info();droidline infocurl -s -X POST localhost:8780/devices/_/info \
-H 'content-type: application/json'{"id":1,"cmd":"info"}Network
network
Connection type (wifi, mobile, none) and airplane mode
Returns: an object with type, airplane, metered
d.network()await d.network();droidline networkcurl -s -X POST localhost:8780/devices/_/network \
-H 'content-type: application/json'{"id":1,"cmd":"network"}proxy
Route chosen apps through an upstream proxy with a per-app VPN
Supports http:// (CONNECT) and socks5:// with user:pass. Pass null or "off" to stop. One upstream at a time. Apps that ignore the proxy setting lose network access instead of leaking.
| Name | Type | Default | Meaning |
|---|---|---|---|
url | string|null | required | socks5://user:pass@host:port, http://host:port, a saved profile like @kr1, or off |
app | string|list<string> | Package or packages to route |
Returns: an object with active, apps
Errors: NO_PERMISSION, PROXY_FAILED, UNSUPPORTED
d.proxy("@kr1", app="com.android.chrome")await d.proxy("@kr1", { app: "com.android.chrome" });droidline proxy @kr1 --app com.android.chromecurl -s -X POST localhost:8780/devices/_/proxy \
-H 'content-type: application/json' \
-d '{"url":"@kr1","app":"com.android.chrome"}'{"id":1,"cmd":"proxy","url":"@kr1","app":"com.android.chrome"}proxy_check
Per-app proxy state and the IP the outside world sees
| Name | Type | Default | Meaning |
|---|---|---|---|
app | string | Package to check |
Returns: an object with active, ip, upstream, error
d.proxy_check("com.android.chrome")await d.proxyCheck("com.android.chrome");droidline proxy_check com.android.chromecurl -s -X POST localhost:8780/devices/_/proxy_check \
-H 'content-type: application/json' \
-d '{"app":"com.android.chrome"}'{"id":1,"cmd":"proxy_check","app":"com.android.chrome"}Apps
launchopen_urlkillclear_dataappsinstalled
launch
Start an app, optionally at a specific activity
| Name | Type | Default | Meaning |
|---|---|---|---|
package | string | required | Package name, for example com.android.chrome |
activity | string | Activity name, either full or starting with a dot |
Returns: an object with ms
Errors: APP_NOT_FOUND, ACTIVITY_BLOCKED
d.launch("com.android.settings")await d.launch("com.android.settings");droidline launch com.android.settingscurl -s -X POST localhost:8780/devices/_/launch \
-H 'content-type: application/json' \
-d '{"package":"com.android.settings"}'{"id":1,"cmd":"launch","package":"com.android.settings"}open_url
Open a URL or deep link
| Name | Type | Default | Meaning |
|---|---|---|---|
url | string | required | http(s) URL or app deep link |
package | string | Open with this app only |
Returns: nothing
d.open_url("https://droidline.dev")await d.openUrl("https://droidline.dev");droidline open_url https://droidline.devcurl -s -X POST localhost:8780/devices/_/open_url \
-H 'content-type: application/json' \
-d '{"url":"https://droidline.dev"}'{"id":1,"cmd":"open_url","url":"https://droidline.dev"}kill
Force stop an app
Runs a settings macro: App info, Force stop, OK. Takes a few seconds.
| Name | Type | Default | Meaning |
|---|---|---|---|
package | string | required | Package name, for example com.android.chrome |
Returns: an object with via, ms
Errors: APP_NOT_FOUND, MACRO_FAILED
d.kill("com.android.chrome")await d.kill("com.android.chrome");droidline kill com.android.chromecurl -s -X POST localhost:8780/devices/_/kill \
-H 'content-type: application/json' \
-d '{"package":"com.android.chrome"}'{"id":1,"cmd":"kill","package":"com.android.chrome"}clear_data
Clear an app's data
Runs a settings macro: App info, Storage, Clear data, OK.
| Name | Type | Default | Meaning |
|---|---|---|---|
package | string | required | Package name, for example com.android.chrome |
Returns: an object with via, ms
Errors: APP_NOT_FOUND, MACRO_FAILED
d.clear_data("com.android.chrome")await d.clearData("com.android.chrome");droidline clear_data com.android.chromecurl -s -X POST localhost:8780/devices/_/clear_data \
-H 'content-type: application/json' \
-d '{"package":"com.android.chrome"}'{"id":1,"cmd":"clear_data","package":"com.android.chrome"}apps
Installed packages
| Name | Type | Default | Meaning |
|---|---|---|---|
system | bool | false | Include system packages |
Returns: a value of type list<app>
d.apps()await d.apps();droidline appscurl -s -X POST localhost:8780/devices/_/apps \
-H 'content-type: application/json'{"id":1,"cmd":"apps"}installed
Version name if installed, empty string if not
| Name | Type | Default | Meaning |
|---|---|---|---|
package | string | required | Package name, for example com.android.chrome |
Returns: a value of type string
d.installed("com.android.chrome")await d.installed("com.android.chrome");droidline installed com.android.chromecurl -s -X POST localhost:8780/devices/_/installed \
-H 'content-type: application/json' \
-d '{"package":"com.android.chrome"}'{"id":1,"cmd":"installed","package":"com.android.chrome"}System
backhomerecentsopen_notificationsquick_settingsdatawifiairplaneclipboardbatch
back
Back
Returns: nothing
d.back()await d.back();droidline backcurl -s -X POST localhost:8780/devices/_/back \
-H 'content-type: application/json'{"id":1,"cmd":"back"}home
Home screen
Returns: nothing
d.home()await d.home();droidline homecurl -s -X POST localhost:8780/devices/_/home \
-H 'content-type: application/json'{"id":1,"cmd":"home"}recents
Recent apps
Returns: nothing
d.recents()await d.recents();droidline recentscurl -s -X POST localhost:8780/devices/_/recents \
-H 'content-type: application/json'{"id":1,"cmd":"recents"}open_notifications
Pull down the notification shade
Returns: nothing
d.open_notifications()await d.openNotifications();droidline open_notificationscurl -s -X POST localhost:8780/devices/_/open_notifications \
-H 'content-type: application/json'{"id":1,"cmd":"open_notifications"}quick_settings
Open quick settings
Returns: nothing
d.quick_settings()await d.quickSettings();droidline quick_settingscurl -s -X POST localhost:8780/devices/_/quick_settings \
-H 'content-type: application/json'{"id":1,"cmd":"quick_settings"}data
Turn mobile data on or off
Cuts the phone's own connection. The call answers accepted first; pass wait to get the final result instead.
| Name | Type | Default | Meaning |
|---|---|---|---|
on | bool | required | true to turn on, false to turn off |
Returns: an object with via, ms
Errors: MACRO_FAILED
d.data(False, wait=True)await d.data(false, { wait: true });droidline data false --waitcurl -s -X POST localhost:8780/devices/_/data \
-H 'content-type: application/json' \
-d '{"wait":true,"on":false}'{"id":1,"cmd":"data","on":false,"wait":true}wifi
Turn Wi-Fi on or off
Cuts the phone's own connection. The call answers accepted first; pass wait to get the final result instead.
| Name | Type | Default | Meaning |
|---|---|---|---|
on | bool | required | true to turn on, false to turn off |
Returns: an object with via, ms
Errors: MACRO_FAILED
d.wifi(False, wait=True)await d.wifi(false, { wait: true });droidline wifi false --waitcurl -s -X POST localhost:8780/devices/_/wifi \
-H 'content-type: application/json' \
-d '{"wait":true,"on":false}'{"id":1,"cmd":"wifi","on":false,"wait":true}airplane
Turn airplane mode on or off
To renew the IP, put on and off in one batch so the phone runs both while offline.
Cuts the phone's own connection. The call answers accepted first; pass wait to get the final result instead.
| Name | Type | Default | Meaning |
|---|---|---|---|
on | bool | required | true to turn on, false to turn off |
Returns: an object with via, ms
Errors: MACRO_FAILED
d.airplane(True, wait=True)await d.airplane(true, { wait: true });droidline airplane true --waitcurl -s -X POST localhost:8780/devices/_/airplane \
-H 'content-type: application/json' \
-d '{"wait":true,"on":true}'{"id":1,"cmd":"airplane","on":true,"wait":true}clipboard
Write the clipboard, or read it when called without text
Reading on Android 10+ needs the Droidline keyboard to be the current input method.
| Name | Type | Default | Meaning |
|---|---|---|---|
text | string | Text to copy. Omit to read |
Returns: a value of type string
Errors: NO_IME
d.clipboard("Hello")await d.clipboard("Hello");droidline clipboard Hellocurl -s -X POST localhost:8780/devices/_/clipboard \
-H 'content-type: application/json' \
-d '{"text":"Hello"}'{"id":1,"cmd":"clipboard","text":"Hello"}batch
Run several commands on the phone in one go, even while it is offline
Steps are [cmd, args...] lists or {cmd, ...} objects. The step sleep(ms) only exists inside batch. If a step cuts the network, the call returns accepted and the result arrives after reconnect.
| Name | Type | Default | Meaning |
|---|---|---|---|
steps | list<step> | required | Commands to run in order |
stop_on_error | bool | true | Stop at the first failing step |
Returns: an object with results
d.batch([("airplane", True), ("sleep", 3000), ("airplane", False)], wait=True)await d.batch([["airplane", true], ["sleep", 3000], ["airplane", false]], { wait: true });droidline batch '[["airplane",true],["sleep",3000],["airplane",false]]' --waitcurl -s -X POST localhost:8780/devices/_/batch \
-H 'content-type: application/json' \
-d '{"wait":true,"steps":[["airplane",true],["sleep",3000],["airplane",false]]}'{"id":1,"cmd":"batch","steps":[["airplane",true],["sleep",3000],["airplane",false]],"wait":true}Chrome
chrome.go
Open a URL in Chrome
| Name | Type | Default | Meaning |
|---|---|---|---|
url | string | required | Address. https:// is added if missing |
new_tab | bool | false | Open in a new tab |
Returns: an object with ms
Errors: APP_NOT_FOUND
d.chrome.go("droidline.dev")await d.chrome.go("droidline.dev");droidline chrome.go droidline.devcurl -s -X POST localhost:8780/devices/_/chrome.go \
-H 'content-type: application/json' \
-d '{"url":"droidline.dev"}'{"id":1,"cmd":"chrome.go","url":"droidline.dev"}Notifications
notificationshas_notificationwait_notificationnotification_replynotification_clicknotification_dismissnotify_filteron_notification
notifications
Notifications currently showing
| Name | Type | Default | Meaning |
|---|---|---|---|
package | string | Only this app |
Returns: a value of type list<notification>
d.notifications()await d.notifications();droidline notificationscurl -s -X POST localhost:8780/devices/_/notifications \
-H 'content-type: application/json'{"id":1,"cmd":"notifications"}has_notification
true if a showing notification matches
| Name | Type | Default | Meaning |
|---|---|---|---|
by | string text | textContains | title | package | required | text and textContains look at both title and text |
value | string | required | The value to match |
Returns: a value of type bool
d.has_notification("textContains", "shipped")await d.hasNotification("textContains", "shipped");droidline has_notification textContains shippedcurl -s -X POST localhost:8780/devices/_/has_notification \
-H 'content-type: application/json' \
-d '{"by":"textContains","value":"shipped"}'{"id":1,"cmd":"has_notification","by":"textContains","value":"shipped"}wait_notification
Wait for a matching notification and return it
Handled by the PC server, so it does not block other commands to the phone. On Android 15+ the OS hides one-time codes from apps: you get the notification but the code is masked.
| Name | Type | Default | Meaning |
|---|---|---|---|
by | string text | textContains | title | package | required | text and textContains look at both title and text |
value | string | required | The value to match |
timeout | number | 60 s | Seconds to wait |
package | string | Only from this app |
Returns: a value of type notification
Errors: TIMEOUT
dl.wait_notification("textContains", "verification code", 60)await dl.waitNotification("textContains", "verification code", 60);droidline wait_notification textContains "verification code" 60curl -s -X POST localhost:8780/server/wait_notification \
-H 'content-type: application/json' \
-d '{"by":"textContains","value":"verification code","timeout":60}'{"id":1,"cmd":"wait_notification","by":"textContains","value":"verification code","timeout":60}notification_reply
Reply inline to a notification that has a reply action
| Name | Type | Default | Meaning |
|---|---|---|---|
key | string | required | Notification key from notifications() or a notification event |
text | string | required | Reply text |
Returns: nothing
n = d.notifications()[0]
d.notification_reply(n["key"], "On my way")const [n] = await d.notifications();
await d.notificationReply(n.key, "On my way");KEY=$(droidline --json notifications | jq -r '.value[0].key')
droidline notification_reply "$KEY" "On my way"curl -s -X POST localhost:8780/devices/_/notification_reply \
-H 'content-type: application/json' \
-d '{"key":"KEY","text":"On my way"}'{"id":1,"cmd":"notification_reply","key":"KEY","text":"On my way"}notification_click
Open a notification
| Name | Type | Default | Meaning |
|---|---|---|---|
key | string | required | Notification key from notifications() or a notification event |
Returns: nothing
n = d.notifications()[0]
d.notification_click(n["key"])const [n] = await d.notifications();
await d.notificationClick(n.key);KEY=$(droidline --json notifications | jq -r '.value[0].key')
droidline notification_click "$KEY"curl -s -X POST localhost:8780/devices/_/notification_click \
-H 'content-type: application/json' \
-d '{"key":"KEY"}'{"id":1,"cmd":"notification_click","key":"KEY"}notification_dismiss
Dismiss a notification
| Name | Type | Default | Meaning |
|---|---|---|---|
key | string | required | Notification key from notifications() or a notification event |
Returns: nothing
n = d.notifications()[0]
d.notification_dismiss(n["key"])const [n] = await d.notifications();
await d.notificationDismiss(n.key);KEY=$(droidline --json notifications | jq -r '.value[0].key')
droidline notification_dismiss "$KEY"curl -s -X POST localhost:8780/devices/_/notification_dismiss \
-H 'content-type: application/json' \
-d '{"key":"KEY"}'{"id":1,"cmd":"notification_dismiss","key":"KEY"}notify_filter
Choose which apps' notifications are sent to the PC. Default is none
| Name | Type | Default | Meaning |
|---|---|---|---|
packages | list<string> | Allowed packages. Omit to read the current list |
Returns: a value of type list<string>
d.notify_filter(["com.android.chrome", "com.google.android.gm"])await d.notifyFilter(["com.android.chrome", "com.google.android.gm"]);droidline notify_filter com.android.chrome,com.google.android.gmcurl -s -X POST localhost:8780/devices/_/notify_filter \
-H 'content-type: application/json' \
-d '{"packages":["com.android.chrome","com.google.android.gm"]}'{"id":1,"cmd":"notify_filter","packages":["com.android.chrome","com.google.android.gm"]}on_notification
Call a function for every matching notification
SDK only. Built on subscribe. The CLI prints matching notifications as JSON lines instead.
Runs inside the SDK; the server sees a subscribe line.
| Name | Type | Default | Meaning |
|---|---|---|---|
package | string | Only from this app | |
textContains | string | Only if title or text contains this |
Returns: nothing
stop = d.on_notification(package="com.google.android.gm", callback=print)
# ... later
stop()const stop = await d.onNotification({ package: "com.google.android.gm" }, (n) => console.log(n.title, n.text));
// ... later
stop();droidline on_notification --package com.google.android.gm{"id":1,"cmd":"subscribe","events":["notification"]}Server
devicespairpair_qrrenamerevokesubscribeserver_infoauth
devices
Paired devices with online state and route
Returns: a value of type list<device>
dl.devices()await dl.devices();droidline devicescurl -s localhost:8780/devices{"id":1,"cmd":"devices"}pair
Approve the phone that shows this 6-digit code
| Name | Type | Default | Meaning |
|---|---|---|---|
code | string | required | Code shown on the phone |
name | string | Name to give the device |
Returns: a value of type device
Errors: PAIRING_FAILED
dl.pair("482913", name="shelf-01")await dl.pair("482913", { name: "shelf-01" });droidline pair 482913 --name shelf-01curl -s -X POST localhost:8780/server/pair \
-H 'content-type: application/json' \
-d '{"code":"482913","name":"shelf-01"}'{"id":1,"cmd":"pair","code":"482913","name":"shelf-01"}pair_qr
Create a one-time pairing QR code valid for 10 minutes
| Name | Type | Default | Meaning |
|---|---|---|---|
name | string | Name to give the device |
Returns: an object with uri, expires
dl.pair_qr()await dl.pairQr();droidline pair # shows the QR code in the terminalcurl -s -X POST localhost:8780/server/pair_qr \
-H 'content-type: application/json'{"id":1,"cmd":"pair_qr"}rename
Give a device a name
| Name | Type | Default | Meaning |
|---|---|---|---|
device | string | required | Device ID or name |
name | string | required | New name |
Returns: a value of type device
dl.rename("k7d2q9xa", "shelf-01")await dl.rename("k7d2q9xa", "shelf-01");droidline rename k7d2q9xa shelf-01curl -s -X POST localhost:8780/server/rename \
-H 'content-type: application/json' \
-d '{"device":"k7d2q9xa","name":"shelf-01"}'{"id":1,"cmd":"rename","device":"k7d2q9xa","name":"shelf-01"}revoke
Unpair a device. It must pair again to connect
| Name | Type | Default | Meaning |
|---|---|---|---|
device | string | required | Device ID or name |
Returns: nothing
dl.revoke("shelf-01")await dl.revoke("shelf-01");droidline revoke shelf-01curl -s -X POST localhost:8780/server/revoke \
-H 'content-type: application/json' \
-d '{"device":"shelf-01"}'{"id":1,"cmd":"revoke","device":"shelf-01"}subscribe
Receive events on this connection
| Name | Type | Default | Meaning |
|---|---|---|---|
events | list<string> | required | Any of notification, screen, toast, device, result |
device | string | Only from this device. Omit for all |
Returns: nothing
dl.subscribe(["notification"])await dl.subscribe(["notification"]);{"id":1,"cmd":"subscribe","events":["notification"]}server_info
Server version, ports and listening addresses
Returns: an object with version, server, name, proto, agent_port, client_port
dl.server_info()await dl.serverInfo();droidline server_infocurl -s -X POST localhost:8780/server/server_info \
-H 'content-type: application/json'{"id":1,"cmd":"server_info"}auth
Authenticate this client connection with a token
| Name | Type | Default | Meaning |
|---|---|---|---|
token | string | required | Client token from droidline token |
Returns: nothing
dl.auth("your-client-token")await dl.auth("your-client-token");{"id":1,"cmd":"auth","token":"your-client-token"}