Automatically clean up Safari cookies on macOS
Safari on macOS offers a means of deleting saved site-specific data (cache, cookies, etc.) under Settings > Private > Manage Website Data...
. Your options from there include searching for and deleting specfic content vs. vapourising everything. The latter option is the safest from a privacy and security perspective; but if you’re interested in focusing on specific cookies and other privacy leaks, you have to search one-by-one. The following script can be used to manage automate this.
Change the sitesToDelete
list to suit your preferences and run. Since the script uses SystemEvents
UI automation, the appropriate permissions are needed at the macOS System Settings level.
--
-- Created by: Alan Duncan
-- Created on: 2025-02-03
--
-- Copyright © 2025 OjisanSeiuchi, All Rights Reserved
--
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
property kDeleteKey : (ASCII character 127)
property kDownArrow : (ASCII character 31)
(*
waitForTableRows()
Description:
Repeatedly checks for the presence of table rows in a
Safari window until they appear or until a timeout
period is reached.
Purpose:
Used for UI automation when table content may load
asynchronously. This function ensures the table has
loaded before proceeding with other operations.
Returns:
- Integer: The number of rows found in the table
Throws:
- Error -128: If no rows appear within timeout period
Usage Example:
set rowCount to waitForTableRows()
if rowCount > 0 then
-- Process table rows
end if
*)
on waitForTableRows()
-- Maximum time to wait for rows to appear
set maxWaitSeconds to 10
-- Store start time for timeout calculation
set startTime to current date
repeat
try
tell application "System Events"
tell process "Safari"
-- Get row count from Privacy window table
-- Path: window->sheet->scroll->table->rows
set rowCount to count of (rows of ¬
table 1 of scroll area 1 of ¬
sheet 1 of window "Privacy")
-- Return count if rows are found
if rowCount > 0 then
return rowCount
end if
end tell
end tell
end try
-- Check for timeout
if ((current date) - startTime) > maxWaitSeconds then
-- Throw timeout error
¬
error "Timeout waiting for table rows" number -128
end if
-- Brief pause before next check
delay 0.25
end repeat
end waitForTableRows
(*
deleteSite(siteName)
Description:
Deletes all matching sites from Safari's Privacy window
by searching and bulk-selecting rows.
Parameters:
- siteName: The site name to search for and delete
Note: This script assumes the Privacy window is already
open and the search field is active.
*)
on deleteSite(siteName)
tell application "System Events"
tell process "Safari"
-- Type the site name to search
keystroke siteName
delay 0.5 -- Give UI time to update
tell sheet 1 of window "Privacy"
set rowCount to (count of rows of ¬
table 1 of scroll area 1)
if rowCount > 0 then
-- Check if Remove button is enabled
try
set removeEnabled to enabled of ¬
button "Remove"
on error
-- Button not found or other error
log "Remove button not found for site: " & siteName
-- Optional: can add specific error number if needed
error "Remove button not accessible" number -50
end try
-- Set tab count based on Remove state
if removeEnabled then
set tabCount to 4
else
set tabCount to 3
end if
-- Navigate back with Shift-Tab
repeat tabCount times
keystroke tab using shift down
delay 1
end repeat
delay 1
tell table 1 of scroll area 1
-- Select first row
click row 1
delay 0.2
-- Use Shift-Down to select the rest
repeat rowCount times
keystroke kDownArrow ¬
using shift down
delay 0.2
end repeat
end tell
delay 0.5
-- Click Remove button
click button "Remove"
delay 1.5
keystroke tab using shift down
end if
end tell
delay 1
-- Clear search field for next use
keystroke "a" using command down
delay 0.1
keystroke kDeleteKey
end tell
end tell
end deleteSite
on clearSafariData(sitesToDelete)
tell application "System Events"
tell process "Safari"
-- Open Safari preferences and Privacy
keystroke "," using command down
delay 0.25
click button "Privacy" of ¬
toolbar 1 of window 1
delay 0.25
-- Open Website Data manager
click button "Manage Website Data…" of ¬
group 1 of group 1 of window "Privacy"
-- Process sites
try
set numRows to waitForTableRows() of me
if numRows > 0 then
repeat with siteName in sitesToDelete
deleteSite(siteName) of me
delay 0.25
end repeat
end if
on error errMsg number errNum
-- Clean up windows before error
try
click button "Done" of ¬
sheet 1 of window "Privacy"
delay 0.25
keystroke "w" using command down
end try
-- Re-throw the error
error errMsg number errNum
end try
-- Close windows
click button "Done" of ¬
sheet 1 of window "Privacy"
delay 0.25
keystroke "w" using command down
end tell
end tell
end clearSafariData
tell application "Safari" to activate
set sitesToDelete to {"google", "facebook", ¬
"twitter", "instagram", "linkedin", ¬
"reddit", ".ru", "tiktok", "pinterest", ¬
"amazon", "youtube", "x.com", ".gov"}
clearSafariData(sitesToDelete)