Iterating over all the tabs in the front most browser window?

My goal - in doing research on various topics I sometimes open 50+ browser tabs. When finished I want to iterate over the list of tabs and save the urls.

I can start with a tab, get the URL and then move on to the next. That part is easy enough. I can't figure out how to tell when I've come to the end? My recovering programmer brain wants there to be a function: hasNextTab().

Bonus Points - is there an elegant way to ignore pinned tabs? I could just start the first tab at 3, knowing I always have two pinned tabs.

This is as far as I got:

Curiously this duplicated some tabs. While I don't know why?pinned tabs contributing to the count, but not visited?

It does a good enough job that I don't care.

The macro below saves Safari urls to a text file - you could just save the applescript results to the clipboard instead of a variable, of course.

14)Safari Tabs to DT3 bookmarks.kmmacros (38 KB)

Here is the Applescript:

tell application "Safari"
	
	--Variables
	set windowCount to number of windows
	set docText to ""
	
	--Repeat for Every Window
	repeat with x from 1 to windowCount
		set tabCount to number of tabs in window x
		
		--Repeat for Every Tab in Current Window
		repeat with y from 1 to tabCount
			
			--Get Tab Name & URL
			set tabURL to URL of tab y of window x
			
			set docText to docText & ¬
				tabURL & ¬
				linefeed as string
		end repeat
		
	end repeat
end tell
1 Like

You may not strictly need to iterate – a declarative expression in a JavaScript for Automation action may suffice.

Something like:

const tabs = Application(kmvar.local_BrowserName).windows.tabs;

return 0 < tabs.length
	? tabs.url().flat().join("\n")
	: `No web pages open in ${kmvar.local_BrowserName}`;

So for example:

List of URLs in each browser tab.kmmacros (4.9 KB)

2 Likes

This is great! Much better than my current approach.

I'm not great at Javascript, can you share how to change the first line to only get the tabs of the frontmost browser window? Thanks!

Sure – we can leave the JS unchanged, and just bind local_BrowserName to the value of the %FrontBrowserName% token.

Something like:

List of URLs in FRONT browser tabs.kmmacros (3.7 KB)

1 Like

Thanks for this. But I was looking for would be the front window of the front browser.

Use case: I manage tab sets in KBM (long story) and I sometimes want to make a new set from the current browser window. I've been doing this before by iterating through the tabs with KBM actions, but with Sonoma/KBMv11 it became a little flakey.

Thanks for any help you can provide. I'm trying to get better at javascript.

.windows.at(0)

const tabs = Application(kmvar.local_BrowserName).windows.at(0).tabs;

So, for example:

List of URLs in tabs of Front Browser's Front Window.kmmacros (3.7 KB)

That is totally intuitive! (not) Thanks very much, I get to fix a problem and learn something at the same time.

:slight_smile:

You can also write windows[0] there, and a string-preprocessor will munge it back to the underlying windows.at(0) behind the scenes before execution, but ...

a disadvantage of using that cosmetic sugaring is that windows is not, in fact, a JS Array, and using Array indexes on it can confuse you into expecting it to have other Array methods like .map and .filter

(You can derive a real Array of Window object references by writing window(), but once you have called that function to convert from a custom collection object to a standard Array object, you do get access to Array methods like .map, but in exchange you lose access to the window.tabs.url() enchainment across the whole collection. (A real JS Array has no .tabs property or .url() method)

It's feasible, but noticeably slower – multiplying the use of costly Apple Events, especially at scale – to write something like:

windows()[0].tabs().map(tab => tab.url())

which costs one Apple Event per tab, whereas with:

window.tabs.url()

we harvest all of the urls at the price of a single Apple Event.

1 Like

I'm using Arc as my main browser, is there a solution that works with it? I would like to copy all names and url of all open tabs but the List of URLs in tabs of Front Browser's Front Window macro doesn't work with it

KM browser tokens are defined for Safari, Chrome, and variants thereof which use the same osascript interface.

token:WebBrowserTokens [Keyboard Maestro Wiki]

They can't be defined for browsers, like Firefox, which don't provide an osascript interface, and are thus beyond the reach of JavaScript for Automation and AppleScript.


Arc appears to use the Chromium engine, so it may appear to Keyboard Maestro to be a version of Google Chrome. See discussion here, for example:

Thanks for your quick reply. I've seen that the Arc Browser is scriptable, i can Open the script dictionary for it, so I thinks a script solution should work, but I'm not able to write such a script; can someone please help me with this?

I was able to write this script to get the name and url of the active tab of the Arc front window

tell application "Arc"
	
	set theTitle to title of active tab of front window
	
	
	set theUrl to URL of active tab of front window
	
	set the clipboard to "[" & theTitle & "]
(" & theUrl & ")"
end tell

How can I modify this script to get the names and url of all the tabs of the Arc frontmost window, skipping the pinned tabs?

1 Like