PyAutoGUIは、Pythonからマウスとキーボードを操作して画面上の手作業を自動化するライブラリです。pip install pyautoguiで入り、Windows・macOS・Linuxで動きます。作者はAl Sweigart氏で、ライセンスはBSDです。
現行版は2023年5月24日公開の0.9.54で、その後PyPIに新しい版は出ていません。一方、依存ライブラリのPyScreezeは更新が続いていて、2023年11月の0.1.30で画像検索の既定動作が変わり、2024年8月に1.0.1まで上がっています。この記事では、OS別のインストール手順と主要関数の使い方に加えて、0.9.54を今のPythonで使うと詰まる3点(Pillowが入らない・画像が見つからないと例外になる・日本語が入力されない)を、Python 3.11〜3.13での実行結果とソースコードで確認した内容に沿って説明します。
まとめ:PyAutoGUIでできることと導入の要点
- できること:マウスの移動・クリック・ドラッグ・スクロール、キー入力とショートカット、スクリーンショット、画面上の画像検索、簡易ダイアログ表示。
- 導入:
pip install pyautogui。Python 3.12以降ではPillowが自動で入らないため、スクリーンショットと画像検索を使うならpip install pillowを追加します。 - 画像検索の既定が変わった:PyScreeze 0.1.30以降と組み合わせると、
locateOnScreen()は画像が見つからないとNoneではなくpyautogui.ImageNotFoundExceptionを送出します。if pos is Noneで書いた古いコードは動きません。 - 日本語は
write()で打てない:キー名にない文字は黙って無視されます。pyperclipでクリップボードに入れ、hotkey('ctrl', 'v')で貼り付けます。 - 止め方を先に覚える:マウスを画面の四隅へ動かすと
FailSafeExceptionで停止します。クリックやキー入力の関数の後には、既定で0.1秒の待ち(PAUSE)が入ります。 - 向かない場面:ブラウザ操作はSeleniumやPlaywright、Windowsアプリのボタン操作はUI Automation系のほうが座標のずれに強く、壊れにくい構成になります。
PyAutoGUIでできること・できないこと
PyAutoGUIは、OSに「マウスがここへ動いた」「このキーが押された」という入力イベントを送るだけのライブラリです。アプリの内部構造(ボタンの名前やHTMLの要素)は見ていません。そのため、どのアプリでも座標さえ分かれば操作できる反面、ウィンドウの位置や解像度が変わると同じスクリプトが別の場所をクリックします。
| やりたいこと | 主な関数 | 補足 |
|---|---|---|
| マウス移動 | moveTo()・move() |
絶対座標・相対移動 |
| クリック | click()・doubleClick()・rightClick() |
回数・ボタン指定可 |
| ドラッグ | dragTo()・drag() |
押したまま移動 |
| スクロール | scroll()・hscroll() |
横はmacOS・Linux |
| キー入力 | press()・write() |
英数字・記号のみ |
| 同時押し | hotkey()・hold() |
ショートカット再現 |
| 座標の取得 | position()・size() |
主モニタ基準 |
| 画面キャプチャ | screenshot() |
要Pillow |
| 画像検索 | locateOnScreen() |
要Pillow |
| ダイアログ | alert()・confirm()・prompt() |
PyMsgBox経由 |
できないことも公式に明記されています。READMEには「PyAutoGUIは現在プライマリモニタでしか動かない」とあり、2台目のモニタでのマウス操作は「OSとバージョンによって動くこともあれば動かないこともある」という扱いです。モバイルOSは対象外で、最小化されたウィンドウや画面ロック中の操作もできません。
PyAutoGUIのインストール手順(Windows・macOS・Linux)
PyPIのpyautoguiを入れると、PyMsgBox・PyTweening・PyScreeze・PyGetWindow・MouseInfoが一緒に入ります。macOSではpyobjc-coreとpyobjc-framework-Quartz、Linuxではpython3-Xlibも自動で追加されます。
python -m pip install pyautogui pillow pyperclip
python -c "import pyautogui; print(pyautogui.__version__)"
2行目で0.9.54と表示されれば導入は完了です。以下、OSごとの差分です。
Windowsでのインストールと表示スケールの扱い
Windowsは追加パッケージなしで動きます。複数のPythonを入れている場合は、py -3.12 -m pip install pyautoguiのようにPythonランチャーで入れ先を指定すると、「インストールしたのにModuleNotFoundError」を避けられます。
表示スケールを125%や150%にしている環境でも、座標は実際のピクセル単位で扱われます。0.9.54のWindows実装は読み込み時にSetProcessDPIAware()を呼んでいます。ソースのコメントによれば、スケーリングで画面の解像度を誤って報告する問題への対処です。
macOSでのインストールとアクセシビリティ権限
macOSではpython3 -m pip install pyautoguiで入ります。インストール自体は通っても、最初の実行でマウスやキーが動かないことがあります。原因はOSの権限で、スクリプトを起動するアプリ(ターミナル・iTerm2・VS Codeなど)に「システム設定 → プライバシーとセキュリティ → アクセシビリティ」の許可が要ります。スクリーンショットと画像検索には、同じ画面の「画面収録とシステムオーディオ録音」の許可も必要です。
macOSのスクリーンショットは、PyScreezeが呼ぶPillowのImageGrab.grab()が内部でscreencaptureコマンドを実行して取得します。画面を取得できない状態で実行すると、subprocess.CalledProcessError(screencapture -xが終了コード1)で止まります。今回の検証環境(macOSのバックグラウンド実行)でもこのエラーになりました。ショートカットはctrlではなくcommandで指定します。
LinuxでのインストールとX11の前提
Linuxの実装はXlibでX Window Systemへ入力を送ります。0.9.54のソースは読み込み時に環境変数DISPLAYの画面へ接続するため、DISPLAYが無いSSHセッションやcronからimport pyautoguiすると、その時点でKeyErrorになります。操作対象のX11デスクトップにログインした同じユーザーで実行してください。SSHやcronから接続する場合は、対象セッションのDISPLAYの値とXサーバーへの認証情報が必要で、DISPLAY=:0の指定だけでは接続できるとは限りません。
公式のインストール手順は、Debian・Ubuntu系で次のパッケージの追加を求めています。python3-tkはMouseInfoの座標表示ウィンドウ、scrotはスクリーンショットに使われます。
sudo apt-get install scrot python3-tk python3-dev
python3 -m pip install pyautogui pillow
Ubuntuの既定セッションはWaylandです。PyScreezeはXDG_SESSION_TYPEかWAYLAND_DISPLAYでWaylandを検知するとスクリーンショットをgnome-screenshot経由に切り替えますが、マウスとキーの入力はXlib経由のままです。「Ubuntu on Xorg」が用意されている環境では、ログイン時に選択してX11セッションで実行します。Ubuntu 25.10のリリースノートは「Ubuntu on X.org」セッションの提供終了を明記しており、25.10以降の標準デスクトップではこの切り替えができません。
Python 3.12以降でのPillowの追加インストール
0.9.54とPyScreeze 1.0.1をPython 3.12以降へ新規導入するときは、Pillowの依存指定に注意が必要です。PyScreeze 1.0.1のsetup.pyは、Pillowの依存をpython_version == "3.11"までしか書いていません。そのため3.12以降ではpip install pyautoguiでPillowが入りません。2026年9月28日にmacOS上のPython 3.11・3.12・3.13の新規仮想環境で依存パッケージの導入を確認したところ、3.11ではPillow 12.3.0が入り、3.12と3.13では入りませんでした。
この状態でもimport pyautoguiは通り、マウスとキーボードの関数は使えます。スクリーンショットや画像検索を呼んだ瞬間に初めて、次の例外が出ます。
pyautogui.PyAutoGUIException: PyAutoGUI was unable to import pyscreeze. (This is likely because you're running a version of Python that Pillow (which pyscreeze depends on) doesn't support currently.) Please install this module to enable the function you tried to call.
メッセージは「PillowがそのPythonに未対応」と読めますが、実際は入っていないだけで、pip install pillowで解消します。
PyAutoGUIのマウス操作:座標の調べ方と移動・クリック
座標は画面左上が(0, 0)で、右へ行くほどx、下へ行くほどyが増えます。基準はプライマリモニタで、pyautogui.size()がその幅と高さを返します。
position()による現在のマウス座標の取得
クリック位置を決めるには、まず目的の場所の座標を知る必要があります。次のスクリプトを動かしたままマウスを目的の位置へ動かすと、座標が1行に上書き表示されます。Ctrl+Cで終了します。
import pyautogui
print('画面サイズ:', pyautogui.size())
try:
while True:
x, y = pyautogui.position()
print(f'X={x:5d} Y={y:5d}', end='\r', flush=True)
pyautogui.sleep(0.05)
except KeyboardInterrupt:
print()
PyAutoGUIに同梱のMouseInfoを使う方法もあります。pyautogui.mouseInfo()を呼ぶと、座標とその位置のRGB値を表示するウィンドウが開き、値をクリップボードへコピーできます。Linuxではpython3-tkが必要です。
moveTo()とclick()による移動・クリック
import pyautogui
pyautogui.moveTo(500, 300, duration=0.5) # 0.5秒かけて(500, 300)へ移動
pyautogui.move(0, 100) # 今の位置から下へ100px
pyautogui.click() # 今の位置を左クリック
pyautogui.click(800, 400, clicks=2, interval=0.2) # 指定座標をダブルクリック
pyautogui.rightClick(800, 400) # 右クリック
durationを省略すると瞬時に移動します。0.9.54ではMINIMUM_DURATIONが0.1秒に設定されていて、0.1秒以下を指定した場合も瞬時移動になります。ホバーでメニューが開くアプリのように、動きを見て反応する画面ではdurationを0.3〜0.5秒ほど取ると取りこぼしが減ります。
dragTo()とscroll()によるドラッグ・スクロール
pyautogui.dragTo(900, 500, duration=1, button='left') # 押したまま(900, 500)へ
pyautogui.scroll(-5) # 下へ5ノッチ
pyautogui.scroll(5, x=600, y=400) # (600, 400)へ移動してから上へ5ノッチ
pyautogui.hscroll(3) # 右へ(macOS・Linuxのみ)
scroll()の引数は画素数ではなく「ホイールの刻み数」です。1刻みで動く量はOSとアプリの設定で変わるため、スクロール後の位置に依存する処理は、画像検索で目印を探し直すほうが安定します。
PyAutoGUIのキーボード操作:press・write・hotkeyの使い分け
キー名はpyautogui.KEYBOARD_KEYSに定義されていて、0.9.54では194個です。pyautogui.isValidKey('enter')で、名前が有効かどうかを確かめられます。
press()とwrite()による単独キー・文字列の入力
pyautogui.press('enter') # 1回押す
pyautogui.press('tab', presses=3, interval=0.1) # 3回押す
pyautogui.press(['left', 'left', 'backspace']) # 順に押す
pyautogui.write('Hello, PyAutoGUI', interval=0.05) # 1文字ずつ入力
write()とtypewrite()は同じ関数です。ソースにはwrite = typewriteとあり、コメントで「1.0でwrite()がtypewrite()を置き換える」と予告されています。新しく書くコードはwrite()に揃えておくと移行が楽です。
hotkey()とhold()による同時押し・キー保持
hotkey()は、渡したキーを順に押し下げ、逆順に離します。hotkey('ctrl', 'shift', 'esc')ならCtrl→Shift→Escの順に押し、Esc→Shift→Ctrlの順に離します。修飾キーを押したまま複数の操作をしたいときは、コンテキストマネージャのhold()を使います。
pyautogui.hotkey('ctrl', 'c') # コピー(macOSは 'command', 'c')
pyautogui.hotkey('alt', 'tab') # ウィンドウ切り替え
with pyautogui.hold('shift'): # Shiftを押したまま
pyautogui.press(['right'] * 5) # 右へ5文字選択
pyautogui.keyDown('ctrl') # 押し下げと解放を個別に書く方法
pyautogui.click(300, 200)
pyautogui.keyUp('ctrl')
keyDown()を使う場合は、途中で例外が起きるとkeyUp()に届かず、キーが押しっぱなしになります。hold()はwithブロックを例外で抜けた場合もキーを解放するので、こちらを優先してください。ただし、0.9.54では解放前にもフェイルセーフを確認するため、画面の四隅で停止した場合にはキーが解放されないことがあります。
pyperclipによる日本語の貼り付け
write('こんにちは')は何も入力しません。エラーも出ません。0.9.54のWindows・macOS・Linuxの各実装は、キー名の対応表に無い文字を受け取ると何もせずに戻るからです(pyautogui.isValidKey('あ')はFalseを返します)。日本語はクリップボード経由で入れます。Linuxでコピー機能が見つからないというエラーが出る場合は、X11環境ならxclipまたはxselなどのクリップボード用コマンドも導入してください。
import pyautogui
import pyperclip
pyperclip.copy('2026年9月分の売上データ')
pyautogui.hotkey('ctrl', 'v') # macOSは hotkey('command', 'v')
pyperclipはMouseInfoの依存として自動で入りますが、自分のコードで使うならpip install pyperclipで明示しておきます。IMEがオンのまま英字をwrite()すると変換候補として入力されるため、英字を打つ前にIMEをオフにする手順も忘れずに入れてください。
PyAutoGUIの画像認識:スクリーンショットとlocateOnScreen
座標の固定値に頼らず、「このボタンの画像が画面のどこにあるか」を探してクリックできます。スクリーンショットと画像検索はPyScreezeの機能で、PyAutoGUIからそのまま呼べます。
im = pyautogui.screenshot() # 画面全体(PIL.Image)
pyautogui.screenshot(region=(0, 0, 400, 300)).save('area.png') # 左上400x300を保存
box = pyautogui.locateOnScreen('ok_button.png') # Box(left, top, width, height)
x, y = pyautogui.locateCenterOnScreen('ok_button.png')
pyautogui.click(x, y)
ファイルへの保存は、戻り値の画像に.save()を呼んで行います。PyScreeze 1.0.1のソースでは、macOSでscreenshot('area.png')のようにファイル名を渡しても保存処理に使われず、Linuxでregionと一緒に渡すと切り出す前の全画面が保存されます。
探す画像(ok_button.png)は、実行する画面と同じ解像度・同じ表示倍率で切り出しておきます。倍率が違う画面で切り出した画像は、見た目が同じでもピクセルが一致しません。macOSのRetinaディスプレイでは、pyautogui.size()の値とscreenshot().sizeの値が一致するか先に確かめてください。一致しない場合は、見つかった座標をその倍率で割ってからクリックします。
PyScreeze 0.1.30以降の画像未検出時の例外
古い解説には「見つからなければNoneが返る」と書かれていますが、今の組み合わせでは違います。挙動を決めているのはPyAutoGUIではなくPyScreezeのUSE_IMAGE_NOT_FOUND_EXCEPTIONで、PyAutoGUI 0.9.54はPyScreezeの例外をpyautogui.ImageNotFoundExceptionに包み直して送出します。PyAutoGUIを0.9.54に固定したままPyScreezeだけ入れ替えて、画面にない画像をlocate()させたところ、0.1.28と0.1.29はNoneを返し、0.1.30と1.0.1は例外を送出しました。PyScreezeの変更履歴にも、この既定値の変更は「後方互換性を壊す変更」と書かれています。
公式ドキュメントのスクリーンショットのページには「0.9.41から例外を送出する」とあります。ただ、実際に既定で例外になるのは、PyScreeze 0.1.30(2023年11月10日公開)以降と組み合わせたときです。今pip install pyautoguiすればPyScreeze 1.0.1が入るので、新しく作る環境では例外になると考えてください。
try:
x, y = pyautogui.locateCenterOnScreen('ok_button.png')
except pyautogui.ImageNotFoundException:
print('OKボタンが見つかりません')
else:
pyautogui.click(x, y)
既存のスクリプトを直す時間がないなら、先頭でpyautogui.useImageNotFoundException(False)を呼ぶと、以前と同じくNoneを返す動作に戻せます(こちらも実行して確認済みです)。ただしNoneをx, y =で受けると別のTypeErrorになるだけなので、長く使うスクリプトは例外で書き直すほうが原因を追いやすくなります。
confidenceによる一致判定のしきい値調整とOpenCVの導入
アンチエイリアスや配色の微差で完全一致しないときは、confidence=0.9のように一致度の下限を指定します。この引数はOpenCVが入っているときだけ使えます。未導入で指定するとNotImplementedError: The confidence keyword argument is only available if OpenCV is installed.になります。
python -m pip install opencv-python
OpenCV版の検索はcv2.matchTemplateを使い、正規化相関の値がconfidenceを超えた位置を一致とみなします。値の意味と下げすぎたときの誤検出はテンプレートマッチングとは?matchTemplateの仕組みと類似度指標の選び方を解説で詳しく扱っています。grayscale=Trueで白黒化して比べると検索が速くなりますが、色だけが違うボタン(有効・無効の切り替えなど)は区別できなくなります。
暴走を止めるFAILSAFEとPAUSEの設定
座標を間違えたスクリプトは、止めようとしたマウスを奪い返して動き続けます。PyAutoGUIはこれに備えて2つの仕組みを既定で有効にしています。
pyautogui.FAILSAFE = True:関数を呼んだ時点でマウスがプライマリモニタの四隅のどこかにあると、pyautogui.FailSafeExceptionを送出して止まります。pyautogui.PAUSE = 0.1:click()やwrite()などの入力操作関数は、実行後に0.1秒待ちます。その間にマウスを四隅へ移動すると、次の関数を呼んだ時点のフェイルセーフ確認で停止します。position()や画像検索のように、この待機と確認を持たない関数もあります。macOSではDARWIN_CATCH_UP_TIMEとして、さらに0.01秒が加わります。
FAILSAFEをFalseにするのは避けてください。ソースのdocstringもFailSafeExceptionを「捕まえるべきではない」例外と定めています。アプリの反応が遅くて操作を取りこぼすなら、PAUSEを0.3〜0.5秒に上げるか、画面の変化を画像検索で待つ処理を挟みます。time.sleep()を増やすより、「目印が出るまで待つ」ほうが処理時間も安定します。
PyAutoGUIの実用例:画像でボタンを探して入力・保存する
ここまでの関数を組み合わせた例です。この例は、「新規」ボタンのクリック後に件名欄へフォーカスが移り、保存ショートカットが使えるアプリを前提とします。実行前に対象アプリを表示し、同じ表示倍率で切り出したnew_button.pngを作業ディレクトリへ置いてください。座標を固定で書かないので、ウィンドウの位置が変わっても動きます。
import sys
import time
import pyautogui
import pyperclip
pyautogui.PAUSE = 0.3
MOD = 'command' if sys.platform == 'darwin' else 'ctrl' # macOSはcommand
def wait_and_click(image, timeout=10):
"""画像が画面に出るまで待ってから中心をクリックする"""
end = time.monotonic() + timeout
while time.monotonic() < end:
try:
x, y = pyautogui.locateCenterOnScreen(image, confidence=0.9)
except pyautogui.ImageNotFoundException:
time.sleep(0.5)
continue
pyautogui.click(x, y)
return
raise TimeoutError(f'{image} が待機時間の目安 {timeout} 秒を超えても見つかりません')
wait_and_click('new_button.png')
pyperclip.copy('2026年9月 月次報告')
pyautogui.hotkey(MOD, 'v')
pyautogui.hotkey(MOD, 's')
confidenceを使っているのでopencv-pythonが必要です。画像の加工(切り出し・縮小)にはPillowとは?Pythonで画像を加工する使い方をコード付きで解説の手順が使えます。
PyAutoGUIを選ばない方がよい場面と代替ツール
PyAutoGUIが一番強いのは、APIもアクセシビリティ情報も持たない古い業務アプリやゲーム画面を、見た目だけを頼りに動かす場面です。逆に、操作対象の中身を読み取れる手段があるなら、そちらを使うべきです。固定座標による操作はウィンドウ位置の変更でずれ、画像検索による操作は表示倍率やテーマの変更で一致しなくなることがあります。
| 操作対象 | 選ぶツール | 理由 |
|---|---|---|
| Webブラウザ | Selenium・Playwright | 要素をIDやセレクタで指定 |
| Windowsアプリ | pywinauto・UI Automation | ボタン名で操作 |
| Excelのデータ処理 | openpyxl・pandas | 画面を開かずに処理 |
| 社内の定型業務全体 | Power Automate Desktop等 | 非開発者も保守できる |
| 中身が読めないアプリ | PyAutoGUI | 画面の見た目で操作 |
ブラウザ操作をPyAutoGUIで書くのは失敗パターンの典型です。ページの読み込み時間や広告の差し込みでボタンの位置が毎回変わり、画面を最小化すれば動きません。Seleniumなら要素の出現を待ってから操作でき、ヘッドレスで裏でも動きます。仕組みはSeleniumとは?WebDriverの仕組みと4系の実行手順・ツール選定を解説、書き方はSeleniumの使い方|Selenium 4でWebDriverの手動設定が不要になった書き方を参照してください。
Windowsのデスクトップアプリも、多くはUI Automationでボタンや入力欄を名前で取れます。PythonからはpywinautoのUIAバックエンドで扱えます。仕組みはUIAutomationとは|Windows UI自動化の仕組みとC#・Python・VBA実装で解説しています。PyAutoGUIを、これらで要素が取れなかった部分に絞ると、座標や画像の変更に合わせて修正する箇所を減らせます。
座標を人が決める代わりにAIが画面から推定する方式もあります。動作原理はスクリーンショット解析でPCを操作するComputer Useの動作原理にまとめています。
よくある質問
PyAutoGUIで何ができますか?
マウスの移動・クリック・ドラッグ・スクロール、キー入力とショートカット、スクリーンショット、画面上の画像検索、簡易ダイアログの表示ができます。操作対象のアプリの種類は問いませんが、動くのはプライマリモニタで、画面に見えている範囲だけです。
pip install pyautoguiをしたのにスクリーンショットでエラーになるのはなぜですか?
Python 3.12以降では、依存するPyScreeze 1.0.1がPillowを自動で入れないためです。「PyAutoGUI was unable to import pyscreeze」と出たらpip install pillowを実行してください。confidence引数を使うならopencv-pythonも必要です。
Pythonでマウスカーソルを動かすには?
pyautogui.moveTo(x, y)で絶対座標へ、pyautogui.move(dx, dy)で今の位置から相対的に動かします。duration=0.5を付けると0.5秒かけて動きます。移動先の座標はpyautogui.position()で調べられます。
Macで動かないのはなぜですか?
スクリプトを起動するアプリにアクセシビリティの許可が無いと、マウスとキーの操作が効きません。スクリーンショットと画像検索には「画面収録とシステムオーディオ録音」の許可も要ります。ショートカットはctrlではなくcommandで指定します。
PyAutoGUIで日本語を入力できますか?
write()では入力できません。対応表に無い文字は、エラーを出さずに無視されます。pyperclip.copy('日本語')でクリップボードへ入れ、pyautogui.hotkey('ctrl', 'v')(macOSは'command')で貼り付けてください。