Improve applescript to open New Private Window with Safari

applescriptsafari

I made this AppleScript to use with the script tool. It can be saved as the application to launch from a click. I have to approve the application though in the Security edit tool.

This open the private browser by clicking the menu items. Then it closes the first window by looking for the unthinkable URL in the Window menu. It is working but flashy as the windows pop open and close.

I wish it can be improved by some way to allow clicking the shortcut then see that only the Safari window is launched in private mode without so much "macro" like appearance. Can you help improve this for me?

# Start or bring forward Safari window
tell application "Safari"
    activate
end tell

# Open a URL that cannot be found
set theURL to "http://localhost:38"
tell application "System Events"
    tell process "Safari"
        open location theURL
    end tell
end tell

# Launch a new private window
tell application "System Events"
    tell process "Safari"
        tell menu bar 1
            click menu bar item "File"
            tell menu "File"
                click menu item "New Private Window"
            end tell
        end tell
    end tell
end tell

# Close the first launcher window
tell application "System Events"
    tell process "Safari"
        tell menu bar 1
            click menu bar item "Window"
            tell menu "Window"
                click menu item "Failed to open page"
            end tell
        end tell
        tell menu bar 1
            click menu bar item "File"
            tell menu "File"
                click menu item "Close Window"
            end tell
        end tell
    end tell
end tell

Best Answer

Try the following:

tell application "Safari"
    activate
    delay 0.5
end tell
tell application "System Events"
    open location "http://localhost:38"
    delay 0.5
    keystroke "w" using command down
    keystroke "n" using {shift down, command down}
end tell

Now here is the code I'd choose to use as it checks to see if Safari is already open and if yes, just opens a new Private window. If not then it works as I believe you intended, which is to close the opening window and then open a new Private window.

on is_running(appName)
    tell application "System Events" to (name of processes) contains appName
end is_running

set isRunning to is_running("Safari")

if isRunning then
    tell application "Safari" to activate
    delay 0.5
    tell application "System Events" to keystroke "n" using {shift down, command down}
else
    tell application "Safari" to activate
    delay 1
    tell application "System Events"
        keystroke "w" using command down
        keystroke "n" using {shift down, command down}
    end tell
end if
  • Note: The value of the delay may need to be adjusted for the speed of your system. As coded the present values of delay work fine on my system. The value is in seconds or fractions thereof as a decimal value.

By the way, I see no need to open a new Tab to "a URL that cannot be found" as I believe my method herein, in the block of code directly above, achieves your intended goal, both quickly and without as you put it, "see that the Safari window is launched in private mode without so much "macro" like appearance.".


By the way, the code in your question could be reduced to the example below and would actually run a bit faster then the way you presently have it coded.

tell application "Safari"
    activate
end tell
tell application "System Events"
    open location "http://localhost:38"
    click menu item "New Private Window" of menu "File" of menu bar 1 of process "Safari"
    click menu item "Failed to open page" of menu "Window" of menu bar 1 of process "Safari"
    click menu item "Close Window" of menu "File" of menu bar 1 of process "Safari"
end tell

However my first (and second) example, at the top of this answer, acts directly without seeing the menus open and close as it's not using click events but key presses. Also while the condensed example of your code is just that, I wouldn't use it without appropriate delay statements where applicable.

In the end, I'd choose to use the second block of code shown in this answer.