Skip to content
Back to the docs

Writing a Python script

The rules of an AppsMobs script: built-in functions, images next to the script, log, input, finish, the safety check and good habits.

Last reviewed 2 November 2026

By the end of this page you will know how to write a robust Python script for AppsMobs: where to put images, how to print and ask things, what the safety check refuses, and how to avoid scripts that crash overnight. ⏱ 15 minutes of reading.

Before you start

  • You ran a first script: Your first script in 10 minutes.
  • You do not need to know programming: the "Python in two minutes" section below gives the minimum.

The three rules of an AppsMobs script

  1. A script is an ordinary .py file. You write it in the Playground's Code mode and it is saved in Documents\AppsMobs\Scripts.
  2. No import for AppsMobs functions. tap, tap_image, wait_text, log… are already there. Do not write from appsmobs import ...: it does not exist.
  3. The phone is provided automatically. Functions act on the device chosen in Run on. You write tap(540, 1200), not tap(client, 540, 1200).

All functions are listed in the function reference. While you type in the editor, function names are also suggested, and the Function reference panel (More actions, Tools group) shows their entries without leaving the editor.

A complete example

log("Start")

if tap_image("play.png", timeout=20):
    random_wait(1, 2)
    if wait_text("Welcome", timeout=15):
        log("Welcome screen reached")
    else:
        log("No welcome screen", "WARNING")
else:
    log("Play button not found", "ERROR")

press_home()

Line by line: we look for and tap play.png (20 seconds at most), wait a random moment, wait for the text "Welcome", write down what happened, then go back to the home screen.

Where to put images

An image is a .png file: the capture of a button or an icon. To make one, follow the "Capture the phone screen" step of Your first script (Device screenshot, crop in Paint).

AppsMobs looks for the file in this order:

  1. if you give a full path, as is;
  2. the script's folder;
  3. Documents\AppsMobs\Scripts\img.

So you just write the name: tap_image("play.png"). An unsaved script has no folder: save it first, or put the image in Scripts\img.

If the file cannot be found, the script stops with (the message is in French):

image introuvable : play.png (cherchée dans le dossier du script et dans Scripts/img)

Choosing good images

Crop the button as tight as possible, avoid areas that change (counters, dates) and take the capture on a device with the same resolution as the one that will run the script. If recognition fails, lower conf a little (conf=0.7) or limit the searched area with region.

log: write in the Output

log("Step 1 done")
log("Careful, this is slow", "WARNING")
log("Cannot continue", "ERROR")

log(message, level='INFO') writes a timestamped line in the Playground's Output panel and in the Console. The level (INFO, WARNING, ERROR…) is used to filter in the Console. It is your number one diagnostic tool: put a log before and after every important step.

input: ask a question

name = input("What name for the backup?")
log(f"I will use {name}")

The script stops and waits. In the Playground, the question shows in the Output, with a Type your answer… field and a Send button; from another source, it shows in the Console, where you type the answer then press Enter. Only use input if someone is there to answer: a script started by a scheduled task would wait forever.

finish: stop cleanly

if not wait_image("home.png", timeout=30):
    log("Home never reached, stopping", "ERROR")
    finish()

finish() ends the script immediately and marks it as finished. Without it, the script ends by itself after its last line.

Python in two minutes

counter = 0                       # a variable
name = "Button"                   # text, between quotes

for i in range(3):                # repeat 3 times (i is 0, 1, 2)
    counter = counter + 1
    log(f"Round {counter}")       # f"..." inserts values into text

while counter < 5:                # repeat while the condition is true
    counter += 1

if counter >= 5:                  # decide
    log("At least five")
else:
    log("Fewer than five")

def tap_twice(x, y):              # your own function
    tap(x, y)
    wait(0.5)
    tap(x, y)

tap_twice(540, 1200)

Two beginner traps: the lines indented by 4 spaces under for, if, while, def are the content of the block (do not mix spaces and tabs), and wait(2) waits 2 seconds, not 2 milliseconds.

The safety check

In Code mode, AppsMobs analyses your script before every run. It notably refuses:

  • import of system modules: os, subprocess, sys, shutil, socket, ctypes, pickle, marshal, multiprocessing, threading;
  • calls to eval(...), exec(...), compile(...) and to os.system, subprocess.run…;
  • obfuscation tricks (__import__, getattr(__builtins__, ...), base64 decoding to run code…).

"Harmless" modules (time, random, math, re, json, datetime) pass. For everything else, you get the Execution blocked window:

For your security, this script cannot be executed.
Use Blocks mode (No-Code) for better security.

followed by a reason (Analyse AST: Code dangereux ou obfusqué détecté, in French whatever the app language) and the detail, for example the line number.

How to get out of it:

  1. Read the detail: it says which line is the problem.
  2. Remove the import or the call. AppsMobs functions do not need any, and most needs (waiting, repeating, deciding) are done in plain Python.
  3. If the window shows up while your code is "innocent", look for a syntax mistake: the detail then contains Erreur de syntaxe.

Developer mode (More actions, Developer mode) relaxes some restrictions and shows Developer mode enabled - Restrictions are relaxed. It is for people who know what they run; never run code whose origin you do not know.

What the safety check does not guarantee

It is a safety net, not a guarantee. It does not replace reading: do not run a script you found or that an AI generated without having read it. Blocks mode is stricter: it only accepts AppsMobs functions.

Good habits

1. Wait for a condition, not a delay

# Fragile: if loading takes 6 seconds, it breaks
tap_image("play.png")
wait(5)
tap_image("level1.png")

# Solid: wait for what matters
tap_image("play.png")
if wait_image("level1.png", timeout=30):
    tap_image("level1.png")

wait_image and wait_text return as soon as the condition is true, and give up after timeout seconds without crashing.

2. Always test the result of a wait

wait_image, wait_text and tap_image do not stop the script when they fail: they return None or False. If what follows depends on it, check with if, and stop with finish() or take another branch.

3. Vary the pauses

random_wait(1, 3)    # between 1 and 3 seconds, at random

A perfectly regular rhythm is more fragile than a slightly varied one, and it leaves the app time to react. random_wait() with no value waits between 0.35 and 0.8 seconds.

4. Never loop forever without saying so

tries = 0
while tries < 50:
    tries += 1
    if tap_image("next.png", timeout=5):
        break
    swipe_up()
else:
    log("Button never found after 50 tries", "ERROR")

A while True loop with no exit runs until you click Stop. Always bound the number of rounds, or the time.

5. Leave the device in a clean state

Close what you opened and go back to the home screen, so the next run starts from a known situation:

close_app("com.android.chrome")
press_home()

6. Retry what can fail

for attempt in range(3):
    open_app("com.android.chrome")
    if wait_text("Chrome", timeout=20):
        break
    log(f"Attempt {attempt + 1} failed, restarting", "WARNING")
    restart_app("com.android.chrome")

7. Several devices: one copy per device

When you run a script on several devices, each one runs its own copy: variables are not shared. To repeat a script at a fixed time or on several devices, use Automation.

Managing your scripts

In the Playground, the More actions menu groups:

  • File: New script (Ctrl + N), Open a script… (Ctrl + O), Save as…, Version history, Export the script.
  • Edit: Undo (Ctrl + Z), Redo (Ctrl + Y), Find / replace (Ctrl + F), Tidy the code.
  • Tools: Device screenshot, Function reference, Keyboard shortcuts, Developer mode.
  • View: Output panel, Side panel, Icon bar, Full screen.

The icon bar on the left gives access to Files, Blocks, Docs, Assistant and Generate.

If you need a different Python than the one bundled with AppsMobs, the Custom Python Path is set in Settings, Advanced section.

Not working?

What you seeCauseWhat to do
For your security, this script cannot be executed.Safety check: forbidden import or call, or a syntax mistake.Read the detail, remove the import; see above.
No device connected: plug a phone in (USB debugging on) or start an emulator, then press Run again.No device.Connect a phone or an emulator.
image introuvable : x.png (cherchée dans le dossier du script et dans Scripts/img)File misplaced or misnamed.See "Where to put images".
NameError: name 'x' is not definedFunction does not exist or typo.Compare with the reference. Names are English and lowercase.
IndentationErrorIrregularly indented spaces.Use 4 spaces everywhere; Tidy the code helps.
SyntaxErrorMissing parenthesis, quote or colon.Re-read the line shown.
Stopped with an error after …The script crashed.Read the end of the Output and the Console.
The script waits and does nothinginput(), or a long wait.Answer in the Output / Console, or click Stop (Shift + F5).

What next

Stuck on a step? Ask on Discord, someone has probably hit it before.Ask on Discord