Get URL of current active tab from Firefox via command line
I am running Mozilla Firefox 54.0.
Given an already opened session of Firefox and multiple open tabs, is there a way for me to extract the currently active tab (the tab I am looking at) via command line?
I could not find anything in a List of command line arguments or on the Mozilla Developer page.
My question differs from this question, as it neither works the intended way for me nor do I want all the tabs; I want one specific tab, the tab I am looking at.
Does anybody have an idea?
Is there maybe a way to interface with a running instance of Firefox?
Thanks for Reading
Edit: The Solution:
import json
f= open('~/.mozilla/firefox/RANDOM.default/sessionstore-backups/recovery.js' )
jdata = json.loads(f.read())
f.close()
CurrentTab = jdata.get("windows")[0].get("tabs")[jdata["windows"][0]["selected"]-1].get("entries")[HistLen-1].get("url")
while
HistLen = len(jdata.get("windows")[0].get("tabs")[jdata["windows"][0]["selected"]-1].get("entries"))
The HistLen
was necessary because else I was always getting some older page I had previously opened in that tab.
Thanks for Reading
A solution has been provided here which is a combination of sed
and python2
. Here is a little bit more clear version of it:
sed -n "$(
python2 <<< $'import json
f = open("/home/username/.mozilla/firefox/RANDOM.default/sessionstore-backups/recovery.js", "r")
jdata = json.loads(f.read())
f.close()
print str(jdata["windows"][0]["selected"])')p" <(python2 <<< $'import json
f = open("/home/username/.mozilla/firefox/RANDOM.default/sessionstore-backups/recovery.js", "r")
jdata = json.loads(f.read())
f.close()
for win in jdata.get("windows"):
for tab in win.get("tabs"):
i = tab.get("index") - 1
print tab.get("entries")[i].get("url")'
)
The file it's using is:
/home/username/.mozilla/firefox/RANDOM.profile/sessionstore.js
in more recent versions you should change it with:
/home/username/.mozilla/firefox/RANDOM.default/sessionstore-backups/recovery.js
Note that this file get regenerated every 15 second so after window being instantly changed it doesn't give you the correct URL, you have to wait some second.
How does this work?
At the first part it look for the id of active tab, it's something between 1 to count of open tabs. let's say it's "3", the code corresponding to this purpose is:
str(jdata["windows"][0]["selected"])
Next it returns a list of URLs (All open tabs) and feds it to the stdin
of sed
:
for win in jdata.get("windows"):
for tab in win.get("tabs"):
i = tab.get("index") - 1
print tab.get("entries")[i].get("url")
So we are doing something like:
sed -n 3p <<< "URL1
URL2
URL3"
which brings us to "URL3".
I have thought about this problem as well and finally came to a solution, inspired by this gist. I thoroughly inspected the objects and unfortunately, I did not find any attribute assigning a tab to be the active tab.
What I instead found was the tabs has a lastAccessed
key and from there I computed the most recent tab.
import json
import lz4.block
import pathlib
from time import time
# Set up path and regex for files
path = pathlib.Path.home().joinpath('.mozilla/firefox')
# files = path.glob('*default*release*/sessionstore-backups/recovery.jsonlz4')
files = path.glob('5ov6afhq.default-release-1/sessionstore-backups/recovery'+
'.jsonlz4')
for f in files:
# decompress if necessary
b = f.read_bytes()
if b[:8] == b'mozLz40\0':
b = lz4.block.decompress(b[8:])
# load as json
j = json.loads(b)
if 'windows' in j.keys():
for w in j['windows']:
# Variables for keeping track of most recent tab
most_recent_tab_index = ''
min_time = 1000
# run through tabs
for t in w['tabs']:
# Firefox does not 0-index
i = t['index'] - 1
# Convert time to seconds
access_time = int((int(time()*1000) - t['lastAccessed'])/600)
if access_time < min_time:
most_recent_tab_index = t['entries'][i]['url']
print("MOST RECENT TAB: ", most_recent_tab_index)
If you use an X11-based desktop, you can try your luck with xprop -id
with the window ID found by xlsclients -l
. It needs some clever use of grep
(possibly with grep -B... -A...
) to filter out the parts you need.