Skip to main content

Read Firefox's local synced-tabs SQLite database and export remote-device tab lists as JSON.

Project description

ff-synctool

Small Python PoC for reading Firefox's local synced-tabs database and exporting the tab list from each remote device as JSON.

What it does

When you're signed into Firefox Sync, Firefox mirrors the list of open tabs from every other signed-in device into a local SQLite database (synced-tabs.sqlite3) inside your profile directory. The tabs table holds one row per remote device, with the actual tab metadata stored as an escaped JSON blob in the record column.

ff_synctool.export opens that database, decodes each record, and writes one tab_<guid>.json file per remote device into the current directory.

Where to find synced-tabs.sqlite3

Inside your active Firefox profile folder:

  • Linux: ~/.mozilla/firefox/<profile>/synced-tabs.sqlite3
  • macOS: ~/Library/Application Support/Firefox/Profiles/<profile>/synced-tabs.sqlite3
  • Windows: %APPDATA%\Mozilla\Firefox\Profiles\<profile>\synced-tabs.sqlite3

Close Firefox before reading the file, or copy it elsewhere first — SQLite may refuse to open it while Firefox holds a lock.

Usage

After installing (see Development below), use the installed console script:

ff-synctool-export path/to/synced-tabs.sqlite3

Or run the module directly from a checkout:

python -m ff_synctool.export path/to/synced-tabs.sqlite3

This writes a tab_<guid>.json file per remote device into the working directory. Each file looks roughly like:

{
  "id": "DFKDGhG1_yV-",
  "clientName": "mike's Firefox Developer Edition on Mike-MBP",
  "tabs": [
    {
      "title": "The lethal trifecta for AI agents…",
      "urlHistory": ["https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/"],
      "icon": "https://simonwillison.net/favicon.ico",
      "lastUsed": 1750500277
    }
  ]
}

ff_synctool.commands

ff_synctool.commands is a second exploratory module that dumps the remote_tab_commands table — the queue Firefox uses for "Send Tab to Device". It currently hardcodes the database path (synced_tabs.sqlite3) and prints each pending command (open URL / close tab) to stdout.

Schema reference

sqlite> PRAGMA table_info(tabs);
0|guid|TEXT|1||1
1|record|TEXT|1||0
2|last_modified|INTEGER|1||0

Status

Proof of concept. Read-only against your Firefox profile, no warranty. Not affiliated with Mozilla.

Development

pip install -e ".[dev]"
ruff check .
pytest

CI runs ruff + pytest on Python 3.12, 3.13, and 3.14 — see .github/workflows/ci.yml.

Releases

Tag-driven publish to PyPI via Trusted Publishing (no API tokens) — see .github/workflows/release.yml.

To cut a release:

  1. Bump version in pyproject.toml.
  2. Commit and tag matching the version, prefixed with v (e.g. git tag v0.1.1 && git push --tags).
  3. The workflow verifies the tag matches pyproject.toml, builds sdist + wheel, and publishes to PyPI.

First-time setup: on pypi.org, add this repo as a trusted publisher for the ff-synctool project (workflow release.yml, environment pypi).

Roadmap / suggested improvements

Concrete next steps to turn this into something more durable, ordered roughly by impact-vs-effort:

  • Tests with pytest. See tests/test_export.py.
  • CI via GitHub Actions. Ruff + pytest on Ubuntu, Python 3.12/3.13/3.14.
  • Project metadata + src layout. PEP 621 pyproject.toml, src/ff_synctool/ package, console script ff-synctool-export. Stdlib-only at runtime.
  • Tag-driven PyPI release workflow. See .github/workflows/release.yml.
  • CLI polish in ff_synctool.export.
    • Use the --json argument (currently parsed but ignored) or remove it.
    • Add --output-dir so output doesn't pollute CWD.
    • Replace f-string path joins with pathlib.Path.
    • Close the sqlite connection (contextlib.closing or explicit conn.close()).
    • Open the DB read-only: sqlite3.connect(f"file:{path}?mode=ro", uri=True) so a running Firefox can't be corrupted.
  • Normalise ff_synctool.commands. Drop the hardcoded filename, take the DB path as an argument, add an if __name__ == "__main__": main() guard, and consider merging into export as a subcommand (export tabs / export commands).
  • Type hints + ruff/mypy. Small surface area, easy win.
  • LICENSE file. MIT or Apache-2.0 — currently absent.
  • Optional: pretty-print mode. A --format=table flag that prints titles + URLs to stdout for quick inspection without writing files.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ff_synctool-0.1.0.tar.gz (6.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ff_synctool-0.1.0-py3-none-any.whl (6.1 kB view details)

Uploaded Python 3

File details

Details for the file ff_synctool-0.1.0.tar.gz.

File metadata

  • Download URL: ff_synctool-0.1.0.tar.gz
  • Upload date:
  • Size: 6.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ff_synctool-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2e2598b92e97ed0b69cf5f62e6d79443f5c0b4c1bf020f0b3dfb0d716180a41c
MD5 d366164211e91930c0ea0b4526ea2170
BLAKE2b-256 754eed13fd76ea6c70b96f0eb610dd9ba50f47929fc4f2f0254e43bb6d6e32db

See more details on using hashes here.

Provenance

The following attestation bundles were made for ff_synctool-0.1.0.tar.gz:

Publisher: release.yml on Darkflib/ff-synctool

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ff_synctool-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: ff_synctool-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 6.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ff_synctool-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d5cb32f49a77ed035f4ecba2b73b39bef0e31ebb8a7c79de111fbcf59d30579c
MD5 e0315bdb4afd2dbbd8cdd36c68f8de96
BLAKE2b-256 ed8c2bad9303e028f366c6b5b0497b09e4ef8dea5fa124ee2799ff6fb2c03775

See more details on using hashes here.

Provenance

The following attestation bundles were made for ff_synctool-0.1.0-py3-none-any.whl:

Publisher: release.yml on Darkflib/ff-synctool

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page