Skip to content

Instantly share code, notes, and snippets.

@jscher2000
Last active March 8, 2026 20:12
Show Gist options
  • Select an option

  • Save jscher2000/b7094b3e74b95e5ba9c26f1f685bda6e to your computer and use it in GitHub Desktop.

Select an option

Save jscher2000/b7094b3e74b95e5ba9c26f1f685bda6e to your computer and use it in GitHub Desktop.
Export Synced Tabs List to "bookmarks.html" file (Browser Console script)
// Run code in Browser Console after enabling chrome debugging --
// about:config => devtools.chrome.enabled => true
// https://developer.mozilla.org/docs/Tools/Browser_Console
try {
var tabPromise = SyncedTabs._internal.getTabClients();
tabPromise.then((arrDevices) => {
if (arrDevices && arrDevices.length > 0){
// Generate a string with the format of a bookmark export file
var d, e, out = '<!DOCTYPE NETSCAPE-Bookmark-file-1>\n<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">\n<TITLE>Bookmarks</TITLE>\n<H1>Bookmarks Menu</H1>\n<DL><p>\n';
const escapeHtmlEntities = function(aText){return (aText || '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;')};
for (var j=0; j<arrDevices.length; j++){
// Create a folder for each device
d = new Date(arrDevices[j].lastModified);
e = Math.floor(d.getTime()/1000);
out += '<DT><H3 ADD_DATE="' + e + '" LAST_MODIFIED="' + e + '">Synced Tabs from ' + escapeHtmlEntities(arrDevices[j].name) + ' as of ' + d.toString() + '</H3>\n<DL><p>\n';
// Sort tabs by most recently used
var arrTabs = arrDevices[j].tabs;
arrTabs.sort(function(a, b){return b.lastUsed - a.lastUsed;});
for (var i=0; i<arrTabs.length; i++){
// Create a bookmark (link) for each tab
d = new Date(arrTabs[i].lastUsed * 1000);
e = Math.floor(d.getTime()/1000);
out += ' <DT><A HREF="' + arrTabs[i].url + '" ADD_DATE="' + e + '" LAST_MODIFIED="' + e + '">' + escapeHtmlEntities(arrTabs[i].title) + '</A>\n';
// Show last access date/time in a note (comment out or delete the next line if you don't want that)
out += ' <DD>Last acccessed: ' + d.toString() + '\n'
}
out += '</DL><p>\n';
}
out += '</DL><p>\n</DL>';
// Set up Save As dialog with proposed file name
var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(Components.interfaces.nsIFilePicker);
try { // Fx125+
fp.init(window.browsingContext, 'Open File', Components.interfaces.nsIFilePicker.modeSave);
} catch(e) { // Fx124 and earlier
fp.init(window, 'Open File', Components.interfaces.nsIFilePicker.modeSave);
}
fp.appendFilter('HTML Files', '*.html');
d = new Date();
d.setMinutes(d.getMinutes() - d.getTimezoneOffset());
var dt = d.toISOString().split('.')[0].replace(/-/g, '').replace(/:/g, '').replace(/T/, '_');
fp.defaultString = 'bookmarks-from-synced-tabs_' + dt + '.html';
// Call Save As dialog and (unless user cancels) write the file
fp.open((aResult) => {
if (aResult == Components.interfaces.nsIFilePicker.returnOK ||
aResult == Components.interfaces.nsIFilePicker.returnReplace) {
try {
IOUtils.writeUTF8(fp.file.path, out);
alert('Look for ' + fp.file.path);
} catch (err) {
alert(err);
}
} else {
alert('Okay, not saving');
}
});
} else {
console.log('NO SYNCED TABS RETRIEVED');
}
}).catch((err) => {
console.log('Problem reading or outputting synced tabs: '+err);
});
} catch (err) {
console.log('Problem reading or outputting synced tabs: '+err);
}
@Ariyara
Copy link

Ariyara commented Mar 4, 2026

Helped me export 1800tabs from my phone. Thanks. But like any chance the history of the tabs can also be recorded? I see few of the tabs were duplicates likely because I was moving around one page to another in a single tab, and the original pages which i wanted to recover is not in the stored list because of history

@jscher2000
Copy link
Author

But like any chance the history of the tabs can also be recorded?

Open Tab Sync is limited to current URLs. History would have historical URLs, but not organized by tab. So I'm not aware of a way to do it from the Sync side.

Perhaps it's possible for an extension to record/export tab history through a local download or some other method?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment