macos-safari

SKILL.md

macOS Safari Automation

Control Safari on macOS using AppleScript via the osascript command.

Prerequisites

  • macOS with Safari installed
  • Automation permission granted to your terminal (System Settings > Privacy & Security > Automation)

Opening URLs

Open a URL in the current tab

osascript -e 'tell application "Safari" to set URL of current tab of front window to "https://example.com"'

Open a URL in a new tab

osascript -e 'tell application "Safari" to tell front window to set current tab to (make new tab with properties {URL:"https://example.com"})'

Open a URL in a new window

osascript -e 'tell application "Safari" to make new document with properties {URL:"https://example.com"}'

Open Safari and bring to front

osascript -e 'tell application "Safari" to activate'

Reading Page Content

Get the current page URL

osascript -e 'tell application "Safari" to return URL of current tab of front window'

Get the current page title

osascript -e 'tell application "Safari" to return name of current tab of front window'

Get page source (HTML)

osascript -e 'tell application "Safari" to return source of current tab of front window'

Get visible text content via JavaScript

osascript -e 'tell application "Safari" to do JavaScript "document.body.innerText" in current tab of front window'

Get a specific element's text

osascript -e 'tell application "Safari" to do JavaScript "document.querySelector(\"h1\").innerText" in current tab of front window'

Managing Tabs

List all tabs in the front window

osascript -e '
tell application "Safari"
    set tabList to ""
    set tabIndex to 1
    repeat with t in tabs of front window
        set tabList to tabList & tabIndex & ". [" & name of t & "] " & URL of t & linefeed
        set tabIndex to tabIndex + 1
    end repeat
    return tabList
end tell'

Get the number of open tabs

osascript -e 'tell application "Safari" to return count of tabs of front window'

Switch to a specific tab (by index, 1-based)

osascript -e 'tell application "Safari" to set current tab of front window to tab 3 of front window'

Close the current tab

osascript -e 'tell application "Safari" to close current tab of front window'

Close a specific tab by index

osascript -e 'tell application "Safari" to close tab 2 of front window'

Managing Windows

List all windows with their current tab info

osascript -e '
tell application "Safari"
    set winList to ""
    set winIndex to 1
    repeat with w in windows
        set winList to winList & winIndex & ". " & name of current tab of w & " — " & URL of current tab of w & linefeed
        set winIndex to winIndex + 1
    end repeat
    return winList
end tell'

Get the number of open windows

osascript -e 'tell application "Safari" to return count of windows'

Close the front window

osascript -e 'tell application "Safari" to close front window'

Executing JavaScript

Run arbitrary JavaScript in the current tab

osascript -e 'tell application "Safari" to do JavaScript "document.title" in current tab of front window'

Click a button or link

osascript -e 'tell application "Safari" to do JavaScript "document.querySelector(\"button.submit\").click()" in current tab of front window'

Fill in a form field

osascript -e 'tell application "Safari" to do JavaScript "document.querySelector(\"input[name=email]\").value = \"user@example.com\"" in current tab of front window'

Scroll to the bottom of the page

osascript -e 'tell application "Safari" to do JavaScript "window.scrollTo(0, document.body.scrollHeight)" in current tab of front window'

Wait for an element (poll with JavaScript)

osascript -e '
tell application "Safari"
    repeat 30 times
        set result to do JavaScript "document.querySelector(\".loaded\") !== null" in current tab of front window
        if result is "true" then exit repeat
        delay 1
    end repeat
end tell'

Bookmarks and History

Search bookmarks via plist conversion

# Bookmarks are stored in a plist; convert and search:
plutil -convert xml1 -o - ~/Library/Safari/Bookmarks.plist | grep -i "search term"

Search browsing history via SQLite

sqlite3 ~/Library/Safari/History.db "SELECT v.title, i.url, datetime(v.visit_time + 978307200, 'unixepoch', 'localtime') as visit_date FROM history_visits v JOIN history_items i ON v.history_item = i.id ORDER BY v.visit_time DESC LIMIT 20;"

Search history for a specific domain

sqlite3 ~/Library/Safari/History.db "SELECT v.title, i.url, datetime(v.visit_time + 978307200, 'unixepoch', 'localtime') as visit_date FROM history_visits v JOIN history_items i ON v.history_item = i.id WHERE i.url LIKE '%example.com%' ORDER BY v.visit_time DESC LIMIT 20;"

Search history by title

sqlite3 ~/Library/Safari/History.db "SELECT v.title, i.url, datetime(v.visit_time + 978307200, 'unixepoch', 'localtime') as visit_date FROM history_visits v JOIN history_items i ON v.history_item = i.id WHERE v.title LIKE '%search term%' ORDER BY v.visit_time DESC LIMIT 20;"

Common Use Cases

Open a page and extract its title

osascript -e '
tell application "Safari"
    make new document with properties {URL:"https://example.com"}
    delay 3
    return name of current tab of front window
end tell'

Save current page text to a file

osascript -e 'tell application "Safari" to do JavaScript "document.body.innerText" in current tab of front window' > /tmp/page-content.txt

Get all links on the current page

osascript -e 'tell application "Safari" to do JavaScript "Array.from(document.querySelectorAll(\"a[href]\")).map(a => a.href).join(\"\\n\")" in current tab of front window'

Take a screenshot of the current page (via screencapture)

osascript -e 'tell application "Safari" to activate'
sleep 0.5
screencapture -w /tmp/safari-screenshot.png

Troubleshooting

Issue Solution
"not authorized" error Grant Automation permission to terminal in System Settings
JavaScript returns empty Page may not be fully loaded; add delay before reading
Can't read History.db Grant Full Disk Access to terminal in System Settings
Bookmarks plist unreadable Use plutil -convert xml1 to convert to readable format
Safari not responding to AppleScript Ensure Safari is running; try tell application "Safari" to activate first

Technical Notes

  • AppleScript controls Safari through its scripting dictionary (no private APIs)
  • do JavaScript requires the "Allow JavaScript from Apple Events" setting enabled in Safari (Develop menu > Allow JavaScript from Apple Events)
  • History database uses Core Data timestamps (seconds since 2001-01-01)
  • Full Disk Access is required for reading History.db and Bookmarks.plist directly
  • Tab indices are 1-based in AppleScript
Weekly Installs
1
First Seen
5 days ago
Installed on
amp1
cline1
opencode1
cursor1
kimi-cli1
codex1