flowchart TD
A["your script types and clicks"] --> B{"is the intended window focused?"}
B -->|no| C["the input goes somewhere else entirely"]
B -->|yes| D["the action lands where you meant"]
E["FAILSAFE = True"] --> F["slam the mouse into a corner to abort"]
G["pyautogui.PAUSE"] --> H["a delay after every call, so you can watch it"]
I["locateOnScreen before clicking"] --> J{"found?"}
J -->|no| K["stop -- do not click blind coordinates"]
J -->|yes| D
C --> L["this is why you test on a machine you can afford to disturb"]
Warning
GUI automation can click/delete the wrong things.
- keep failsafes
- prefer APIs when possible
Basic controls
import pyautogui
print(pyautogui.size())
print(pyautogui.position())Failsafe
By default, moving the mouse to the top-left corner raises pyautogui.FailSafeException.
Keep it enabled.
What pyautogui is
pyautogui controls the mouse and keyboard, takes screenshots, and shows simple dialogs. Install it with pip install pyautogui. It works on Windows, macOS, and Linux, but with conditions: on macOS you must give your terminal or editor Accessibility (and Screen Recording) permission in System Settings, and on Linux it needs an X11 session, so it does not work under Wayland on many setups.
It sends input to the whole desktop. It has no idea which program or button it is affecting, and that is why this page begins with warnings. The rest of the section builds on the four groups of calls introduced here.
- Screen:
size(),position(),screenshot(), and the locate functions. - Mouse:
moveTo,click,dragTo,scroll. - Keyboard:
write,press,hotkey. - Dialogs:
alert,confirm,prompt.
The three safety settings
import pyautogui
pyautogui.FAILSAFE = True # default: mouse to the top-left corner raises FailSafeException
pyautogui.PAUSE = 0.5 # default is 0.1: seconds to wait after every pyautogui call
width, height = pyautogui.size()
x, y = pyautogui.position()
print(f"screen {width}x{height}, mouse at ({x}, {y})")
try:
pyautogui.moveTo(width // 2, height // 2, duration=1)
except pyautogui.FailSafeException:
print("Stopped by the failsafe corner")FAILSAFE is your emergency brake. A runaway script that is typing or clicking is hard to stop, because it also controls the mouse you would use to close it. Slamming the cursor into the corner stops it. Do not turn it off. PAUSE slows every call so that you can watch what is happening and the target program can keep up. Raise it while you develop, and lower it only when the script is proven.
Coordinates and scaling
The origin (0, 0) is the top-left, and y grows downwards. On displays with scaling (common on laptops), the numbers pyautogui uses may differ from what your screenshot shows, so always read positions from pyautogui itself, not from an image editor. Multiple monitors extend the coordinate space, and a monitor to the left of the primary one has negative x values.
Habits for writing these scripts
- Start with a countdown so you can put the right window in front.
- Check before acting. Confirm the window title or find the image, and stop if it is not there.
- Log each step, so you can see how far the script got.
- Keep scripts short. A long chain of blind clicks fails at step 40, and the rest happen in the wrong place.
- Use a test account or spare machine for the first runs.
Common mistakes
- Turning off
FAILSAFEto make a script "smoother". - Running on an unfocused window.
- Ignoring OS permissions and wondering why nothing happens on macOS.
- Building the script on one monitor setup and running on another.
- Working on the computer while the script runs. Your own mouse and keyboard fight with it.
Check your understanding
What is the purpose of pyautogui.FAILSAFE?
It raises FailSafeException when the cursor reaches the corner, which is the way to stop a runaway script that controls the mouse.
Show answer
A — Moving the mouse to the top-left corner aborts the script — It raises FailSafeException when the cursor reaches the corner, which is the way to stop a runaway script that controls the mouse.
What does pyautogui.PAUSE do?
PAUSE is a global delay after each call. It gives you time to watch and gives the target program time to react.
Show answer
B — Adds a delay after every pyautogui call — PAUSE is a global delay after each call. It gives you time to watch and gives the target program time to react.
Where is the pixel (0, 0)?
The origin is at the top-left, with x to the right and y downward.
Show answer
C — The top-left corner of the primary screen — The origin is at the top-left, with x to the right and y downward.