Android phones,
one line at a time.

Drive real phones from Python, Node.js,
the shell or an AI agent.
No ADB, no USB cable, no root.

Install the SDKpip install droidlinenpm install droidline
shelf-01online · Android 14login.py
  1. Nothing sent yet. Send the first line, or run the whole script.
d.launch("dev.droidline.demo")

Simulated in your browser with the same demo app that droidline-fakephone runs. Requests and replies use the real line format.

The phone dials out.
Your code stays on localhost.

droidline serve runs on your PC. The Droidline app on the phone connects to it, so the phone opens no port and never needs adb forward. Your code sends one JSON line to localhost:8780 and reads one line back.

Your codePython, Node.js, CLI, HTTP or MCP
one line per command
droidline serveon your PC, port 8780 for your code
the phone connects out
Droidline appon each phone, Android 9 or later
Encrypted end to end
P-256 key exchange and AES-256-GCM on every line after the handshake.
Waiting happens on the phone
touch waits up to 10 seconds for its target and falls back to a coordinate tap by itself.
Three permissions, no root
An accessibility service, a keyboard and an optional per-app VPN. Nothing needs Shizuku or adb.

Pick the element,
not the pixel.

dump() returns the screen as a tree. Every element has text, id and desc. Pass the field and the value, and touch waits for the element, taps it, and taps the center of its bounds if the element refuses the click.

Choose an element on the phone

This element in dump()

Select an element to see its fields.
Select an element to see its fields.

One name
in every language.

touch is touch in the SDKs, on the wire, in the CLI and as an MCP tool. They are all generated from one file, commands.json, so a new command reaches every language at once.

pip install droidline

from droidline import connect

d = connect()
d.touch("text", "Log in")
Read the guide: Python

Built for
a shelf of phones.

One PC runs many phones. Commands to one phone run in order, and different phones run in parallel.

shelf-01 online lan

Same Wi-Fi: The phone finds the PC with a UDP broadcast and connects directly.

d = dl.device("shelf-01")
d.launch("com.android.chrome")
  • Names, not serial numbersName a phone once (shelf-01) and address it by that name from every interface.
  • A proxy per appSend chosen apps through socks5 or http over a local VPN, one upstream per phone.
  • Notifications as eventsWait for one with wait_notification, or receive them all through a signed webhook.
  • Nothing runs twiceA phone that drops off mobile data resumes where it left off; a command in flight is never repeated.

Off your Wi-Fi, too.

Phones on mobile data sit behind the carrier's NAT and cannot accept connections, so the phone always connects out. Pick the route that fits your network; the phone tries them in order and switches back to Wi-Fi when it can.

internetYour PCdroidline serverouterPhone
Same Wi-FiThe phone finds the PC with a UDP broadcast and connects directly.

Past the handshake every line is encrypted end to end. A tunnel or relay only carries ciphertext. Remote connection guides

What Droidline
cannot do.

It only uses permissions an ordinary app can get. That rules some things out, and it is better to know before you start.

Full list of limits
  1. Open another app's screens that the app does not export. launch falls back to the start screen.
  2. Unlock a PIN, pattern or password lock screen.
  3. Read one-time codes from notifications on Android 15 and later: you learn that a code arrived, then read it in the app.
  4. Tap elements that games and some custom UIs never expose. Use tap with coordinates and color(x, y) there.
  5. Run instantly when a command needs Settings: force stop, clear data and the network toggles press buttons for you and take a few seconds.

How it differs from ADB tools
and on-phone scripts.

DroidlineADB-based toolsuiautomator2 3.x, Appium UiAutomator2On-phone scriptsAuto.js, AutoX.js
Needs ADBNoYesNo
Where your code runsYour PCYour PCThe phone
LanguageAny, through SDKs, HTTP or a socketThe tool's client librariesJavaScript
Better atMany phones over Wi-Fi or mobile data, no cableInstalling apps, adb shell, instrumentation, non-exported screensRunning with no PC at all

Sources: uiautomator2, Appium UiAutomator2 driver, AutoX.js

Questions people
ask first.

Do I need ADB at any point?

No. You install the app from an APK file, turn on its permissions in the phone's settings, and pair it with a QR code or a 6-digit code. On Android 13 and later you also allow restricted settings for the app once, which the app walks you through.

Does it work when the phone is on mobile data?

Yes. The phone always connects out, so it works behind a carrier's NAT. Use a forwarded port, a tunnel such as Cloudflare Tunnel, or a relay you deploy to Cloudflare Workers or a VPS. Nobody runs a public relay for you.

Can the relay or tunnel see my screen or my commands?

No. After the two-line handshake every line is encrypted with AES-256-GCM using keys only your PC and your phone hold. The relay sees device IDs, sizes and timing.

Which Android versions are supported?

Android 9 (API 28) and later. A few features need newer versions: the per-app proxy needs Android 10, and the accessibility screenshot needs Android 11 (older versions ask once for screen capture permission).

Is the app on Google Play?

No. Signed APKs are published on GitHub Releases, and the app tells you when a new version is out.

Does it need root or Shizuku?

No. Everything runs on the accessibility service, the Droidline keyboard and Android's VPN API, which any app can use with your permission.

Can an AI agent use it?

Yes. droidline mcp exposes every command as an MCP tool. The agent calls dump to see the screen and touch, input or scroll_to to act on it.

What happens if the PC restarts while a command is running?

The phone keeps unacknowledged replies and resends them when it reconnects. A command that was in flight is not run twice; if the phone app itself restarted, the call fails with AGENT_RESTARTED so you can decide.

Pair your
first phone.

  1. Run the server on your PCdroidline serve
  2. Install the app and pairdroidline pair
  3. Send a commanddroidline touch text "OK"