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:
- Bump
versionin pyproject.toml. - Commit and tag matching the version, prefixed with
v(e.g.git tag v0.1.1 && git push --tags). - 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 scriptff-synctool-export. Stdlib-only at runtime. - Tag-driven PyPI release workflow. See .github/workflows/release.yml.
- CLI polish in
ff_synctool.export.- Use the
--jsonargument (currently parsed but ignored) or remove it. - Add
--output-dirso output doesn't pollute CWD. - Replace f-string path joins with
pathlib.Path. - Close the sqlite connection (
contextlib.closingor explicitconn.close()). - Open the DB read-only:
sqlite3.connect(f"file:{path}?mode=ro", uri=True)so a running Firefox can't be corrupted.
- Use the
- Normalise
ff_synctool.commands. Drop the hardcoded filename, take the DB path as an argument, add anif __name__ == "__main__": main()guard, and consider merging intoexportas 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=tableflag 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)
| File | Size | Uploaded | |
|---|---|---|---|
| ff_synctool-0.1.0.tar.gz | 6.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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