Firefox quietly saves your open tabs to disk every few seconds. If you’ve ever lost a session after a crash, force-quit, or botched update — those tabs are very likely still sitting in a backup file. This post shows you how to read them with a small Python script and get your tabs back.


Where Firefox stores session backups

Firefox keeps session files in your profile folder:

Linux:

~/.mozilla/firefox/<profile-id>/sessionstore-backups/

macOS:

~/Library/Application Support/Firefox/Profiles/<profile-id>/sessionstore-backups/

Windows:

%APPDATA%\Mozilla\Firefox\Profiles\<profile-id>\sessionstore-backups\

Inside you’ll find files like:

FileContents
recovery.jsonlz4The most recent session (updated live)
previous.jsonlz4The session before the current one
recovery.baklz4A rolling backup of recovery
upgrade.jsonlz4-<date>Snapshots taken before Firefox updates

The .jsonlz4 extension is Mozilla’s custom format: a small 8-byte magic header (mozLz40\0) followed by LZ4 block-compressed JSON.


The script

Install the dependency first:

pip install lz4

Then save this as session_viewer.py inside your sessionstore-backups/ folder (or anywhere you like):

#!/usr/bin/env python3
"""Firefox session backup viewer — lists tabs from .jsonlz4 files."""

import json
import sys
import os
import struct
import lz4.block


def decode_session(path):
    with open(path, "rb") as f:
        data = f.read()
    if data[:8] != b"mozLz40\0":
        raise ValueError("Not a valid Firefox session file")
    payload = data[8:]
    # Mozilla stores the uncompressed size as the first 4 bytes after the magic
    stored_size = struct.unpack_from("<I", payload, 0)[0]
    for size in (stored_size, 256 * 1024 * 1024):
        try:
            return json.loads(lz4.block.decompress(payload[4:], uncompressed_size=size))
        except Exception:
            pass
    # Last resort: skip the size prefix entirely
    return json.loads(lz4.block.decompress(payload, uncompressed_size=256 * 1024 * 1024))


def list_tabs(session):
    for wi, window in enumerate(session.get("windows", []), 1):
        tabs = window.get("tabs", [])
        print(f"\n── Window {wi} ({len(tabs)} tabs) ──")
        for tab in tabs:
            entries = tab.get("entries", [])
            if entries:
                e = entries[-1]
                title = e.get("title", "").strip() or "(no title)"
                url = e.get("url", "")
                print(f"  {title}")
                print(f"    {url}")


def list_backups(folder):
    files = sorted(
        f for f in os.listdir(folder)
        if f.endswith(".jsonlz4") or f.endswith(".baklz4") or ".jsonlz4-" in f
    )
    return [os.path.join(folder, f) for f in files]


def main():
    here = os.path.dirname(os.path.abspath(__file__))

    if len(sys.argv) > 1:
        targets = sys.argv[1:]
    else:
        targets = list_backups(here)
        if not targets:
            print("No session files found.")
            sys.exit(1)
        print("Available session backups:\n")
        for i, p in enumerate(targets):
            print(f"  [{i}] {os.path.basename(p)}")
        print()
        choice = input("Enter number to view (or press Enter for most recent): ").strip()
        targets = [targets[int(choice)] if choice else targets[-1]]

    for path in targets:
        print(f"\n{'='*60}")
        print(f"File: {os.path.basename(path)}")
        print("=" * 60)
        try:
            session = decode_session(path)
            list_tabs(session)
        except Exception as e:
            print(f"  Error reading file: {e}")


if __name__ == "__main__":
    main()

Usage

Interactive mode — run without arguments to get a menu of all backup files:

python3 session_viewer.py
Available session backups:

  [0] previous.jsonlz4
  [1] recovery.baklz4
  [2] recovery.jsonlz4
  [3] upgrade.jsonlz4-20260403140140
  [4] upgrade.jsonlz4-20260415192539
  [5] upgrade.jsonlz4-20260427013024

Enter number to view (or press Enter for most recent):

Press Enter to view the most recent, or type a number.

Direct mode — pass a filename as an argument:

python3 session_viewer.py recovery.jsonlz4
python3 session_viewer.py upgrade.jsonlz4-20260415192539

Example output:

============================================================
File: recovery.jsonlz4
============================================================

── Window 1 (8 tabs) ──
  "Software Fundamentals Matter More Than Ever" — Matt Pocock - YouTube
    https://www.youtube.com/watch?v=v4F1gFy-hqg
  Stop Using JSON Web Tokens (JWTs) for Authorization! - YouTube
    
  Deep Agents overview - Docs by LangChain
    https://docs.langchain.com/oss/python/deepagents/overview

How to restore a session

Once you’ve identified which backup has the tabs you want, restoring is a one-liner.

Close Firefox completely before doing this.

# Replace recovery.jsonlz4 with the backup you want to restore
cp upgrade.jsonlz4-20260415192539 recovery.jsonlz4

Reopen Firefox. It will detect the session file and offer to restore it. Accept — and your tabs are back.


How the format works

The mozLz4 format is straightforward:

[8 bytes magic: "mozLz40\0"] [4 bytes: uncompressed size (LE uint32)] [lz4 block data...]

The JSON inside is the full session state — windows, tabs, tab history (back/forward stack), scroll positions, form data, and more. The entries array inside each tab contains the navigation history; the last entry is the currently visible page.

# The key paths in the JSON:
session["windows"]            # list of open windows
window["tabs"]                # list of tabs in a window
tab["entries"][-1]["url"]     # URL of the active page in a tab
tab["entries"][-1]["title"]   # page title

Automating it (grep for a URL)

You can pipe the output and grep for specific domains:

python3 session_viewer.py upgrade.jsonlz4-20260427013024 | grep github.com

Or extract just the URLs:

python3 session_viewer.py recovery.jsonlz4 | grep "https://"

Requirements

  • Python 3.6+
  • lz4 (pip install lz4)

That’s it. No Firefox extensions, no third-party apps.

If the opening do not work you can aways import them one by one with

firefox --new-tab https://docs.ollama.com/integrations/hermes