> For the complete documentation index, see [llms.txt](https://wiki.crosswatch.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wiki.crosswatch.app/crosswatch/scrobble/scrobble-filters.md).

# Scrobble filters

Scrobbling supports a small set of filters.

The exact set depends on the source provider.

At a glance:

* **Plex**: user filters, server UUID filters, and library whitelist
* **Emby/Jellyfin**: user ID filters and library whitelist

These filters apply in **Watcher**.

Plex also applies them in **Webhooks**.

### Library whitelist

`*.scrobble.libraries` controls which libraries can generate scrobbles.

Plex example:

```json
{
  "plex": {
    "scrobble": {
      "libraries": ["1", "2"]
    }
  }
}
```

Emby or Jellyfin example:

```json
{
  "emby": {
    "scrobble": {
      "libraries": ["LIBRARY_ID_1", "LIBRARY_ID_2"]
    }
  }
}
```

Behavior:

* Empty list = accept all libraries.
* Filled list = accept only listed libraries.
* If a whitelist is set and no usable library id is present, CrossWatch skips the event.

Scrobble library filtering is allow-list only.

There is no separate scrobble library blacklist.

Provider notes:

* Plex uses library section ids.
* Emby and Jellyfin use their own server library ids.

Related: [Library Whitelisting](/crosswatch/library-whitelisting.md).

### User filters

User filters decide which account a route or webhook accepts.

For Plex:

* Watcher uses `scrobble.watch.filters.username_whitelist`.
* Webhooks use `scrobble.webhook.filters_plex.username_whitelist`.
* Supported values are plain name, `id:<account id>`, or `uuid:<account uuid>`.

Watcher example:

```json
{
  "scrobble": {
    "watch": {
      "filters": {
        "username_whitelist": ["Pascal", "id:123", "uuid:abcd"]
      }
    }
  }
}
```

Webhook example:

```json
{
  "scrobble": {
    "webhook": {
      "filters_plex": {
        "username_whitelist": ["Pascal", "id:123", "uuid:abcd"]
      }
    }
  }
}
```

For Emby and Jellyfin:

* Watcher uses a user ID filter.
* There is no Plex-style server UUID layer.

Behavior:

* No user filter = accept all visible users.
* User filter set = accept only matching users.
* On shared servers, set a user filter early.

Plain Plex names are normalized.

`Pascal` and `pascal` match the same Plex account title.

Use `id:` or `uuid:` when you want strict Plex matching.

### Server UUID filters

These filters are Plex-only.

Watcher and Webhooks both support them:

* `server_uuid_whitelist`
* `server_uuid_blacklist`
* legacy `server_uuid`

Whitelist example:

```json
{
  "server_uuid_whitelist": ["SERVER_UUID_1", "SERVER_UUID_2"]
}
```

Blacklist example:

```json
{
  "server_uuid_blacklist": ["SERVER_UUID_BAD"]
}
```

Legacy single-value example:

```json
{
  "server_uuid": "SERVER_UUID_1"
}
```

Behavior:

* Empty whitelist = accept all servers unless blacklisted.
* Filled whitelist = accept only listed servers.
* Blacklist always wins.

If a server appears in both lists, CrossWatch ignores the event.

### Filter order

A scrobble event must pass every enabled filter:

1. The source must be enabled.
2. If Plex server filters are in use, the server must pass them.
3. If a user filter exists, the user must match it.
4. If a library whitelist exists, the library must match it.
5. The media type must be supported.
6. Debounce, suppression, and dedupe rules must allow it.

For Plex, blacklist wins over whitelist.

Playback scrobbling focuses on `movie` and `episode` events.

Plex rating forwarding supports a wider set of Plex media types.

### Watcher specifics

Watcher filtering is route-based.

That means different routes can own different users, servers, or sinks.

Provider differences:

* Plex routes can filter by username, server UUID, and library whitelist.
* Emby and Jellyfin routes use user ID plus library whitelist.
* Separate routes per user or profile keeps ownership clear.

Watcher also supports `scrobble.watch.ignore_live_tv_dvr`.

That option is Plex-only.

When enabled, Live TV and DVR-like Plex events are ignored.

Related: [Watcher](/crosswatch/scrobble/watcher.md).

### Webhook specifics

This section is mainly about Plex.

Plex webhook filters are global for the Plex webhook endpoint.

They are not route-based.

If you configure a webhook secret, CrossWatch validates the Plex webhook signature.

Webhook mode also applies its own debounce and suppression settings.

Common examples are pause debounce, near-end start suppression, autoplay suppression, and optional session progress probing.

For Emby and Jellyfin, user filtering is usually handled in the media server webhook setup.

Related: [Webhooks](/crosswatch/scrobble/webhooks.md).

### Run Watcher and Webhooks together

This rule matters for Plex.

CrossWatch can enable both sources at the same time:

```json
{
  "scrobble": {
    "enabled": true,
    "sources": {
      "webhook": true,
      "watcher": true
    }
  }
}
```

`scrobble.sources` is the current way to control them independently.

The older `scrobble.mode` still exists for compatibility.

Use both only when each path owns different Plex servers.

Safe pattern:

* Watcher = local Plex server
* Webhooks = remote Plex server

Example split:

```json
{
  "scrobble": {
    "sources": {
      "webhook": true,
      "watcher": true
    },
    "watch": {
      "filters": {
        "server_uuid_whitelist": ["LOCAL_SERVER_UUID"]
      }
    },
    "webhook": {
      "filters_plex": {
        "server_uuid_whitelist": ["REMOTE_SERVER_UUID"]
      }
    }
  }
}
```

If the same Plex server feeds both paths, duplicate events are possible.

Common side effects:

* duplicate starts, pauses, stops, or ratings
* conflicting progress updates
* extra tracker API calls

### Best practice

* Start with user filters.
* Add a library whitelist when only some libraries should scrobble.
* Use server UUID filters only for Plex.
* For Emby and Jellyfin, split shared setups by user ID, routes, or profiles.
* Do not let the same Plex server hit Watcher and Webhooks.

For one Plex server, use one path.

For multiple Plex servers, use both only when each source owns different server UUIDs.

### Related topics

* [Watcher](/crosswatch/scrobble/watcher.md)
* [Webhooks](/crosswatch/scrobble/webhooks.md)
* [Webhook or Watcher](/crosswatch/scrobble/webhook-or-watcher.md)
* [Configuration (config.json)](/crosswatch/configuration-config-json.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://wiki.crosswatch.app/crosswatch/scrobble/scrobble-filters.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
