Skip to main content

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.

Metadata

Release files for ff-synctool 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ff-synctool 0.1.0
File Size Uploaded
ff_synctool-0.1.0.tar.gz 6.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ff-synctool 0.1.0
File Interpreter ABI Platform
ff_synctool-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 12.6 kB

Release files / ff_synctool-0.1.0.tar.gz

Download URL ff_synctool-0.1.0.tar.gz
Size 6.4 kB
Tags Source
SHA-256 checksum
How to use checksums
2e2598b92e97ed0b69cf5f62e6d79443f5c0b4c1bf020f0b3dfb0d716180a41c
BLAKE2b-256 checksum
How to use checksums
754eed13fd76ea6c70b96f0eb610dd9ba50f47929fc4f2f0254e43bb6d6e32db
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 28, 2026.

Transparency log

Release files / ff_synctool-0.1.0-py3-none-any.whl

Download URL ff_synctool-0.1.0-py3-none-any.whl
Size 6.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d5cb32f49a77ed035f4ecba2b73b39bef0e31ebb8a7c79de111fbcf59d30579c
BLAKE2b-256 checksum
How to use checksums
ed8c2bad9303e028f366c6b5b0497b09e4ef8dea5fa124ee2799ff6fb2c03775
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 28, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page