Automating Safari Configuration on macOS
Automating Safari configuration on macOS is essential for system administrators, IT departments, and developers who need to deploy standardized browser settings across multiple systems. This guide provides comprehensive scripts and techniques for managing Safari preferences programmatically.
Table of Contents
Why Automate Safari Configuration?
Common Use Cases
- Enterprise Deployment: Setting up standardized homepage and security settings across corporate devices
 - Development Environment: Configuring Safari for testing and development workflows
 - Kiosk Mode: Setting up dedicated browsing stations with specific configurations
 - System Administration: Managing browser settings remotely or in bulk
 - User Onboarding: Automating browser setup for new employees
 
Benefits of Automation
- Consistency: Ensure identical configurations across all systems
 - Efficiency: Reduce manual configuration time
 - Compliance: Meet corporate security and policy requirements
 - Scalability: Apply changes to hundreds of systems simultaneously
 
Basic Safari Configuration Script
Shell Script Approach
Here’s a comprehensive shell script for automating Safari configuration:
#!/bin/bash
# Quit Safari to ensure changes take effectosascript -e 'tell application "Safari" to quit'sleep 2
# Set homepage and window behavior using defaultsdefaults write com.apple.Safari HomePage -string "https://infopercept.com"defaults write com.apple.Safari NewWindowBehavior -int 0defaults write com.apple.Safari NewTabBehavior -int 0
# Force preferences to reloadkillall cfprefsd
# Reopen Safarisleep 2open -a Safarisleep 3
# Use AppleScript to configure homepage in Safari Preferencesosascript <<EOFtell application "System Events"    tell process "Safari"        delay 2        keystroke "," using command down -- Open Preferences        delay 2        -- Navigate to Homepage field        keystroke tab        keystroke tab        keystroke tab        keystroke tab        delay 1        -- Select existing text and replace with homepage URL        keystroke "a" using command down        delay 0.5        keystroke "https://infopercept.com"        delay 0.5        keystroke return        -- Close Preferences        keystroke "w" using command down    end tellend tellEOF
echo "✅ Safari homepage successfully set to https://infopercept.com"AppleScript-Only Approach
For a cleaner AppleScript-only implementation:
#!/usr/bin/osascript
-- Quit Safari to ensure preferences applytell application "Safari" to quitdelay 2
-- Set homepage and open behavior using shell commandsdo shell script "defaults write com.apple.Safari HomePage -string 'https://infopercept.com'"do shell script "defaults write com.apple.Safari NewWindowBehavior -int 0"do shell script "defaults write com.apple.Safari NewTabBehavior -int 0"do shell script "killall cfprefsd"
-- Open Safaridelay 2tell application "Safari" to activate
return "Safari homepage successfully set to https://infopercept.com"Advanced Configuration Options
Comprehensive Safari Settings
#!/bin/bash
# Safari Configuration Script# Configures multiple Safari preferences for enterprise deployment
HOMEPAGE_URL="https://your-company.com"COMPANY_NAME="Your Company"
echo "🔧 Configuring Safari for $COMPANY_NAME..."
# Quit Safariosascript -e 'tell application "Safari" to quit' 2>/dev/nullsleep 3
# Homepage and New Window/Tab Behaviordefaults write com.apple.Safari HomePage -string "$HOMEPAGE_URL"defaults write com.apple.Safari NewWindowBehavior -int 0  # Homepagedefaults write com.apple.Safari NewTabBehavior -int 0     # Homepage
# Security Settingsdefaults write com.apple.Safari AutoOpenSafeDownloads -bool falsedefaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabled -bool falsedefaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabledForLocalFiles -bool false
# Privacy Settingsdefaults write com.apple.Safari SendDoNotTrackHTTPHeader -bool truedefaults write com.apple.Safari WebKitStorageBlockingPolicy -int 1defaults write com.apple.Safari BlockStoragePolicy -int 1
# Developer Settings (Optional)defaults write com.apple.Safari IncludeDevelopMenu -bool truedefaults write com.apple.Safari WebKitDeveloperExtrasEnabledPreferenceKey -bool truedefaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled -bool true
# Search Engine Settingsdefaults write com.apple.Safari SearchProviderIdentifier -string "com.google.www"
# Appearance Settingsdefaults write com.apple.Safari ShowFavoritesBar -bool truedefaults write com.apple.Safari ShowSidebar -bool false
# Tab Settingsdefaults write com.apple.Safari TabCreationPolicy -int 1defaults write com.apple.Safari OpenNewTabsInFront -bool false
# Download Settingsdefaults write com.apple.Safari DownloadsClearingPolicy -int 1
# Force preferences daemon to reloadkillall cfprefsd
echo "✅ Safari configuration completed for $COMPANY_NAME"
# Optionally restart Safariread -p "Would you like to restart Safari now? (y/n): " -n 1 -rechoif [[ $REPLY =~ ^[Yy]$ ]]; then    open -a Safari    echo "🚀 Safari restarted with new configuration"fiSecurity-Focused Configuration
#!/bin/bash
# High-Security Safari Configuration# Suitable for corporate environments with strict security requirements
echo "🔒 Applying high-security Safari configuration..."
# Quit Safariosascript -e 'tell application "Safari" to quit' 2>/dev/nullsleep 2
# Security Settingsdefaults write com.apple.Safari AutoOpenSafeDownloads -bool falsedefaults write com.apple.Safari AutoFillFromAddressBook -bool falsedefaults write com.apple.Safari AutoFillPasswords -bool falsedefaults write com.apple.Safari AutoFillCreditCardData -bool falsedefaults write com.apple.Safari AutoFillMiscellaneousForms -bool false
# Disable plugins and Javadefaults write com.apple.Safari WebKitPluginsEnabled -bool falsedefaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2PluginsEnabled -bool falsedefaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabled -bool falsedefaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabledForLocalFiles -bool false
# Enable Do Not Trackdefaults write com.apple.Safari SendDoNotTrackHTTPHeader -bool true
# Block pop-upsdefaults write com.apple.Safari WebKitJavaScriptCanOpenWindowsAutomatically -bool falsedefaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically -bool false
# Prevent cross-site trackingdefaults write com.apple.Safari WebKitStorageBlockingPolicy -int 1defaults write com.apple.Safari BlockStoragePolicy -int 1
# Disable location servicesdefaults write com.apple.Safari SafariGeolocationPermissionPolicy -int 0
# Clear downloads list when Safari quitsdefaults write com.apple.Safari DownloadsClearingPolicy -int 1
# Force HTTPS where possible (if available)defaults write com.apple.Safari ForceHTTPS -bool true
killall cfprefsd
echo "✅ High-security Safari configuration applied"Enterprise Deployment Strategies
Mass Deployment Script
#!/bin/bash
# Enterprise Safari Deployment Script# Supports multiple users and system-wide configuration
SCRIPT_NAME="Safari Enterprise Configuration"LOG_FILE="/var/log/safari_config.log"CONFIG_VERSION="1.0"
# Logging functionlog_message() {    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"}
# Check if running as admincheck_admin() {    if [[ $EUID -ne 0 ]]; then        echo "This script must be run as administrator (sudo)"        exit 1    fi}
# Configure Safari for specific userconfigure_user_safari() {    local username=$1    local user_home="/Users/$username"
    if [[ ! -d "$user_home" ]]; then        log_message "ERROR: User home directory not found for $username"        return 1    fi
    log_message "Configuring Safari for user: $username"
    # Run configuration as the specific user    sudo -u "$username" defaults write com.apple.Safari HomePage -string "https://company-portal.com"    sudo -u "$username" defaults write com.apple.Safari NewWindowBehavior -int 0    sudo -u "$username" defaults write com.apple.Safari NewTabBehavior -int 0    sudo -u "$username" defaults write com.apple.Safari AutoOpenSafeDownloads -bool false    sudo -u "$username" defaults write com.apple.Safari SendDoNotTrackHTTPHeader -bool true
    log_message "Safari configuration completed for user: $username"}
# Main executionmain() {    log_message "Starting $SCRIPT_NAME v$CONFIG_VERSION"
    check_admin
    # Get all user accounts (excluding system accounts)    users=$(dscl . list /Users | grep -v "^_" | grep -v "daemon\|nobody\|root")
    for user in $users; do        # Skip if user UID is less than 500 (system accounts)        user_id=$(id -u "$user" 2>/dev/null)        if [[ $user_id -ge 500 ]] 2>/dev/null; then            configure_user_safari "$user"        fi    done
    # System-wide configuration using Configuration Profiles (if needed)    create_configuration_profile
    log_message "$SCRIPT_NAME completed successfully"}
# Create Configuration Profile for MDM deploymentcreate_configuration_profile() {    local profile_path="/tmp/safari_config.mobileconfig"
    cat > "$profile_path" << EOF<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict>    <key>PayloadContent</key>    <array>        <dict>            <key>PayloadDisplayName</key>            <string>Safari Settings</string>            <key>PayloadIdentifier</key>            <string>com.company.safari.settings</string>            <key>PayloadType</key>            <string>com.apple.Safari</string>            <key>PayloadUUID</key>            <string>$(uuidgen)</string>            <key>PayloadVersion</key>            <integer>1</integer>            <key>HomePage</key>            <string>https://company-portal.com</string>            <key>NewWindowBehavior</key>            <integer>0</integer>            <key>NewTabBehavior</key>            <integer>0</integer>            <key>AutoOpenSafeDownloads</key>            <false/>            <key>SendDoNotTrackHTTPHeader</key>            <true/>        </dict>    </array>    <key>PayloadDisplayName</key>    <string>Safari Configuration</string>    <key>PayloadIdentifier</key>    <string>com.company.safari</string>    <key>PayloadType</key>    <string>Configuration</string>    <key>PayloadUUID</key>    <string>$(uuidgen)</string>    <key>PayloadVersion</key>    <integer>1</integer></dict></plist>EOF
    log_message "Configuration profile created at: $profile_path"}
# Run main functionmain "$@"Remote Deployment via SSH
#!/bin/bash
# Remote Safari Configuration Deployment# Deploy Safari settings to multiple macOS systems via SSH
TARGETS_FILE="macos_targets.txt"CONFIG_SCRIPT="safari_config.sh"SSH_USER="admin"SSH_KEY="~/.ssh/id_rsa"
# Read target systems from fileif [[ ! -f "$TARGETS_FILE" ]]; then    echo "Error: Target systems file '$TARGETS_FILE' not found"    echo "Create a file with one hostname/IP per line"    exit 1fi
# Deploy to each targetwhile IFS= read -r target; do    [[ -z "$target" ]] && continue
    echo "🔄 Deploying to: $target"
    # Copy script to target system    scp -i "$SSH_KEY" "$CONFIG_SCRIPT" "$SSH_USER@$target:/tmp/"
    # Execute script on target system    ssh -i "$SSH_KEY" "$SSH_USER@$target" "chmod +x /tmp/$CONFIG_SCRIPT && sudo /tmp/$CONFIG_SCRIPT"
    if [[ $? -eq 0 ]]; then        echo "✅ Successfully configured: $target"    else        echo "❌ Failed to configure: $target"    fi
    # Clean up    ssh -i "$SSH_KEY" "$SSH_USER@$target" "rm -f /tmp/$CONFIG_SCRIPT"
    echo "---"done < "$TARGETS_FILE"
echo "🎉 Remote deployment completed"Troubleshooting and Validation
Validation Script
#!/bin/bash
# Safari Configuration Validation Script# Verifies that Safari settings have been applied correctly
echo "🔍 Validating Safari configuration..."
# Function to check a settingcheck_setting() {    local key=$1    local expected=$2    local domain=${3:-com.apple.Safari}
    current=$(defaults read "$domain" "$key" 2>/dev/null)
    if [[ "$current" == "$expected" ]]; then        echo "✅ $key: $current (correct)"        return 0    else        echo "❌ $key: $current (expected: $expected)"        return 1    fi}
# Check critical settingsecho "Checking Safari preferences..."
check_setting "HomePage" "https://infopercept.com"check_setting "NewWindowBehavior" "0"check_setting "NewTabBehavior" "0"check_setting "AutoOpenSafeDownloads" "0"check_setting "SendDoNotTrackHTTPHeader" "1"
# Check if Safari is configured to show the homepageecho ""echo "🏠 Homepage configuration:"homepage=$(defaults read com.apple.Safari HomePage 2>/dev/null)echo "Current homepage: $homepage"
# Check Safari versionecho ""echo "ℹ️ Safari information:"safari_version=$(osascript -e 'tell application "Safari" to version' 2>/dev/null)echo "Safari version: $safari_version"
# Check if configuration profiles are installedecho ""echo "📋 Configuration profiles:"profiles -P 2>/dev/null | grep -i safari || echo "No Safari configuration profiles found"
echo ""echo "🎯 Validation completed"Common Issues and Solutions
Issue: Settings Don’t Persist
# Force preferences to reload and persistkillall cfprefsddefaults synchronizeIssue: AppleScript UI Automation Fails
# Enable accessibility permissions for Terminal/script# Check System Preferences > Security & Privacy > Privacy > AccessibilityIssue: Preferences Revert After User Login
# Use Configuration Profiles for persistent settingssudo profiles install -path safari_config.mobileconfigDebugging Script
#!/bin/bash
# Safari Configuration Debug Script# Helps diagnose configuration issues
echo "🔧 Safari Configuration Debug Information"echo "========================================"
# Check Safari installationif [[ -d "/Applications/Safari.app" ]]; then    echo "✅ Safari is installed"    safari_version=$(defaults read /Applications/Safari.app/Contents/Info.plist CFBundleShortVersionString)    echo "   Version: $safari_version"else    echo "❌ Safari is not installed"    exit 1fi
# Check current userecho ""echo "👤 Current user: $(whoami)"echo "   User ID: $(id -u)"
# Check Safari preferencesecho ""echo "⚙️ Current Safari preferences:"defaults read com.apple.Safari 2>/dev/null | head -20
# Check running processesecho ""echo "🔄 Safari-related processes:"ps aux | grep -i safari | grep -v grep
# Check system integrityecho ""echo "🛡️ System integrity:"if command -v csrutil &> /dev/null; then    csrutil statuselse    echo "System Integrity Protection status unknown"fi
# Check accessibility permissionsecho ""echo "♿ Accessibility permissions:"sqlite3 "/Library/Application Support/com.apple.TCC/TCC.db" \    "SELECT client, auth_value FROM access WHERE service='kTCCServiceAccessibility';" 2>/dev/null || \    echo "Cannot check accessibility permissions (may require admin privileges)"
echo ""echo "🎯 Debug information collection completed"Best Practices
Security Considerations
- Validate Scripts: Always test scripts in a controlled environment before deployment
 - User Permissions: Run with appropriate privileges (avoid unnecessary root access)
 - Input Validation: Validate all user inputs and file paths
 - Secure Distribution: Use secure channels for script distribution
 - Audit Logging: Maintain logs of configuration changes
 
Error Handling
#!/bin/bash
# Robust Safari Configuration with Error Handling
set -euo pipefail  # Exit on error, undefined vars, pipe failures
LOGFILE="/var/log/safari_config.log"HOMEPAGE_URL="https://company.com"
# Logging functionlog() {    echo "$(date '+%Y-%m-%d %H:%M:%S'): $*" | tee -a "$LOGFILE"}
# Error handlererror_exit() {    log "ERROR: $1"    exit 1}
# Validation functionvalidate_url() {    local url=$1    if [[ ! "$url" =~ ^https?:// ]]; then        error_exit "Invalid URL format: $url"    fi}
# Main configuration functionconfigure_safari() {    log "Starting Safari configuration"
    validate_url "$HOMEPAGE_URL"
    # Quit Safari with error handling    if ! osascript -e 'tell application "Safari" to quit' 2>/dev/null; then        log "Safari was not running or failed to quit"    fi
    sleep 2
    # Apply settings with error checking    if ! defaults write com.apple.Safari HomePage -string "$HOMEPAGE_URL"; then        error_exit "Failed to set homepage"    fi
    if ! defaults write com.apple.Safari NewWindowBehavior -int 0; then        error_exit "Failed to set new window behavior"    fi
    # Force preferences reload    killall cfprefsd || log "Warning: Failed to reload preferences daemon"
    log "Safari configuration completed successfully"}
# Run main functionconfigure_safariTesting Framework
#!/bin/bash
# Safari Configuration Test Suite
TEST_RESULTS=()
# Test functionrun_test() {    local test_name=$1    local test_command=$2
    echo "Running test: $test_name"
    if eval "$test_command"; then        echo "✅ PASS: $test_name"        TEST_RESULTS+=("PASS: $test_name")    else        echo "❌ FAIL: $test_name"        TEST_RESULTS+=("FAIL: $test_name")    fi}
# Test suiteecho "🧪 Safari Configuration Test Suite"echo "================================="
run_test "Safari Installation" "[[ -d '/Applications/Safari.app' ]]"run_test "Homepage Setting" "[[ \$(defaults read com.apple.Safari HomePage 2>/dev/null) == 'https://company.com' ]]"run_test "New Window Behavior" "[[ \$(defaults read com.apple.Safari NewWindowBehavior 2>/dev/null) == '0' ]]"run_test "Security Settings" "[[ \$(defaults read com.apple.Safari AutoOpenSafeDownloads 2>/dev/null) == '0' ]]"
# Results summaryecho ""echo "📊 Test Results Summary:"echo "======================="for result in "${TEST_RESULTS[@]}"; do    echo "$result"done
# Count resultspass_count=$(printf '%s\n' "${TEST_RESULTS[@]}" | grep -c "PASS" || true)fail_count=$(printf '%s\n' "${TEST_RESULTS[@]}" | grep -c "FAIL" || true)
echo ""echo "Passed: $pass_count"echo "Failed: $fail_count"
if [[ $fail_count -eq 0 ]]; then    echo "🎉 All tests passed!"    exit 0else    echo "⚠️ Some tests failed"    exit 1fiConclusion
Automating Safari configuration on macOS provides significant benefits for system administrators and IT departments. By using the scripts and techniques outlined in this guide, you can:
- Standardize browser settings across multiple systems
 - Improve security posture with consistent configuration
 - Reduce manual effort in deployment and maintenance
 - Ensure compliance with corporate policies
 
Key Takeaways
- Use 
defaultscommand for persistent preference settings - Combine shell scripts and AppleScript for comprehensive automation
 - Implement proper error handling and validation
 - Test thoroughly before enterprise deployment
 - Document configurations for maintenance and troubleshooting
 
Whether you’re managing a small team or deploying across hundreds of systems, these automation techniques will help you maintain consistent, secure Safari configurations efficiently.
Remember to always test automation scripts in a controlled environment before deploying to production systems.