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
Open 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 effect
osascript -e 'tell application "Safari" to quit'
sleep 2
# Set homepage and window behavior using defaults
defaults write com.apple.Safari HomePage -string "https://infopercept.com"
defaults write com.apple.Safari NewWindowBehavior -int 0
defaults write com.apple.Safari NewTabBehavior -int 0
# Force preferences to reload
killall cfprefsd
# Reopen Safari
sleep 2
open -a Safari
sleep 3
# Use AppleScript to configure homepage in Safari Preferences
osascript <<EOF
tell 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 tell
end tell
EOF
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 apply
tell application "Safari" to quit
delay 2
-- Set homepage and open behavior using shell commands
do 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 Safari
delay 2
tell 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 Safari
osascript -e 'tell application "Safari" to quit' 2>/dev/null
sleep 3
# Homepage and New Window/Tab Behavior
defaults write com.apple.Safari HomePage -string "$HOMEPAGE_URL"
defaults write com.apple.Safari NewWindowBehavior -int 0 # Homepage
defaults write com.apple.Safari NewTabBehavior -int 0 # Homepage
# Security Settings
defaults write com.apple.Safari AutoOpenSafeDownloads -bool false
defaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabled -bool false
defaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabledForLocalFiles -bool false
# Privacy Settings
defaults write com.apple.Safari SendDoNotTrackHTTPHeader -bool true
defaults write com.apple.Safari WebKitStorageBlockingPolicy -int 1
defaults write com.apple.Safari BlockStoragePolicy -int 1
# Developer Settings (Optional)
defaults write com.apple.Safari IncludeDevelopMenu -bool true
defaults write com.apple.Safari WebKitDeveloperExtrasEnabledPreferenceKey -bool true
defaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled -bool true
# Search Engine Settings
defaults write com.apple.Safari SearchProviderIdentifier -string "com.google.www"
# Appearance Settings
defaults write com.apple.Safari ShowFavoritesBar -bool true
defaults write com.apple.Safari ShowSidebar -bool false
# Tab Settings
defaults write com.apple.Safari TabCreationPolicy -int 1
defaults write com.apple.Safari OpenNewTabsInFront -bool false
# Download Settings
defaults write com.apple.Safari DownloadsClearingPolicy -int 1
# Force preferences daemon to reload
killall cfprefsd
echo "β
Safari configuration completed for $COMPANY_NAME"
# Optionally restart Safari
read -p "Would you like to restart Safari now? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
open -a Safari
echo "π Safari restarted with new configuration"
fi
Security-Focused Configuration
#!/bin/bash
# High-Security Safari Configuration
# Suitable for corporate environments with strict security requirements
echo "π Applying high-security Safari configuration..."
# Quit Safari
osascript -e 'tell application "Safari" to quit' 2>/dev/null
sleep 2
# Security Settings
defaults write com.apple.Safari AutoOpenSafeDownloads -bool false
defaults write com.apple.Safari AutoFillFromAddressBook -bool false
defaults write com.apple.Safari AutoFillPasswords -bool false
defaults write com.apple.Safari AutoFillCreditCardData -bool false
defaults write com.apple.Safari AutoFillMiscellaneousForms -bool false
# Disable plugins and Java
defaults write com.apple.Safari WebKitPluginsEnabled -bool false
defaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2PluginsEnabled -bool false
defaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabled -bool false
defaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabledForLocalFiles -bool false
# Enable Do Not Track
defaults write com.apple.Safari SendDoNotTrackHTTPHeader -bool true
# Block pop-ups
defaults write com.apple.Safari WebKitJavaScriptCanOpenWindowsAutomatically -bool false
defaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically -bool false
# Prevent cross-site tracking
defaults write com.apple.Safari WebKitStorageBlockingPolicy -int 1
defaults write com.apple.Safari BlockStoragePolicy -int 1
# Disable location services
defaults write com.apple.Safari SafariGeolocationPermissionPolicy -int 0
# Clear downloads list when Safari quits
defaults 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 function
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}
# Check if running as admin
check_admin() {
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as administrator (sudo)"
exit 1
fi
}
# Configure Safari for specific user
configure_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 execution
main() {
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 deployment
create_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 function
main "$@"
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 file
if [[ ! -f "$TARGETS_FILE" ]]; then
echo "Error: Target systems file '$TARGETS_FILE' not found"
echo "Create a file with one hostname/IP per line"
exit 1
fi
# Deploy to each target
while 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 setting
check_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 settings
echo "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 homepage
echo ""
echo "π Homepage configuration:"
homepage=$(defaults read com.apple.Safari HomePage 2>/dev/null)
echo "Current homepage: $homepage"
# Check Safari version
echo ""
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 installed
echo ""
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 persist
killall cfprefsd
defaults synchronize
Issue: AppleScript UI Automation Fails
# Enable accessibility permissions for Terminal/script
# Check System Preferences > Security & Privacy > Privacy > Accessibility
Issue: Preferences Revert After User Login
# Use Configuration Profiles for persistent settings
sudo profiles install -path safari_config.mobileconfig
Debugging Script
#!/bin/bash
# Safari Configuration Debug Script
# Helps diagnose configuration issues
echo "π§ Safari Configuration Debug Information"
echo "========================================"
# Check Safari installation
if [[ -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 1
fi
# Check current user
echo ""
echo "π€ Current user: $(whoami)"
echo " User ID: $(id -u)"
# Check Safari preferences
echo ""
echo "βοΈ Current Safari preferences:"
defaults read com.apple.Safari 2>/dev/null | head -20
# Check running processes
echo ""
echo "π Safari-related processes:"
ps aux | grep -i safari | grep -v grep
# Check system integrity
echo ""
echo "π‘οΈ System integrity:"
if command -v csrutil &> /dev/null; then
csrutil status
else
echo "System Integrity Protection status unknown"
fi
# Check accessibility permissions
echo ""
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 function
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S'): $*" | tee -a "$LOGFILE"
}
# Error handler
error_exit() {
log "ERROR: $1"
exit 1
}
# Validation function
validate_url() {
local url=$1
if [[ ! "$url" =~ ^https?:// ]]; then
error_exit "Invalid URL format: $url"
fi
}
# Main configuration function
configure_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 function
configure_safari
Testing Framework
#!/bin/bash
# Safari Configuration Test Suite
TEST_RESULTS=()
# Test function
run_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 suite
echo "π§ͺ 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 summary
echo ""
echo "π Test Results Summary:"
echo "======================="
for result in "${TEST_RESULTS[@]}"; do
echo "$result"
done
# Count results
pass_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 0
else
echo "β οΈ Some tests failed"
exit 1
fi
Conclusion
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
defaults
command 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.