Reference
Everything Watchkeeper records, where it keeps it, and what it can’t see. The README on GitHub has the same facts in more detail.
What the Panel Counts
| Line | What it counts |
|---|---|
| Other sites told about your visit | Registrable domains, other than the page’s own, that the page sent a request to: scripts, images, styles, frames, fetch, XMLHttpRequest, beacons, WebSockets and EventSource |
| Addresses requested | Distinct addresses, origin and path only, never the query string |
| Cookies for this site | Cookies in the engine’s store for the page’s site, including HttpOnly ones |
| Cookies for those other sites | Cookies for sites the engine itself saw the page contact |
| Storage writes | Keys written to localStorage, sessionStorage and IndexedDB, and how many by frames from other sites |
| Fingerprinting reads | A drawn canvas read back, WebGL asked for the graphics hardware, an offline audio context made, each with the site whose script did it |
| Workers started | Workers and shared workers the page started |
Names only, never values: Watchkeeper doesn’t keep cookie contents, storage contents or anything you type. The page’s full address appears in the address bar and nowhere else.
Who Made a Fingerprinting Read
The site named for a read is the nearest script on the call stack when the read happened, and only if the engine’s own list of loaded resources shows that script. Code written into the page itself is credited to the page. A read from a data: script, or made while the page tampers with how the engine reports errors, shows as “by unknown”. The named site is the script that was running, which isn’t proof that script chose to read: a page can hand a reading function to a library it loads, and the library then gets the credit.
Limits
| Limit | Per site |
|---|---|
| Distinct addresses | 5,000, plus the first 50 on each host |
| Other sites | 2,000, plus up to 2,000 more the engine itself saw contacted |
| Script cookie names and storage keys | 1,000 each |
| Text of any one name or address | 512 bytes |
Anything past a limit is counted as left out, and the panel says how much.
Command Line
| Command | What it does |
|---|---|
watchkeeper example.com |
Opens with that site |
watchkeeper --no-history |
Keeps no per-site record at all |
watchkeeper --selftest results-dir |
Runs the end-to-end self-test and writes the results to that folder |
Files Watchkeeper Keeps
The browsing session lives in memory and is deleted when the app closes.
The per-site record is history.json in the data folder:
| System | Folder |
|---|---|
| Windows | %APPDATA%\net.watchkeeper.app |
| macOS | ~/Library/Application Support/net.watchkeeper.app |
| Linux | ~/.local/share/net.watchkeeper.app |
For each site it keeps the last 20 visits: the date in UTC, how many other sites the page contacted, the names of up to 300 of them that the engine saw contacted, the cookie and storage counts, and the fingerprinting reads by site. It holds at most 2,000 sites and about 8 MB, dropping the oldest visits first. A damaged file is set aside as history.json.bad- followed by the time.
Saved reports go to your Downloads folder as watchkeeper-<site>-<date>-<time>.html and .json. An existing file is never overwritten.
Report Format
The JSON report starts with "format": "watchkeeper-report" and "format_version": 1. Its main fields:
| Field | What it holds |
|---|---|
site, page_address, saved |
The page’s site, its address without query, and when the report was saved in UTC |
summary |
The counts the panel shows |
other_sites |
Each other site, whether the engine confirmed it, and its addresses with how each was reached |
own_addresses |
Addresses on the page’s own site |
cookies |
Name, domain, HttpOnly and whom it belongs to, for this site and confirmed other sites |
earlier_cookies |
How many other cookies were in the store, left by earlier sites; never named |
script_cookies, storage_writes |
Names written by scripts, with the site of the frame that wrote them |
fingerprinting |
Each kind of read and who made it |
workers, dropped, unlisted_addresses |
Workers started, events left out, and addresses on sites past the limit |
last_visit |
The previous visit, when history is kept |
cannot_see |
The gaps below, in words |
The HTML report shows the same things as plain text. It has no scripts and no links, and it tells the browser that opens it to load nothing.
What Watchkeeper Can’t See
- Requests from inside workers and service workers. Watchkeeper sees a worker start but not what it sends.
- A beacon sent as you leave a page can be missed, because the page is gone before Watchkeeper collects it.
- Inside other sites’ frames, an engine can hold back some details.
- Engines differ. Safari’s engine and WebKitGTK block some third-party cookies on their own, so the same site can leave fewer cookies on macOS and Linux than on Windows.
- Floods. A page that makes many thousands of calls in an instant can push some addresses out of the count. The panel says how many, and every host keeps room for its first 50 addresses, so a real site isn’t lost in the noise.
- A determined page can notice Watchkeeper. It can find the collector by name and see the app’s message bridge, whose calls are refused. It can add false entries about itself. It can’t read or remove what Watchkeeper collected.