Search

Guides

How to Make a Bot for Any Android Game in MAS

How to make a bot for any Android game in Macro Automation Studio: install one from the Marketplace, ask MAS Agent, or script it in Python on BlueStacks.

  • Windows
  • Mac
  • Emulator
  • Cloud device
  • Phone
  • Studio
  • Python SDK
Beginner Updated 7 min read
On this page
  1. Before you start
  2. How to make a bot for an Android game: three ways
  3. Install one from the Marketplace
  4. Ask MAS Agent
  5. Build it in Python
  6. Automating Android games with Python
  7. 1. List what the bot must see
  8. 2. Create the project
  9. 3. Capture templates in Asset Lab
  10. 4. Capture an OCR region
  11. 5. Write the loop
  12. 6. Run it and read the logs
  13. 7. Schedule it
  14. 8. Run it on a device group
  15. A complete example bot
  16. Tips that keep a bot stable
  17. What can go wrong
  18. The button is never found
  19. The counter reads the wrong number
  20. The bot stops at once on the second day
  21. Clicks land beside the button

This tutorial shows how to make a bot for any Android game in Macro Automation Studio (MAS), from an installed game to a bot that runs on a schedule, on one account or on several. MAS bots work from the screen: they find buttons by image, read counters with OCR, and tap with humanized timing. It is for first-time bot builders on Windows or Mac.

How to make a bot for any game preview

How to make a bot for any game

Before you start

  • MAS is installed and you are signed in with the free trial or a plan. See Install MAS.
  • The game runs on a device MAS can drive: an emulator on this computer, a cloud device, or your own phone. See Devices.
  • The device sits in a device group and its card shows Stopped, not Error. The Getting started page walks through adding one.
  • For the Python path you need nothing else. MAS ships its own Python environment with the mas package.

How to make a bot for an Android game: three ways

Install one from the Marketplace

The fastest route when someone has already built a bot for your game.

  1. Open Marketplace and search for the game.
  2. Open the listing and click Download. The bot appears under Macros.
  3. In Device Groups, open your group, choose the bot in the device’s Macro selector and click Start.

The full walkthrough with screenshots is How to Run a Macro from the Marketplace. Ready-made bots exist for Whiteout Survival, Kingshot and Last Asylum: Plague.

Ask MAS Agent

The no-code route for a game with no listing.

  1. Open Agent and pick the device.
  2. Describe the routine in one sentence, including when it should stop, and click Author.
  3. Answer when the agent asks. It stops and asks instead of guessing.
  4. When the macro passes 3 validation runs, click Add to My Macros.

Authoring spends AI credits; running the finished macro costs none. The result is a normal Python project you can open and edit. See MAS Agent.

Build it in Python

Full control over every decision the bot makes. The rest of this page is this path.

Automating Android games with Python

1. List what the bot must see

Play the routine once by hand and write down every screen it touches. That means the button you press, the popups that interrupt, the counter that shows your energy, and the message that means you are done. Each item becomes a template image or an OCR region. A bot that knows its stop state never runs blind.

2. Create the project

  1. Open Macros and click Create New Project.
  2. Choose Code-Based, set Target Device to mobile, name the project and click Create Project.
  3. Open the project. The Code Editor shows src/app.py, the file MAS runs.

3. Capture templates in Asset Lab

  1. Start the game on the device and go to the screen with the button.
  2. In the Code Editor, open the Assets panel and click Open Asset Helper. Asset Lab opens on the live screen.
  3. Crop a tight rectangle around the button and save it. It lands in your Image Library with a numeric ID.
  4. Repeat for the popup close button, the confirm button and the “out of energy” message.
  5. Back in the Assets panel, use Copy ID on each image and paste the IDs into mas.images at the top of your script.

Keep crops small and distinctive. A whole screen only matches that exact screen; a button matches wherever the button appears. Templates can be jpg, png, gif or webp, up to 10 MB each. The Asset Lab page covers the tool in detail.

4. Capture an OCR region

  1. In Asset Lab, draw a box around the counter you want to read.
  2. Run the live OCR test and tighten the box until the digits come back clean.
  3. Copy the coordinates into a Region(x1, y1, x2, y2) in your script.

The OCR guide explains the segmentation modes and colour conversion if the text reads badly.

5. Write the loop

The loop below is the shape every game bot shares. Each line maps to an SDK call:

  • find_object_retry looks for the button up to total_tries=3 times, time_sleep=2.0 seconds apart, and returns None when nothing matches.
  • click(x, y, delay_ms=1000) taps the centre of the match and waits a second for the game to react.
  • read_text(region, psm=7) reads the counter as a single line.
  • time.sleep(random.uniform(0.8, 2.0)) adds a human pause between rounds.
  • mas.save and mas.retrieve keep the round counter, so a stopped run resumes where it left off.
  • Stop conditions end the loop. The example uses five: a maximum number of rounds, a time budget, the “out of energy” template, a low counter, and too many misses in a row.

6. Run it and read the logs

Pick the device in the Code Editor and click Run (F5). Every mas.log line appears in the run console. Stop is Shift+F5. Fix one thing at a time: when a template is not found, recrop it before touching the logic.

7. Schedule it

  1. Open Scheduler and click Create New Schedule.
  2. Fill in Name, pick the Macro and the Emulator Port, set Date and Time.
  3. Set Recurrence to Daily and click Create Schedule.

The app must stay open; the scheduler runs inside it. See Scheduler and Loops and scheduling.

8. Run it on a device group

Add every account’s emulator instance as a device in one group, assign the bot to each device and click Start All. Per-device values such as the account name come from a settings profile. See Multi-instance farming.

A complete example bot

Replace the image IDs and the region with the ones you captured. The script farms a resource until energy runs low, a time budget passes, or thirty rounds are done, and it survives a restart.

python
import random
import sys
import time

import mas
from mas import Region

images = mas.images({
    "attack_button": 101,
    "confirm_button": 102,
    "close_popup": 103,
    "out_of_energy": 104,
})

ENERGY_REGION = Region(x1=380, y1=20, x2=520, y2=60)
TASK = "farm_bot"
MAX_ROUNDS = 30
TIME_BUDGET_S = 20 * 60
MIN_ENERGY = 10


def pause(low=0.8, high=2.0):
    time.sleep(random.uniform(low, high))


def read_energy():
    result = mas.read_text(region=ENERGY_REGION, psm=7)
    digits = "".join(ch for ch in result.text if ch.isdigit())
    return int(digits) if digits else None


def clear_popups():
    popup = mas.find_any_object([images.close_popup, images.confirm_button])
    if popup:
        mas.click(popup.x, popup.y, delay_ms=800)
        return True
    return False


def main():
    rounds = mas.retrieve(TASK).get("rounds", 0)
    misses = 0
    started = time.monotonic()
    mas.log(f"Starting at round {rounds}")

    while rounds < MAX_ROUNDS:
        if time.monotonic() - started > TIME_BUDGET_S:
            mas.log("Time budget reached", level="warning")
            break
        if clear_popups():
            continue
        if mas.find_object(images.out_of_energy):
            mas.log("Out of energy, stopping")
            break
        energy = read_energy()
        if energy is not None and energy < MIN_ENERGY:
            mas.log(f"Energy {energy} is below {MIN_ENERGY}, stopping")
            break
        button = mas.find_object_retry(images.attack_button, total_tries=3, time_sleep=2.0)
        if button is None:
            misses += 1
            mas.log(f"Attack button not found ({misses})", level="warning")
            if misses >= 5:
                mas.log("Giving up after 5 misses", level="error")
                sys.exit(2)
            continue
        misses = 0
        mas.click(button.x, button.y, delay_ms=1000)
        pause()
        rounds += 1
        mas.save(TASK, {"rounds": rounds})
        mas.log(f"Round {rounds} of {MAX_ROUNDS}")

    if rounds >= MAX_ROUNDS:
        mas.clear(TASK)
    mas.log(f"Finished with {rounds} rounds")


if __name__ == "__main__":
    main()

sys.exit(2) marks the run as failed, so a webhook subscribed to macro.failed hears about it. A clean exit reports macro.completed. See Webhooks.

Tips that keep a bot stable

  • Resolution. Templates and regions belong to the resolution and DPI you captured them on. Keep every device that runs the bot on the same setting; the emulator guides use 540x960 in portrait at 240 DPI as the baseline.
  • Template hygiene. Crop only the button, never the background around it. Recrop after a game update changes the art. When a button has two looks, capture both and search with find_any_object.
  • Stop conditions. Every loop needs at least two: a counter or time budget, and a screen state that means “done”. A bot without them runs until you notice.
  • Slow down. A pause of one to two seconds between rounds costs little and looks less mechanical.
  • Log the decision, not the tap. mas.log("Energy 8, stopping") tells you why a run ended; a log of a hundred clicks does not.

What can go wrong

The button is never found

The crop is too large, the threshold is too strict for the art, or the device runs at a different resolution than the one you captured on. Recrop tighter, then try threshold=0.7 on the call. The image recognition guide has the full checklist.

The counter reads the wrong number

The region includes a neighbouring icon, or the text is light on a dark background. Tighten the box in Asset Lab and pass color_conversion=ColorConversion.BLACK_WHITE. The OCR guide shows how to check the confidence.

The bot stops at once on the second day

The stored counter is already at the limit. The example clears storage when it reaches MAX_ROUNDS; if you changed that, call mas.clear("farm_bot") once from a scratch script.

Clicks land beside the button

The emulator’s resolution or DPI changed after capture, or the window is not in portrait. Reset the emulator display to the capture setting and recapture anything that still misses.

No automation tool is 100% risk-free, so automate responsibly and at your own discretion.

Next steps

Related pages

Was this page helpful?

Questions? Ask in Discord