Permissions

macOS protects some features behind privacy permissions. They are granted to the app running Python (Terminal, iTerm, VS Code, PyCharm…), not to Python itself, so a script can work in one terminal and not in another.

Feature

Permission

Where to enable it

macos.screenshot()

Screen Recording

System Settings › Privacy & Security › Screen & System Audio Recording

macos.notify()

Notifications for Script Editor

System Settings › Notifications › Script Editor

macos.keyboard typing and keys, macos.mouse moving, clicking and scrolling

Accessibility

System Settings › Privacy & Security › Accessibility

macos.camera.photo(), macos.camera.record()

Camera (asked the first time)

System Settings › Privacy & Security › Camera

macos.audio.record(), record_until_silence(), input_level(), videos with sound

Microphone (asked the first time)

System Settings › Privacy & Security › Microphone

macos.windows

Accessibility

System Settings › Privacy & Security › Accessibility

macos.hotkeys

Input Monitoring, and Accessibility to keep shortcuts from the app in front

System Settings › Privacy & Security › Input Monitoring

macos.screen.record()

Screen Recording (and Microphone with audio=True)

System Settings › Privacy & Security › Screen & System Audio Recording

macos.screen.find_text(), wait_for_text(), color_at(), Window.screenshot()

Screen Recording

System Settings › Privacy & Security › Screen & System Audio Recording

macos.mouse.click_text()

Screen Recording and Accessibility

System Settings › Privacy & Security

macos.keyboard.watch(), macos.mouse.watch()

Input Monitoring

System Settings › Privacy & Security › Input Monitoring

macos.finder.selection(), current_folder()

Automation of Finder (asked the first time)

System Settings › Privacy & Security › Automation

macos.apps.login_items(), add_login_item(), remove_login_item()

Automation of System Events (asked the first time)

System Settings › Privacy & Security › Automation

macos.time_machine.last_backup()

may need Full Disk Access

System Settings › Privacy & Security › Full Disk Access

macos.music

Automation of Music or Spotify (asked the first time)

System Settings › Privacy & Security › Automation

macos.browser

Automation of the browser (asked the first time); run_js() also needs the browser’s Allow JavaScript from Apple Events

System Settings › Privacy & Security › Automation

macos.screen.set_night_shift_schedule() with "sunset"

Location Services

System Settings › Privacy & Security › Location Services

macos.appearance.set_mode()

Automation of System Events (asked the first time)

System Settings › Privacy & Security › Automation

macos.bluetooth.connect(), disconnect(), set_power()

Bluetooth (may be asked the first time)

System Settings › Privacy & Security › Bluetooth

The other features (clipboard, appearance, apps, Keychain, speech, power, Shortcuts, Finder, volume, Spotlight, geocoding, dialogs, system info, Vision, images, PDFs, language, audio devices, sounds, network, brightness, the keyboard backlight, the mouse position, listing Bluetooth devices, Caps Lock, microphone volume, camera and microphone use, locking the screen, system events, scheduling scripts, the Dock, defaults, Finder and screenshot settings, disk images, Touch ID) need no permission. Watching folders needs none either, except that the Desktop, Documents and Downloads folders ask for access the first time, like any access to them.

Screen Recording

Without this permission macOS doesn’t fail: it returns a screenshot that shows only the wallpaper and the menu bar. pymacos checks first and raises PermissionDeniedError instead.

macos.screen.has_permission()       # check without prompting
macos.screen.request_permission()   # show the system prompt

After granting it in System Settings, restart the app running Python; macOS only applies the change to newly started processes.

Camera and microphone

The camera and the microphone need their own permission, which macOS asks for the first time a script uses them. Check or ask without taking anything:

macos.camera.has_permission()
macos.camera.request_permission()   # shows the prompt the first time
macos.audio.has_permission()        # the microphone
macos.audio.request_permission()

If the user denies it, macos.camera, macos.audio.record(), record_until_silence() and input_level() raise PermissionDeniedError; allow it again in System Settings › Privacy & Security, then restart the app running Python.

Accessibility

Sending keystrokes and mouse events lets a script control any app, so macOS asks for the Accessibility permission. Without it macOS silently drops the events; macos.keyboard and macos.mouse check first and raise PermissionDeniedError instead.

macos.keyboard.has_permission()       # check without prompting (the same for macos.mouse)
macos.keyboard.request_permission()   # show the system prompt

As with Screen Recording, restart the app running Python after allowing it.

Input Monitoring

macos.hotkeys listens to the keyboard for its shortcuts, which macOS treats as Input Monitoring; keeping a shortcut from the app in front also needs Accessibility. Without them, run() and wait() raise PermissionDeniedError.

macos.hotkeys.has_permission()       # check without prompting
macos.hotkeys.request_permission()   # show the system prompt

Restart the app running Python after allowing it.

Automation

macos.appearance.set_mode() asks System Events to switch the appearance, macos.apps.login_items() asks it for the login items, macos.finder.selection() asks Finder for the selected files, macos.music asks Music or Spotify to play, and macos.browser asks the browser for its tabs, so the first time macOS asks whether the app running Python may control them. If that’s denied, it raises PermissionDeniedError; allow it again in System Settings › Privacy & Security › Automation.

Notifications

Notifications are posted through AppleScript, so macOS attributes them to Script Editor.

When notifications for Script Editor are turned off, macOS drops them without an error, so macos.notify() raises PermissionDeniedError instead. Turn them on in System Settings › Notifications › Script Editor. If Script Editor isn’t listed there yet, open Script Editor, run display notification "hi" once and accept the prompt.

Also check that a Focus mode (such as Do Not Disturb) isn’t hiding them.

Keychain

Reading an item that another app created may make macOS ask the user to allow access. If the user denies it, macos.keychain raises PermissionDeniedError. Items created by your script can be read back by it without a prompt.