Search

Python SDK

Python ADB Tap, Swipe, Type and Key Press in MAS

Python ADB tap, swipe, type and key press on an Android emulator with the MAS SDK, using the real defaults, humanized timing and two worked examples.

  • Windows
  • Mac
  • Emulator
  • Cloud device
  • Python SDK
Intermediate Updated 5 min read
On this page
  1. Python ADB tap coordinates and screen size
  2. click
  3. swipe
  4. input_text
  5. key_press
  6. zoom_in and zoom_out
  7. Humanized timing in ADB Python scripting
  8. Example: type into a search field
  9. Example: scroll until found
  10. Errors

The interaction functions are how a Macro Automation Studio (MAS) macro touches the screen from Python. Each tap, swipe and key press reaches the device as a real input event, over adb on an emulator, so an app sees it as a finger would. This page explains each function, its defaults, and the timing habits that keep a macro readable and believable. All of them live at the top of the mas package. Full signatures are on the API reference. If you describe the task to MAS Agent instead, it writes this code for you.

Python ADB tap coordinates and screen size

Every coordinate is a pixel offset from the top-left corner of the screen. x grows to the right and y grows downward. get_screen_size() returns the width and height of the connected device, so you can compute positions instead of hard-coding them.

python
import mas

size = mas.get_screen_size()
mas.click(size.width // 2, size.height // 2)            # center of the screen
mas.swipe((size.width // 2, int(size.height * 0.8)),
          (size.width // 2, int(size.height * 0.2)))    # scroll down one screen

Hard-coded coordinates are tied to the resolution you wrote them on, just like template images. Keep every device that runs a macro on the same resolution, or derive positions from get_screen_size() and from find_object matches. Points you pick in Asset Lab are already in device pixels.

click

click(x, y, delay_ms=1000) taps once at a point, then waits delay_ms milliseconds before returning. The default pause is a full second, which gives most apps time to react before your next line runs. Shorten it for quick menus and lengthen it for screens that animate.

python
import mas

mas.click(150, 300)                  # tap, then wait 1000 ms
mas.click(150, 300, delay_ms=250)    # tap, then wait 250 ms

The usual pattern is to tap the center of a template match rather than a fixed point. See Vision for the matching side.

python
import mas

images = mas.images({"claim_btn": 784})
match = mas.find_object_retry(images.claim_btn, total_tries=3, time_sleep=2.0)
if match:
    mas.click(match.x, match.y)

There is no separate long-press or double-tap function. To hold a hardware key, use key_press with a duration_ms of 500 or more.

swipe

swipe(from_coords, to_coords, duration_ms=1000) drags one finger from a start point to an end point. Both points are (x, y) tuples. duration_ms is how long the finger stays down, so it sets the speed: a short swipe flicks and scrolls further, a long swipe drags.

python
import mas

mas.swipe((500, 1500), (500, 500), duration_ms=400)    # swipe up: the list scrolls down
mas.swipe((100, 500), (900, 500), duration_ms=300)     # swipe right: previous page
mas.swipe((200, 300), (800, 300), duration_ms=1000)    # slow drag, for drag-and-drop

Mind the direction. To see content further down a list, the finger moves up.

input_text

input_text(text, delay_ms=0, clear=False) types into the field that currently has focus. Tap the field first; typing into nothing does nothing. With clear=True the cursor moves to the end of the field and the existing characters are deleted before typing, so the field does not need to be empty. delay_ms waits after typing and defaults to 0.

python
import mas

mas.click(540, 420)                            # focus the field
mas.input_text("user@example.com")
mas.input_text("new value", clear=True)        # replace whatever was there
mas.input_text("SecurePassword123!", delay_ms=500)

key_press

key_press(key_code, modifiers=None, duration_ms=100, repeat=1) presses a hardware key. key_code is a member of KeyCode, and modifiers is an optional list of Modifier members: SHIFT, CTRL, ALT and META.

Two parameters need care:

  • duration_ms: a value of 500 or more sends the key as a long press; anything smaller is a normal press. The Android input bridge has no arbitrary-hold primitive, so the exact number of milliseconds is not honored beyond that distinction. duration_ms=3000 and duration_ms=500 do the same thing.
  • repeat: how many times to press the key, from 1 to 100. All presses go to the device in one command, so repeat=10 is much faster than ten calls in a loop.
python
import mas
from mas import KeyCode, Modifier

mas.key_press(KeyCode.BACK)                        # back button
mas.key_press(KeyCode.HOME)                        # home button
mas.key_press(KeyCode.ENTER)                       # submit a form
mas.key_press(KeyCode.POWER, duration_ms=3000)     # long press
mas.key_press(KeyCode.DELETE, repeat=10)           # delete 10 characters
mas.key_press(KeyCode.TAB, modifiers=[Modifier.SHIFT])
GroupMembers
Navigation and textBACK, HOME, MENU, APP_SWITCH, ENTER, TAB, SPACE, DELETE
HardwarePOWER, CAMERA, VOLUME_UP, VOLUME_DOWN, BRIGHTNESS_UP, BRIGHTNESS_DOWN
D-padDPAD_UP, DPAD_DOWN, DPAD_LEFT, DPAD_RIGHT, DPAD_CENTER
MediaMEDIA_PLAY, MEDIA_PAUSE, MEDIA_NEXT, MEDIA_PREVIOUS
NumbersNUM_0 to NUM_9

There is no ESCAPE member; use BACK. DELETE sends KEYCODE_DEL, which is backspace.

zoom_in and zoom_out

zoom_in(center=None, percent=50, duration_ms=0, steps=10) and zoom_out(center=None, percent=50, duration_ms=0, steps=10) perform two-finger pinch gestures. The gesture is synthesized through the emulator’s touch input device, which MAS detects automatically.

  • center: the (x, y) point the fingers work around. Defaults to the center of the screen.
  • percent: intensity from 1 to 100, as a share of the largest pinch that fits around the center. For zoom_in it is how far the fingers spread; for zoom_out it is how far apart they start.
  • duration_ms: total gesture time. The default 0 runs the gesture as fast as the device executes it.
  • steps: finger movement steps, from 2 to 100. More steps make a smoother gesture.
python
import mas

mas.zoom_in()                                    # zoom in at the screen center
mas.zoom_in(center=(540, 960), percent=80)       # strong zoom at a point
mas.zoom_out(center=(540, 960), percent=30)      # gentle zoom out

Humanized timing in ADB Python scripting

MAS sends taps and swipes exactly when you ask for them, so the rhythm of a macro is yours to design. Three habits keep it believable and robust.

  1. Let delay_ms do the waiting after a tap instead of stacking time.sleep calls. One second is a fair default; shorten it only where you know the app responds at once.
  2. Vary the pauses. A fixed 1000 ms between every action is a mechanical signature. random.uniform gives each pause a little spread.
  3. Wait for the screen, not the clock. After an action that changes the screen, look for the next template with find_object_retry rather than sleeping a fixed amount.
python
import random
import time
import mas

def pause(low=0.6, high=1.4):
    time.sleep(random.uniform(low, high))

mas.click(540, 1200, delay_ms=random.randint(700, 1300))
pause()
mas.swipe((540, 1500), (540, 600), duration_ms=random.randint(350, 600))

Example: type into a search field

Focus the field with a template match, replace any old query, submit with the keyboard, then wait for the results.

python
import mas
from mas import KeyCode

images = mas.images({"search_box": 201, "first_result": 202})

box = mas.find_object_retry(images.search_box, total_tries=3, time_sleep=2.0)
if box is None:
    mas.log("search box not on screen", level="warning")
    raise SystemExit(1)

mas.click(box.x, box.y, delay_ms=500)           # focus the field
mas.input_text("blue widgets", clear=True)      # replace any old query
mas.key_press(KeyCode.ENTER)

result = mas.find_object_retry(images.first_result, total_tries=5, time_sleep=1.5)
if result:
    mas.click(result.x, result.y)

Example: scroll until found

Search, swipe, search again, and give up after a fixed number of swipes so the macro never loops forever.

python
import mas

images = mas.images({"settings_row": 310})
size = mas.get_screen_size()
x = size.width // 2

match = None
for _ in range(8):                               # at most 8 swipes
    match = mas.find_object(images.settings_row, threshold=0.85)
    if match:
        break
    mas.swipe((x, int(size.height * 0.75)), (x, int(size.height * 0.25)), duration_ms=600)

if match:
    mas.click(match.x, match.y)
else:
    mas.log("row not found after 8 swipes", level="error")

In apps that expose an accessibility tree, scroll_to_element does the same loop for you by element text or resource id.

Errors

Every interaction call raises DeviceNotConnectedError when no device is bound to the run and CommandFailedError when the device rejects the gesture. Both are subclasses of RPCError, so one except mas.RPCError catches them. The full hierarchy is on Errors and exceptions.

Next steps

Related pages

Was this page helpful?

Questions? Ask in Discord