Absent since although it’s possible to get the window’s title, it’s not possible to get its URL (it used to be, before version 3.6
). It’s possible via hacky ways that consist of sending keystrokes, but those can be unreliable. This bug is being tracked in Bugzilla.
-
-
Save vitorgalvao/5392178 to your computer and use it in GitHub Desktop.
-- AppleScript -- | |
-- This example is meant as a simple starting point to show how to get the information in the simplest available way. | |
-- Keep in mind that when asking for a `return` after another, only the first one will be output. | |
-- This method is as good as its JXA counterpart. | |
-- Webkit variants include "Safari", "Webkit", "Orion". | |
-- Specific editions are valid, including "Safari Technology Preview". | |
-- "Safari" Example: | |
tell application "Safari" to return name of front document | |
tell application "Safari" to return URL of front document | |
-- "Webkit" Example: | |
tell application "Webkit" to return name of front document | |
tell application "Webkit" to return URL of front document | |
-- Chromium variants include "Google Chrome", "Chromium", "Opera", "Vivaldi", "Brave Browser", "Microsoft Edge", "Arc". | |
-- Specific editions are valid, including "Google Chrome Canary", "Microsoft Edge Dev". | |
-- "Google Chrome" Example: | |
tell application "Google Chrome" to return title of active tab of front window | |
tell application "Google Chrome" to return URL of active tab of front window | |
-- "Chromium" Example: | |
tell application "Chromium" to return title of active tab of front window | |
tell application "Chromium" to return URL of active tab of front window | |
-- This example returns both the title and URL for the frontmost tab of the active browser, separated by a newline. | |
-- For shorter code inclusive of all editions, only the start of the application name is checked. | |
-- Keep in mind that to be able to use a variable in `tell application` — via `using terms from` — we’re basically requiring that referenced browser to be available on the system. | |
-- That means that to use this on "Google Chrome Canary" or "Chromium", "Google Chrome" needs to be installed. Same for other browsers. | |
-- This method also does not exit with a non-zero exit status when the frontmost application is not a supported browser. | |
-- For the aforementioned reasons, this method is inferior to its JXA counterpart. | |
tell application "System Events" to set frontApp to name of first process whose frontmost is true | |
if (frontApp starts with "Safari") or (frontApp starts with "Webkit") or (frontApp starts with "Orion") then | |
using terms from application "Safari" | |
tell application frontApp to set currentTabTitle to name of front document | |
tell application frontApp to set currentTabURL to URL of front document | |
end using terms from | |
else if (frontapp starts with "Google Chrome") or (frontApp starts with "Chromium") or (frontApp starts with "Opera") or (frontApp starts with "Vivaldi") or (frontApp starts with "Brave Browser") or (frontApp starts with "Microsoft Edge") or (frontApp starts with "Arc") then | |
using terms from application "Google Chrome" | |
tell application frontApp to set currentTabTitle to title of active tab of front window | |
tell application frontApp to set currentTabURL to URL of active tab of front window | |
end using terms from | |
else | |
return frontApp & " is not a supported browser" | |
end if | |
return currentTabURL & "\n" & currentTabTitle |
// JavaScript for Automation (JXA) // | |
// This example is meant as a simple starting point to show how to get the information in the simplest available way. | |
// Keep in mind that when asking for a value after another, only the last one one will be output. | |
// This method is as good as its AppleScript counterpart. | |
// Webkit variants include "Safari", "Webkit", "Orion". | |
// Specific editions are valid, including "Safari Technology Preview". | |
// "Safari" Example: | |
Application("Safari").windows[0].currentTab.name() | |
Application("Safari").windows[0].currentTab.url() | |
// "Webkit" Example: | |
Application("Webkit").windows[0].currentTab.name() | |
Application("Webkit").windows[0].currentTab.url() | |
// Chromium variants include "Google Chrome", "Chromium", "Opera", "Vivaldi", "Brave Browser", "Microsoft Edge", "Arc". | |
// Specific editions are valid, including "Google Chrome Canary", "Microsoft Edge Dev". | |
// "Google Chrome" Example: | |
Application("Google Chrome").windows[0].activeTab.name() | |
Application("Google Chrome").windows[0].activeTab.url() | |
// "Chromium" Example: | |
Application("Chromium").windows[0].activeTab.name() | |
Application("Chromium").windows[0].activeTab.url() | |
// This example returns both the title and URL for the frontmost tab of the active browser, separated by a newline. | |
// For shorter code inclusive of all editions, only the start of the application name is checked. | |
// This method is superior to its AppleScript counterpart. It does not need a "main" browser available on the system to reuse the command on similar ones and throws a proper error code on failure. | |
const frontAppName = Application("System Events").applicationProcesses.where({ frontmost: true })[0].name() | |
const frontApp = Application(frontAppName) | |
const webkitVariants = ["Safari", "Webkit", "Orion"] | |
const chromiumVariants = ["Google Chrome", "Chromium", "Opera", "Vivaldi", "Brave Browser", "Microsoft Edge", "Arc"] | |
if (webkitVariants.some(appName => frontAppName.startsWith(appName))) { | |
var currentTabTitle = frontApp.windows[0].currentTab.name() | |
var currentTabURL = frontApp.windows[0].currentTab.url() | |
} else if (chromiumVariants.some(appName => frontAppName.startsWith(appName))) { | |
var currentTabTitle = frontApp.windows[0].activeTab.name() | |
var currentTabURL = frontApp.windows[0].activeTab.url() | |
} else { | |
throw new Error(`${frontAppName} is not a supported browser: ${webkitVariants.concat(chromiumVariants).join(", ")}`) | |
} | |
`${currentTabURL}\n${currentTabTitle}` |
Vitor,
I'm trying to write up something that will perform an option for whichever of these are the frontmost application because you're right about making the applescripts available to work with as many browsers as possible, but I'm running into a problem.
When I'm running the script in the Applescript editor and run into "Google Chrome Canary," the editor brings up the dictionary selector and asks me to find "Google Chrome Canary," which I don't have installed. Is there a way around that? I tried wrapping it in a "try" statement, but that didn't help. As is, it's inside an "if" statement that should prevent the above commands from being invoked.
I use if statements as well, for this. I’ve refrained from making the gist more complex with those since the goal isn’t really for this to be used as is, in AppleScript, but to be adapted and used inside your language of choice, possibly by calling osascript
.
I’ve updated the gist with a new file that should be able to help with your question, Shawn. It has a caveat, though (explained in the comment).
Any idea about Firefox support for AppleScript?
EDIT looks like Firefox does not implement any of AppleScript scripting support at all.
Is there any way to retrieve the tab number of the current tab in Safari? Counting from the left starting from 1.
I have firgured out how to SET the current tab, for example:
tell window 1 of application "Safari" to set current tab to tab 2
Now I just need to GET the current tab for my script.
@gandalfsaxe tell window 1 of application "Safari" to return index of current tab
.
"tell application frontApp to close current tab of front window" is not working with safari, in chrome i got it working. can you help me?
what would we script for firefox
@himanshuoodles Firefox can’t get the URL via AppleScript. Not cleanly. They have removed support for it on version 3.6.
If you have a need for it, make your voice heard. Don’t get your hopes up, though. No one seems to be capable/willing to do it.
FWIW: I've put your apple scripts together in a neat little NSRunningApplication
extension for Swift v2.2.
Usage:
if let app = NSWorkspace.sharedWorkspace().frontmostApplication{
print("Active Tab Title: ",app.activeTabTitle)
print("Active Tab URL: ",app.activeTabURL)
}
And here's the code:
import Cocoa
extension NSRunningApplication{
var activeTabURL: NSURL?{
guard self.active, let bundleIdentifier = self.bundleIdentifier else {
return nil
}
let code: String? = {
switch(bundleIdentifier){
case "org.chromium.Chromium":
return "tell application \"Chromium\" to return URL of active tab of front window"
case "com.google.Chrome.canary":
return "tell application \"Google Chrome Canary\" to return URL of active tab of front window"
case "com.google.Chrome":
return "tell application \"Google Chrome\" to return URL of active tab of front window"
case "com.apple.Safari":
return "tell application \"Safari\" to return URL of front document"
default:
return nil
}
}()
var errorInfo: NSDictionary?
if let code = code, let script = NSAppleScript(source: code), let out: NSAppleEventDescriptor = script.executeAndReturnError(&errorInfo){
if let errorInfo = errorInfo{
print(errorInfo)
} else if let urlString = out.stringValue{
return NSURL(string: urlString)
}
}
return nil
}
var activeTabTitle: String?{
guard self.active, let bundleIdentifier = self.bundleIdentifier else {
return nil
}
let code: String? = {
switch(bundleIdentifier){
case "org.chromium.Chromium":
return "tell application \"Chromium\" to return title of active tab of front window"
case "com.google.Chrome.canary":
return "tell application \"Google Chrome Canary\" to return title of active tab of front window"
case "com.google.Chrome":
return "tell application \"Google Chrome\" to return title of active tab of front window"
case "com.apple.Safari":
return "tell application \"Safari\" to return name of front document"
default:
return nil
}
}()
var errorInfo: NSDictionary?
if let code = code, let script = NSAppleScript(source: code), let out: NSAppleEventDescriptor = script.executeAndReturnError(&errorInfo){
if let errorInfo = errorInfo{
print(errorInfo)
} else {
return out.stringValue
}
}
return nil
}
}
This works great.
I am just facing one minor issue i.e I am running this script on regular intervals from nodejs and when the browser ( chrome or safari ) is minimised it still keeps on reporting the title of the tab which was opened in the browser
I guess this has something to do with the line :
tell application "System Events" to set frontApp to name of first process whose frontmost is true
I.e when we minimise the process, frontApp still points to the minimised process. We need to take into account visibility factor also i guess along with the frontmost.
@bhavyaw Frontmost means frontmost, however the the OS interprets it. If macOS can interpret a minimised application as the frontmost app, it’s for a reason. It means the application that is active, not the application whose window is visible.
What’s a minor issue for you is actually an advantage for other people. What you’re trying to do goes counter to the OS’s interpretation, so I have no intention of adding window visibility detection.
Made some major changes. Most notably, added a JavaScript for Automation version which is superior to the AppleScript one and a document explaining the absence of other browsers.
Anybody knows how to identify "Chrome Application" that is running? like Postman.
If I use this script the result is url from Chrome Browser active tab, but the front window is Postman application.
Thank you for this.
These declarations were both undefined for me on Catalina (10.15.7):
const frontmost_app_name = Application('System Events').applicationProcesses.where({ frontmost: true }).name()[0]
const frontmost_app = Application(frontmost_app_name)
But I got it to work with this line:
const frontmost_app = Application('System Events').processes.whose({frontmost: true})[0];
I combined this script with another script to extract the main window's title (when a non-browser is the frontmost application). I wrote about it here but here's the final script I came up with:
var seApp = Application("System Events");
var oProcess = seApp.processes.whose({frontmost: true})[0];
var appName = oProcess.displayedName();
// if script is compiled and run multiple times, you need to reset variables explicitly
var url = undefined, incognito = undefined, title = undefined;
switch(appName) {
case "Safari":
url = Application(appName).documents[0].url();
title = Application(appName).documents[0].name();
break;
case "Google Chrome":
case "Google Chrome Canary":
case "Chromium":
case "Brave Browser":
const activeWindow = Application(appName).windows[0];
const activeTab = activeWindow.activeTab();
url = activeTab.url();
title = activeTab.name();
break;
default:
mainWindow = oProcess.
windows().
find(w => w.attributes.byName("AXMain").value() === true)
// in some cases, the primary window of an application may not be found
// this occurs rarely and seems to be triggered by switching to a different application
if(mainWindow) {
title = mainWindow.
attributes.
byName("AXTitle").
value()
}
}
JSON.stringify({
appName,
url,
title,
incognito
});
From version 87
of Firefox we able to get URL. Only constraint is that we need to set accessibility.force_disabled
to -1
. Source
link=$( osascript -e 'tell application "System Events" to tell process "Firefox" to get value of UI element 1 of combo box 1 of toolbar "Navigation" of first group of front window' )
echo "$link"
@japanese-goblinn That’s a hack. I don’t intend to add Firefox support to the list until they support AppleScript properly, which at this point seems unlikely will ever happen.
@vitorgalvao fair enough, but I think that's more reliable "hack" than sending keystrokes :)
@vitorgalvao is there a way to use this script without having to have Google Chrome installed? I am trying to get the front most browser URL returned to a c# program but can't guarantee that the user will have Chrome installed. I have tried wrapping in if statements and try statement but I always get the splash screen asking where the application Google Chrome is?
@maxhuckers Use only the last section of the JXA. The code comments explain why.
@vitorgalvao Works a treat thank you. Is there no way to implement Firefox with this script?
If we have: tell application "System Events" to get value of UI element 1 of combo box 1 of toolbar "Navigation" of first group of front window of application process "Firefox"
in an AppleScript, do you know what the equivalent is in JXA for the same thing?
@maxhuckers
well, I'm not familiar with JXA, so i don't know
Thank you I couldn't figure out why Vivaldi wasn't responding to my scripts! "using terms from" got things going again. :)
@vitorgalvao This works for me on my machine, I am calling this from a Python script. However, when I packaged it as a Python application and ran it on another Mac machine, it did not work. Are there any specific permissions required for this to function properly? I am new to MacOS development and would appreciate any guidance you could provide. Thank you.
Hey, thanks for this consolidated resource.
I couldn't get Apple Script to work when I have two windows of a browser. Does anyone know if there's a way to get said data for the active
window (similar to the active tab)?
@realshovanshah That’s already how it works, and always has. Without an error, it’s impossible to help further.
Either way, as per the comments, use the JXA version, not the AppleScript version.
Removed Opera support, since it seems they no longer support AppleScript.