# WatchState

WatchState is a self-hosted backup app. Self-hosted service that syncs per-user play state across Plex, Jellyfin, and Emby media servers. It is open source and self-hosted, installable on Docker Hub and Unraid.

Canonical page: https://ourlocalhost.com/app/1350/watchstate

## Description

Self-hosted service that syncs per-user play state across Plex, Jellyfin, and Emby media servers. It keeps watch progress consistent between the three backends without relying on third-party services, so homelab users running multiple media servers don't need an external bridge.

## Platform availability

Available on 2 of 9 platforms: Unraid, Proxmox.

## Health score

80/100 (Excellent), based on 4 of 5 factors.
- Maintained: 100 (last commit 21 days ago)
- Popular: 64 (1,577 GitHub stars)
- Easy to install: 45 (2 install platforms, install notes, Docker image)
- Security check: 95 (no serious findings, CI, tests)

## Links

- Docker Hub: https://hub.docker.com/r/arabcoders/watchstate
- GitHub: https://github.com/arabcoders/watchstate
- Unraid: https://ca.unraid.net/apps/watchstate-1jb3plr0b1lr43?q=watchstate

## Common questions

### How should I mount WatchState data in Docker?

Create a local data directory and mount it to /config in the container, for example ./data:/config. The default compose example maps host port 8080 to container port 8080, and you can set the container user with UID.

### What happens to existing records when path matching is enabled?

Path matching is enabled by default and generates guid_path values for new and refreshed movie and episode records unless WS_GUID_PATH_ENABLED is disabled. Existing records require a full import before they can match by path.

### How do I create the initial account and connect media server users?

Create the first WatchState admin account with a username and password before one already exists. Use the identity provisioning preview to see which Plex or Jellyfin users match your identities, and fix unmatched users before applying so their activity is attributed correctly.

### What should I check if WatchState fails as a systemd service?

Confirm the service points to the correct PHP program and the actual WatchState folder, and runs as the watchstate user. Wrong paths or permissions can make the service fail to start.

### How do I audit media record problems in WatchState?

Use Media Health as the central place to audit media record problems, replacing the old parity, duplicate-reference, and file-integrity views. It reports backend metadata coverage, GUID conflicts, duplicate GUIDs, duplicate file references, structural metadata disagreement, path disagreement, weak matches, and optional local file checks.

### Where do I get the webhook URL if I use the Docker installation video?

Copy the webhook URL directly from the backends page because the video has a small mistake about the webhook URL.

---
Source: Our Local Host (https://ourlocalhost.com/app/1350/watchstate), the self-hosted and open-source app directory.
