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)