football-docs 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/docs.db +0 -0
- package/docs/statsbomb/api-access.md +41 -14
- package/docs/statsbomb/api-endpoints.md +120 -0
- package/docs/statsbomb/data-model.md +54 -11
- package/docs/statsbomb/event-types.md +42 -1
- package/docs/statsbomb/identity-surfaces.md +16 -0
- package/docs/statsbomb/iq-metrics-glossary.md +223 -0
- package/docs/statsbomb/player-mapping.md +148 -0
- package/docs/statsbomb/player-match-stats.md +245 -0
- package/docs/statsbomb/player-season-stats.md +269 -0
- package/docs/statsbomb/team-match-stats.md +217 -0
- package/docs/statsbomb/team-season-stats.md +213 -0
- package/docs/statsbomb/xg-model.md +33 -3
- package/package.json +29 -18
package/data/docs.db
CHANGED
|
Binary file
|
|
@@ -172,32 +172,59 @@ The nested JSON objects (pass, shot, carry, etc.) are flattened with underscores
|
|
|
172
172
|
## 3. Commercial REST API
|
|
173
173
|
|
|
174
174
|
**Access**: Requires a paid license from StatsBomb (contact sales@statsbomb.com)
|
|
175
|
-
**Base URL**: `https://data.statsbomb.com/api/v2/`
|
|
176
175
|
|
|
177
176
|
### Authentication
|
|
178
177
|
|
|
179
|
-
HTTP Basic Auth with username (email) and password provided by StatsBomb.
|
|
178
|
+
HTTP Basic Auth with username (email) and password provided by StatsBomb. The
|
|
179
|
+
same credentials work across every endpoint.
|
|
180
180
|
|
|
181
181
|
### Endpoints
|
|
182
182
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
|
183
|
+
There is **no single base URL or global API version**. Each resource is
|
|
184
|
+
independently versioned and the API spans **two hostnames**
|
|
185
|
+
(`data.statsbombservices.com` and `data.statsbomb.com`). The full host/version
|
|
186
|
+
matrix, query parameters, and caveats (including a host typo in StatsBomb's own
|
|
187
|
+
Team Stats spec) are documented in **`api-endpoints.md`**. Summary:
|
|
188
|
+
|
|
189
|
+
| Resource | Path (see api-endpoints.md for host + version) |
|
|
190
|
+
|----------|-----------------------------------------------|
|
|
191
|
+
| Competitions | `/api/v4/competitions` |
|
|
192
|
+
| Matches | `/api/v6/competitions/{cid}/seasons/{sid}/matches` |
|
|
193
|
+
| Lineups | `/api/v4/lineups/{mid}` |
|
|
194
|
+
| Events | `/api/v8/events/{mid}` |
|
|
195
|
+
| 360 Frames | `/api/v2/360-frames/{mid}` |
|
|
196
|
+
| Player Mapping | `/api/v1/player-mapping?<params>` |
|
|
197
|
+
| Player Match / Season Stats | `/api/v5/matches/{mid}/player-stats`, `/api/v4/competitions/{cid}/seasons/{sid}/player-stats` |
|
|
198
|
+
| Team Match / Season Stats | `/api/v1/matches/{mid}/team-stats`, `/api/v2/competitions/{cid}/seasons/{sid}/team-stats` |
|
|
190
199
|
|
|
191
200
|
### Response Format
|
|
192
201
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
202
|
+
For competitions, matches, lineups, events, and 360 frames the commercial API
|
|
203
|
+
returns the same JSON structure as the open data files (more competitions,
|
|
204
|
+
fresher data). The **stats endpoints and player-mapping have no open-data
|
|
205
|
+
equivalent** — see the parity table below and the dedicated docs
|
|
206
|
+
(`player-match-stats.md`, `player-season-stats.md`, `team-match-stats.md`,
|
|
207
|
+
`team-season-stats.md`, `player-mapping.md`, `iq-metrics-glossary.md`).
|
|
208
|
+
|
|
209
|
+
### Open Data vs Commercial parity
|
|
210
|
+
|
|
211
|
+
| Capability | Open Data | Commercial API |
|
|
212
|
+
|---|---|---|
|
|
213
|
+
| Competitions / Matches / Lineups / Events / 360 | Yes (selective comps) | Yes (licensed scope) |
|
|
214
|
+
| Player & Team Match/Season Stats (IQ metrics) | **No** | Yes |
|
|
215
|
+
| Player Mapping (live/offline IDs) | **No** | Yes |
|
|
216
|
+
| Freshness | Irregular GitHub updates | Near-live for licensed comps |
|
|
217
|
+
|
|
218
|
+
Code written against open data cannot read OBV, xGChain, PPDA, PSxG, the IQ
|
|
219
|
+
metric catalogues, or live/offline IDs — these exist only in the commercial
|
|
220
|
+
feed.
|
|
197
221
|
|
|
198
222
|
### Rate Limits
|
|
199
223
|
|
|
200
|
-
The commercial API has rate limits that vary by license tier. StatsBomb
|
|
224
|
+
The commercial API has rate limits that vary by license tier. StatsBomb
|
|
225
|
+
recommends caching responses locally and polling the Competitions/Matches
|
|
226
|
+
`*_updated` / `last_updated` timestamps to refetch only changed data (see
|
|
227
|
+
`api-endpoints.md` → Incremental sync).
|
|
201
228
|
|
|
202
229
|
---
|
|
203
230
|
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
source_type: curated
|
|
3
|
+
source_url: https://github.com/statsbomb/open-data
|
|
4
|
+
upstream_version: null
|
|
5
|
+
crawled_at: null
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# StatsBomb Commercial REST API Endpoints
|
|
9
|
+
|
|
10
|
+
Reference for the StatsBomb commercial REST API surface. Each resource is
|
|
11
|
+
**independently versioned** and the API spans **two hostnames** — there is no
|
|
12
|
+
single global API version or base path.
|
|
13
|
+
|
|
14
|
+
> This page describes these endpoint versions: Competitions v4.0.0, Matches
|
|
15
|
+
> v6.0.0, Lineups v4.0.1, Events v8.0.0, 360 Frames v2.0.0, Player Mapping
|
|
16
|
+
> v1.0.0, Player Match Stats v5.0.0, Player Season Stats v4.0.0, Team Match
|
|
17
|
+
> Stats v1.0.0, Team Season Stats v2.0.0. StatsBomb increments the version
|
|
18
|
+
> segment per resource when the response shape changes, so the URL itself
|
|
19
|
+
> tells you which version a feed is; a higher version than listed here may
|
|
20
|
+
> carry additional fields not described on this page.
|
|
21
|
+
|
|
22
|
+
## Authentication
|
|
23
|
+
|
|
24
|
+
All endpoints use **HTTP Basic Auth** with the username (email) and password
|
|
25
|
+
issued by StatsBomb. The same credentials work across every endpoint. Access
|
|
26
|
+
requires a paid licence; licensed scope determines which competitions/seasons
|
|
27
|
+
return data.
|
|
28
|
+
|
|
29
|
+
`statsbombpy` and `StatsBombR` wrap these endpoints. With `statsbombpy`, set
|
|
30
|
+
`SB_USERNAME`/`SB_PASSWORD` env vars or pass `creds={"user":..., "passwd":...}`.
|
|
31
|
+
|
|
32
|
+
## Endpoint matrix
|
|
33
|
+
|
|
34
|
+
`{cid}` = competition_id, `{sid}` = season_id, `{mid}` = match_id.
|
|
35
|
+
|
|
36
|
+
| Resource | Method + path | Host | Spec version |
|
|
37
|
+
|---|---|---|---|
|
|
38
|
+
| Competitions | `GET /api/v4/competitions` | `data.statsbombservices.com` | v4.0.0 |
|
|
39
|
+
| Matches | `GET /api/v6/competitions/{cid}/seasons/{sid}/matches` | `data.statsbombservices.com` | v6.0.0 |
|
|
40
|
+
| Lineups | `GET /api/v4/lineups/{mid}` | `data.statsbomb.com` | v4.0.1 |
|
|
41
|
+
| Events | `GET /api/v8/events/{mid}` | `data.statsbombservices.com` | v8.0.0 |
|
|
42
|
+
| 360 Frames | `GET /api/v2/360-frames/{mid}` | `data.statsbombservices.com` | v2.0.0 |
|
|
43
|
+
| Player Mapping | `GET /api/v1/player-mapping?<params>` | `data.statsbomb.com` | v1.0.0 |
|
|
44
|
+
| Player Match Stats | `GET /api/v5/matches/{mid}/player-stats` | `data.statsbombservices.com` | v5.0.0 |
|
|
45
|
+
| Player Season Stats | `GET /api/v4/competitions/{cid}/seasons/{sid}/player-stats` | `data.statsbombservices.com` | v4.0.0 |
|
|
46
|
+
| Team Match Stats | `GET /api/v1/matches/{mid}/team-stats` | `data.statsbomb.com` | v1.0.0 |
|
|
47
|
+
| Team Season Stats | `GET /api/v2/competitions/{cid}/seasons/{sid}/team-stats` | `data.statsbombservices.com` | v2.0.0 |
|
|
48
|
+
|
|
49
|
+
Older versions of a resource are generally reachable by lowering the version
|
|
50
|
+
segment (e.g. `/api/v7/events/{mid}`), subject to StatsBomb retaining them.
|
|
51
|
+
|
|
52
|
+
### Host and typo caveats
|
|
53
|
+
|
|
54
|
+
- **Two active hosts.** Most resources are on `data.statsbombservices.com`;
|
|
55
|
+
Lineups and Player Mapping are documented on `data.statsbomb.com`. The hosts
|
|
56
|
+
are not interchangeable in the specs — use the one documented per resource and
|
|
57
|
+
verify against live behaviour.
|
|
58
|
+
- **Team Match Stats typo.** The Team Match Stats v1.0.0 PDF prints the host as
|
|
59
|
+
`data.statsbom.com` (missing a `b`). This is a documentation typo; the
|
|
60
|
+
intended host is almost certainly `data.statsbomb.com`. Treat with caution and
|
|
61
|
+
confirm against StatsBomb support.
|
|
62
|
+
|
|
63
|
+
## Response format
|
|
64
|
+
|
|
65
|
+
Every endpoint returns a JSON **array** of objects. The shape mirrors the
|
|
66
|
+
StatsBomb Open Data JSON for the entities that exist in open data
|
|
67
|
+
(competitions, matches, lineups, events, 360-frames). The four stats endpoints
|
|
68
|
+
and player-mapping have no open-data equivalent.
|
|
69
|
+
|
|
70
|
+
| Resource | Array element | Documented in |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| Competitions | competition-season object | `data-model.md` |
|
|
73
|
+
| Matches | match object (incl. `collection_status`, `metadata`) | `data-model.md` |
|
|
74
|
+
| Lineups | per-team lineup (lineup/formations/events arrays) | `data-model.md` |
|
|
75
|
+
| Events | event object (v8 fields incl. OBV, pass clusters) | `event-types.md` |
|
|
76
|
+
| 360 Frames | freeze-frame object per event_uuid | `data-model.md`, `coordinate-system.md` |
|
|
77
|
+
| Player Mapping | competition-season-team block per player | `player-mapping.md` |
|
|
78
|
+
| Player Match/Season Stats | one row per player | `player-match-stats.md`, `player-season-stats.md` |
|
|
79
|
+
| Team Match/Season Stats | one row per team | `team-match-stats.md`, `team-season-stats.md` |
|
|
80
|
+
|
|
81
|
+
## Open Data vs commercial parity
|
|
82
|
+
|
|
83
|
+
The free Open Data repository (`github.com/statsbomb/open-data`) mirrors only a
|
|
84
|
+
subset of the commercial API:
|
|
85
|
+
|
|
86
|
+
| Capability | Open Data | Commercial API |
|
|
87
|
+
|---|---|---|
|
|
88
|
+
| Competitions / Matches / Lineups / Events / 360 | Yes (selective competitions) | Yes (licensed scope) |
|
|
89
|
+
| Player Match Stats | **No** | Yes (`/matches/{mid}/player-stats`) |
|
|
90
|
+
| Player Season Stats | **No** | Yes (`/competitions/{cid}/seasons/{sid}/player-stats`) |
|
|
91
|
+
| Team Match Stats | **No** | Yes (`/matches/{mid}/team-stats`) |
|
|
92
|
+
| Team Season Stats | **No** | Yes (`/competitions/{cid}/seasons/{sid}/team-stats`) |
|
|
93
|
+
| Player Mapping (live/offline IDs) | **No** | Yes (`/player-mapping`) |
|
|
94
|
+
| Data freshness | Irregular GitHub updates | Near-live for licensed comps |
|
|
95
|
+
|
|
96
|
+
The pre-computed IQ metric catalogues (OBV, xGChain, PPDA, PSxG, GSAA, etc.)
|
|
97
|
+
and the live/offline ID mapping **only exist in the commercial feed**. Code
|
|
98
|
+
written against open data cannot read these fields — do not assume their
|
|
99
|
+
presence from open-data examples.
|
|
100
|
+
|
|
101
|
+
## Incremental sync
|
|
102
|
+
|
|
103
|
+
The Competitions response carries `match_updated`, `match_updated_360`,
|
|
104
|
+
`match_available`, and `match_available_360` timestamps per competition-season;
|
|
105
|
+
the Matches response carries `last_updated` / `last_updated_360` per match.
|
|
106
|
+
Poll Competitions, diff the timestamps, then refetch only changed
|
|
107
|
+
competition-seasons/matches rather than re-pulling everything.
|
|
108
|
+
|
|
109
|
+
`match_status` must be `"available"` before Events can be fetched for a match;
|
|
110
|
+
`match_status_360` of `"available"` is required before 360 frames exist. See the
|
|
111
|
+
collection/match status enums in `data-model.md`.
|
|
112
|
+
|
|
113
|
+
## Player Mapping request rules
|
|
114
|
+
|
|
115
|
+
`/api/v1/player-mapping` requires at least one query parameter (no params = no
|
|
116
|
+
data). `all-account-data=true` is required to return the full licensed set
|
|
117
|
+
(otherwise the response is trimmed for trialling). If a query would return
|
|
118
|
+
**more than 5000 records the response is streamed to a file** as JSON rather
|
|
119
|
+
than returned inline. See `player-mapping.md` for parameters and the
|
|
120
|
+
live/offline ID model.
|
|
@@ -98,9 +98,49 @@ File: `matches/{competition_id}/{season_id}.json`
|
|
|
98
98
|
|
|
99
99
|
### Data Quality Flags
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
`metadata` (object on each match; child attributes are optional and the object
|
|
102
|
+
is empty for matches not yet `available`):
|
|
103
|
+
|
|
104
|
+
- `data_version` -- the event-data collection version applied to this match (e.g. `1.0.0`, `1.0.1`, `1.0.2`, `1.0.3`, `1.1.0`). Which optional event fields are populated depends on this value; `1.1.0` is the fullest.
|
|
105
|
+
- `shot_fidelity_version` -- `"1"` (basic) or `"2"` (high-fidelity x/y on shots, freeze frames and shot-paired events)
|
|
106
|
+
- `xy_fidelity_version` -- `"1"` (standard location granularity) or `"2"` (high-precision x/y coordinates)
|
|
107
|
+
|
|
108
|
+
### Match & collection status (Matches API v6)
|
|
109
|
+
|
|
110
|
+
The Matches response carries several status fields. Events/360 are only
|
|
111
|
+
fetchable once the relevant status reaches `available`:
|
|
112
|
+
|
|
113
|
+
| Field | Values |
|
|
114
|
+
|---|---|
|
|
115
|
+
| `match_status` | `available` (event data obtainable), `scheduled`, `deleted` |
|
|
116
|
+
| `match_status_360` | `available`, `scheduled` (awaiting 360), `unscheduled` (comp gets no 360) |
|
|
117
|
+
| `play_status` | `Normal`, `Postponed`, `Cancelled`, `Abandoned`, `Forfeited` |
|
|
118
|
+
| `collection_status` | collection pipeline state (16 values, below) |
|
|
119
|
+
|
|
120
|
+
`collection_status` values: `Unassigned` (not started), `InProgress`,
|
|
121
|
+
`WithoutLocation` (events not yet located on pitch), `WithoutFreezeFrame` (shot
|
|
122
|
+
freeze-frame phase), `PendingValidation`, `Validating`, `Invalid`,
|
|
123
|
+
`WithoutDirection`, `Complete`, `Postponed`, `NoVidError` (footage not sourced),
|
|
124
|
+
`IncVidError` (incomplete footage), `PoorVidError`, `ErrorAbandoned`,
|
|
125
|
+
`ErrorCancelled`, `ErrorForfeit`.
|
|
126
|
+
|
|
127
|
+
Use `last_updated` / `last_updated_360` per match (and the Competitions
|
|
128
|
+
`match_updated*` / `match_available*` timestamps) to drive incremental sync —
|
|
129
|
+
see `api-endpoints.md`.
|
|
130
|
+
|
|
131
|
+
### Competition stages
|
|
132
|
+
|
|
133
|
+
`competition_stage` is an `{id, name}` pair. Stage IDs (from Matches/Events
|
|
134
|
+
specs): 1 Regular Season, 2 Play-In Round, 6 Europa League Play-offs –
|
|
135
|
+
Semi-finals, 8 MLS Cup – Conference Semi-finals, 9 3rd Qualifying Round,
|
|
136
|
+
10 Group Stage, 11 Quarter-finals, 12 Europa League Play-offs – Finals,
|
|
137
|
+
13 16th Finals, 14 Promotion Play-offs – Final, 15 Semi-finals, 18 Promotion
|
|
138
|
+
Play-offs – Semi-finals, 19 Preliminary Round, 20 2nd Round, 21 Europa League
|
|
139
|
+
Play-offs – Quarter-finals, 22 2nd Qualifying Round, 23 MLS Cup – Conference
|
|
140
|
+
Finals, 24 Promotion Play-offs – 1st Round, 25 3rd Place Final, 26 Final,
|
|
141
|
+
27 Promotion Play-offs – 2nd Round, 28 Play-offs, 29 1st Qualifying Round,
|
|
142
|
+
31 Preliminary Round – Semi-finals, 33 8th Finals, 34 1st Phase, 35 Preliminary
|
|
143
|
+
Round – Final.
|
|
104
144
|
|
|
105
145
|
---
|
|
106
146
|
|
|
@@ -316,11 +356,14 @@ Every event is tagged with how the current possession started (counter-attack, s
|
|
|
316
356
|
|
|
317
357
|
## Data Versions
|
|
318
358
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
|
323
|
-
|
|
324
|
-
| `
|
|
325
|
-
| `
|
|
326
|
-
| `
|
|
359
|
+
Each match's `metadata` reports the collection versions applied to it. The
|
|
360
|
+
values you may see, side by side:
|
|
361
|
+
|
|
362
|
+
| Field | Value | What this match contains |
|
|
363
|
+
|-------|-------|--------------------------|
|
|
364
|
+
| `data_version` | `1.0.0` | Core event set, no carry events |
|
|
365
|
+
| `data_version` | `1.1.0` | Full event set including carries and the additional event attributes described on this page and in `event-types.md` |
|
|
366
|
+
| `shot_fidelity_version` | `"1"` | Shots at standard location granularity |
|
|
367
|
+
| `shot_fidelity_version` | `"2"` | Shots, their freeze frames, and shot-paired events at high-precision x/y |
|
|
368
|
+
| `xy_fidelity_version` | `"1"` | Standard x/y location granularity |
|
|
369
|
+
| `xy_fidelity_version` | `"2"` | High-precision x/y coordinates |
|
|
@@ -9,6 +9,7 @@ StatsBomb uses named event types with numeric IDs. Every event in a match has a
|
|
|
9
9
|
| 2 | Ball Recovery | Player regains possession from a loose ball |
|
|
10
10
|
| 3 | Dispossessed | Player loses the ball through opponent action (not a failed dribble) |
|
|
11
11
|
| 4 | Duel | Contested situation between two players (aerial or ground) |
|
|
12
|
+
| 5 | Camera On* | Signals the camera resuming gameplay capture after a replay/cut (deprecated; superseded by `off_camera`) |
|
|
12
13
|
| 6 | Block | Player blocks a shot, pass, or cross |
|
|
13
14
|
| 8 | Offside | Player caught in an offside position |
|
|
14
15
|
| 9 | Clearance | Defensive action to remove the ball from a dangerous area |
|
|
@@ -18,10 +19,12 @@ StatsBomb uses named event types with numeric IDs. Every event in a match has a
|
|
|
18
19
|
| 17 | Pressure | Player applies pressure on an opponent in possession |
|
|
19
20
|
| 18 | Half Start | Marks the start of each half/period |
|
|
20
21
|
| 19 | Substitution | Player substitution |
|
|
22
|
+
| 20 | Own Goal Against | An own goal scored against the team |
|
|
21
23
|
| 21 | Foul Won | Player wins a foul from an opponent |
|
|
22
24
|
| 22 | Foul Committed | Player commits a foul |
|
|
23
25
|
| 23 | Goal Keeper | Goalkeeper-specific actions (saves, punches, claims, etc.) |
|
|
24
26
|
| 24 | Bad Behaviour | Disciplinary action not linked to a foul (e.g. dissent) |
|
|
27
|
+
| 25 | Own Goal For | An own goal scored for the team |
|
|
25
28
|
| 26 | Player On | Player enters the pitch (substitution on) |
|
|
26
29
|
| 27 | Player Off | Player leaves the pitch (substitution off) |
|
|
27
30
|
| 28 | Shield | Player shields the ball from an opponent |
|
|
@@ -30,12 +33,20 @@ StatsBomb uses named event types with numeric IDs. Every event in a match has a
|
|
|
30
33
|
| 34 | Half End | Marks the end of each half/period |
|
|
31
34
|
| 35 | Starting XI | Starting lineup announcement (one per team per match) |
|
|
32
35
|
| 36 | Tactical Shift | Formation or positional change during play |
|
|
36
|
+
| 37 | Error | Player makes an on-the-ball mistake that leads to a shot on goal |
|
|
33
37
|
| 38 | Miscontrol | Player fails to control the ball cleanly |
|
|
34
38
|
| 39 | Dribbled Past | Player is beaten by an opponent's dribble |
|
|
35
39
|
| 40 | Injury Stoppage | Play stopped due to injury |
|
|
40
|
+
| 41 | Referee Ball-Drop | Referee drops the ball to resume play after an injury stoppage |
|
|
36
41
|
| 42 | Ball Receipt* | Player receives a pass (the asterisk is part of the name) |
|
|
37
42
|
| 43 | Carry | Player moves with the ball at their feet between events |
|
|
38
43
|
|
|
44
|
+
> The event-type vocabulary and field set below describe the **Events API
|
|
45
|
+
> v8.0.0** feed (`GET /api/v8/events/{match_id}`). Each match also carries a
|
|
46
|
+
> `metadata.data_version` string (see `data-model.md`) — the exact set of
|
|
47
|
+
> fields present on a given match depends on the data version it was collected
|
|
48
|
+
> under.
|
|
49
|
+
|
|
39
50
|
---
|
|
40
51
|
|
|
41
52
|
## Common Event Fields
|
|
@@ -76,6 +87,25 @@ Every event shares these base fields:
|
|
|
76
87
|
- `duration` -- event duration in seconds (0.0 for instantaneous events)
|
|
77
88
|
- `related_events` -- UUIDs of causally linked events (e.g. pass -> receipt)
|
|
78
89
|
- `under_pressure` -- boolean, present and true when a defender is applying pressure
|
|
90
|
+
- `off_camera` -- boolean, present and true only when the event occurred while the camera was off (data then logically inferred)
|
|
91
|
+
- `out` -- boolean, present and true when the event's outcome is the ball going out of bounds
|
|
92
|
+
- `counterpress` -- boolean, on various defensive events (pressure, dribbled past, 50-50, duel, block, interception, non-offensive foul committed): a pressing action within 5 seconds of an open-play turnover
|
|
93
|
+
|
|
94
|
+
### On-Ball Value fields
|
|
95
|
+
|
|
96
|
+
OBV-eligible events carry net/before/after value fields measuring the change in
|
|
97
|
+
scoring/conceding likelihood caused by the event:
|
|
98
|
+
|
|
99
|
+
- `obv_for_after`, `obv_for_before`, `obv_for_net` -- scoring likelihood within the possession chain after/before/net
|
|
100
|
+
- `obv_against_after`, `obv_against_before`, `obv_against_net` -- conceding likelihood in the next possession chain
|
|
101
|
+
- `obv_total_net` -- net expected goal-difference change over the next two possession chains
|
|
102
|
+
|
|
103
|
+
OBV is populated only where play is not interrupted by off-ball events.
|
|
104
|
+
Eligible types: Carry, Ground/High/Low Pass, Dribble, Shot, Goalkeeper
|
|
105
|
+
Collection, Block, Tackle, Interception, Clearance, Goalkeeper Sweep,
|
|
106
|
+
Goalkeeper Save, Foul Committed, Goalkeeper Concede. See
|
|
107
|
+
`iq-metrics-glossary.md` for the OBV concept and its aggregated forms in the
|
|
108
|
+
stats endpoints.
|
|
79
109
|
|
|
80
110
|
---
|
|
81
111
|
|
|
@@ -103,7 +133,12 @@ The `shot` object is nested within shot events.
|
|
|
103
133
|
|
|
104
134
|
| Field | Type | Description |
|
|
105
135
|
|-------|------|-------------|
|
|
106
|
-
| `statsbomb_xg` | float |
|
|
136
|
+
| `statsbomb_xg` | float | xG "chance quality" -- likelihood of scoring from the shot situation (location, GK and blocker positions), **not** considering shot execution |
|
|
137
|
+
| `gk_save_difficulty_xg` | float | Likelihood of the keeper conceding, given shot placement/velocity and keeper position (on-target, unblocked shots only). Some feeds label this field `statsbomb_xg2` |
|
|
138
|
+
| `shot_execution_xg` | float | Likelihood of scoring after execution -- incorporates placement & velocity on top of the `statsbomb_xg` features |
|
|
139
|
+
| `shot_execution_xg_uplift` | float | `shot_execution_xg − statsbomb_xg`; how much execution improved (or, if negative, worsened) the chance |
|
|
140
|
+
| `gk_positioning_xg_suppression` | float | Goal-scoring threat suppressed by the keeper's positioning vs an average keeper |
|
|
141
|
+
| `gk_shot_stopping_xg_suppression` | float | Goals prevented above expectation by the keeper's shot-stopping |
|
|
107
142
|
| `end_location` | [x, y] or [x, y, z] | Where the shot ended up. Z is height in yards (present for shots that leave the ground) |
|
|
108
143
|
| `key_pass_id` | string | UUID of the pass that assisted this shot |
|
|
109
144
|
| `technique` | object | How the shot was struck |
|
|
@@ -207,6 +242,12 @@ The `pass` object is nested within pass events.
|
|
|
207
242
|
| `no_touch` | boolean | Player intended the ball to run through |
|
|
208
243
|
| `miscommunication` | boolean | Pass and recipient miscommunicated |
|
|
209
244
|
| `backheel` | boolean | Whether the pass was a backheel |
|
|
245
|
+
| `deflected` | boolean | Pass was deflected (can occur on complete or incomplete passes) |
|
|
246
|
+
| `aerial_won` | boolean | The pass event was also an aerial duel won |
|
|
247
|
+
| `pass_cluster_id` | integer | Which of 60 distinct pass clusters this pass is most associated with |
|
|
248
|
+
| `pass_cluster_label` | string | Text description of that cluster, combining its starting third, side of the pitch, length (long/short), primary direction, and modal pass height |
|
|
249
|
+
| `pass_cluster_probability` | float | Probability the pass belongs to `pass_cluster_id`/`label` |
|
|
250
|
+
| `pass_success_probability` | float | Estimated likelihood of the attempted pass being completed, given pitch location, context and target |
|
|
210
251
|
|
|
211
252
|
### Pass Types
|
|
212
253
|
|
|
@@ -37,6 +37,22 @@ StatsBomb Open Data exposes numeric `competition_id`, `season_id`, `match_id`,
|
|
|
37
37
|
inside the provider dataset but should stay provider-scoped. Do not infer global
|
|
38
38
|
identity from a bare number without provider and dataset context.
|
|
39
39
|
|
|
40
|
+
### Two internal ID systems: live vs offline
|
|
41
|
+
|
|
42
|
+
StatsBomb does **not** have a single ID space. Internally there is a *live*
|
|
43
|
+
system and an *offline* system, each with its own ids for players, teams,
|
|
44
|
+
country-of-birth, and matches (`live_player_id` vs `offline_player_id`,
|
|
45
|
+
`live_team_id` vs `offline_team_id`, `live_match_id` vs `offline_match_id`,
|
|
46
|
+
etc.). The same person/team has different integers in each. Which system's ids
|
|
47
|
+
appear in a given feed depends on the system that produced it.
|
|
48
|
+
|
|
49
|
+
Treat a StatsBomb id as a **(system, id)** pair, not a bare integer. Reconciling
|
|
50
|
+
the two requires the commercial **Player Mapping** endpoint
|
|
51
|
+
(`/api/v1/player-mapping`), which returns paired `live_*`/`offline_*` ids — see
|
|
52
|
+
`player-mapping.md`. Open Data does not expose this duality or the mapping
|
|
53
|
+
endpoint, so Open-Data-only workflows generally see one system's ids and should
|
|
54
|
+
record which.
|
|
55
|
+
|
|
40
56
|
## Useful Matching Fields
|
|
41
57
|
|
|
42
58
|
- Competitions and seasons: IDs, names, country, gender, and season label.
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
---
|
|
2
|
+
source_type: curated
|
|
3
|
+
source_url: https://github.com/statsbomb/open-data
|
|
4
|
+
upstream_version: null
|
|
5
|
+
crawled_at: null
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# StatsBomb IQ Metrics Glossary
|
|
9
|
+
|
|
10
|
+
Definitions of the derived metrics that recur across the StatsBomb commercial
|
|
11
|
+
stats endpoints (`player-match-stats`, `player-season-stats`,
|
|
12
|
+
`team-match-stats`, `team-season-stats`) and, for OBV/xG, the Events feed.
|
|
13
|
+
These concepts are referenced by many column names — read this alongside the
|
|
14
|
+
per-endpoint catalogues.
|
|
15
|
+
|
|
16
|
+
These metrics are commercial-only unless noted. OBV and the xG-decomposition
|
|
17
|
+
fields also appear on individual events; everything else is delivered
|
|
18
|
+
pre-aggregated by the stats endpoints.
|
|
19
|
+
|
|
20
|
+
## On-Ball Value (OBV)
|
|
21
|
+
|
|
22
|
+
OBV models the change in the likelihood of scoring/conceding caused by an event,
|
|
23
|
+
expressed in expected-goal-difference units.
|
|
24
|
+
|
|
25
|
+
On an **event** (Events v8) it appears decomposed as:
|
|
26
|
+
- `obv_for_after` / `obv_for_before` — probability of scoring within the
|
|
27
|
+
possession chain after / before the event.
|
|
28
|
+
- `obv_for_net` — net change in scoring likelihood from the event.
|
|
29
|
+
- `obv_against_after` / `obv_against_before` / `obv_against_net` — same for the
|
|
30
|
+
likelihood of conceding in the next possession chain.
|
|
31
|
+
- `obv_total_net` — net change in expected goal difference (scoring change minus
|
|
32
|
+
conceding change) over the next two possession chains.
|
|
33
|
+
|
|
34
|
+
OBV is only populated where the sequence of play is not interrupted by off-ball
|
|
35
|
+
events. Event types eligible for OBV: Carry, Ground/High/Low Pass, Dribble,
|
|
36
|
+
Shot, Goalkeeper Collection, Block, Tackle, Interception, Clearance, Goalkeeper
|
|
37
|
+
Sweep, Goalkeeper Save, Foul Committed, Goalkeeper Concede.
|
|
38
|
+
|
|
39
|
+
In the **stats** endpoints OBV is aggregated and split by action family:
|
|
40
|
+
`*_obv` (total), `*_obv_pass`, `*_obv_shot`, `*_obv_defensive_action`,
|
|
41
|
+
`*_obv_dribble_carry`, `*_obv_gk`. Team stats add `*_obv_*_conceded` (opponent
|
|
42
|
+
OBV). Season uses `_90` / `_pg` suffixes.
|
|
43
|
+
|
|
44
|
+
## xGChain and xGBuildup
|
|
45
|
+
|
|
46
|
+
Both attribute the xG of a possession's final shot to **every player involved in
|
|
47
|
+
that possession**, not just the shooter/assister.
|
|
48
|
+
|
|
49
|
+
- **xGChain** — credits all players who touched the ball during a possession
|
|
50
|
+
that ended in a shot, with the shot's xG.
|
|
51
|
+
- **xGBuildup** — the same, but **excludes** the shooter and the assisting
|
|
52
|
+
(key) pass, isolating contribution to build-up play prior to the chance.
|
|
53
|
+
|
|
54
|
+
Variants across the stats endpoints: `xgchain` / `xgbuildup`, `op_*` (open play
|
|
55
|
+
only), `*_per_possession`, and `_90` / `_pg` season forms.
|
|
56
|
+
|
|
57
|
+
## xG, npxG, xA and combined measures
|
|
58
|
+
|
|
59
|
+
- `np_xg` — non-penalty expected goals (xG excluding penalty shots).
|
|
60
|
+
- `np_xg_per_shot` — shot-quality proxy: average npxG per shot taken.
|
|
61
|
+
- `xa` / `op_xa` / `sp_xa` — expected assists: the xG of the shot a player's
|
|
62
|
+
pass set up (all / open play / set piece).
|
|
63
|
+
- `npxgxa` (season) — non-penalty xG + xA combined goal contribution.
|
|
64
|
+
- `over_under_performance` (season) — actual goal contribution minus expected
|
|
65
|
+
(xG+xA): finishing/creation over- or under-performance.
|
|
66
|
+
- `conversion_ratio` / `penalty_conversion_ratio` — % of (non-penalty / penalty)
|
|
67
|
+
shots converted to goals.
|
|
68
|
+
|
|
69
|
+
## Post-Shot xG (PSxG) and goalkeeping value
|
|
70
|
+
|
|
71
|
+
PSxG models goal probability **after** the shot is struck, using placement and
|
|
72
|
+
velocity — only defined for on-target, unblocked shots. Used to value
|
|
73
|
+
goalkeeping.
|
|
74
|
+
|
|
75
|
+
- `np_psxg` — non-penalty PSxG earned from a player's on-target shots.
|
|
76
|
+
- `npot_psxg_faced` / `np_psxg_faced_90` — non-penalty on-target PSxG faced by a
|
|
77
|
+
goalkeeper.
|
|
78
|
+
- `gsaa` (Goals Saved Above Average) — goals the keeper saved/conceded versus
|
|
79
|
+
expectation (PSxG faced minus goals conceded). `gsaa_ratio` expresses it as a
|
|
80
|
+
share of shots faced. `xs_ratio` (season) — expected save % given PSxG faced.
|
|
81
|
+
- `save_ratio` — % of on-target shots saved.
|
|
82
|
+
- `gk_positioning_error` / `np_optimal_gk_dlength` — average distance of the
|
|
83
|
+
keeper from the modelled optimal position for facing a shot.
|
|
84
|
+
- `da_aggressive_distance` — average distance from goal at which the keeper
|
|
85
|
+
performs defensive actions (sweeping tendency).
|
|
86
|
+
- `ccaa` / `clcaa` — Claimable Collection Attempts over Average: how often the
|
|
87
|
+
keeper attempts to claim a claimable pass vs the average keeper.
|
|
88
|
+
- `claim_success` — % of claim attempts that succeed.
|
|
89
|
+
- `goals_conceded` (player-match) — goals conceded by the keeper, excluding
|
|
90
|
+
penalties and own goals.
|
|
91
|
+
|
|
92
|
+
The Events v8 shot object decomposes shot xG into: `statsbomb_xg` (chance
|
|
93
|
+
quality — pre-strike situation including GK/defender positions),
|
|
94
|
+
`shot_execution_xg` (incorporates placement & velocity),
|
|
95
|
+
`shot_execution_xg_uplift` (`shot_execution_xg − statsbomb_xg`; can be
|
|
96
|
+
negative), `gk_save_difficulty_xg` (renamed from `statsbomb_xg2`; difficulty for
|
|
97
|
+
the keeper given placement/velocity/position), `gk_positioning_xg_suppression`
|
|
98
|
+
and `gk_shot_stopping_xg_suppression` (threat suppressed by keeper positioning /
|
|
99
|
+
shot-stopping). See `xg-model.md`.
|
|
100
|
+
|
|
101
|
+
## PPDA — Passes Per Defensive Action
|
|
102
|
+
|
|
103
|
+
`ppda` (team stats) — how many passes a team allows the opponent before making a
|
|
104
|
+
defensive action (tackle, interception, foul). Lower = more intense pressing.
|
|
105
|
+
StatsBomb defines it in attacking areas: from 40% of pitch length away from the
|
|
106
|
+
pressing team's own goal and forward. `defensive_distance_ppda` is the average
|
|
107
|
+
distance from a team's own goal at which it makes those defensive actions.
|
|
108
|
+
|
|
109
|
+
## Pressing and counterpressing
|
|
110
|
+
|
|
111
|
+
- `pressures` — times a player/team pressures an opponent in possession.
|
|
112
|
+
- `counterpressures` — pressures within 5 seconds of the team losing the ball
|
|
113
|
+
(an open-play turnover).
|
|
114
|
+
- `pressure_regains` / `counterpressure_regains` /
|
|
115
|
+
`defensive_action_regains` — ball won back within 5 seconds of a pressure /
|
|
116
|
+
counterpressure / any defensive action.
|
|
117
|
+
- `pressured_action_fails` / `counterpressured_action_fails` — opponent actions
|
|
118
|
+
forced to fail under (counter)pressure.
|
|
119
|
+
- `aggressive_actions` — tackles, pressures and fouls within 2 seconds of an
|
|
120
|
+
opposition ball receipt. `aggression` — the proportion of an opponent's pass
|
|
121
|
+
receipts so contested.
|
|
122
|
+
- `fhalf_*` — restricted to the opposition (final) half of the pitch;
|
|
123
|
+
`fhalf_*_ratio` expresses it as a share of the player's/team's total.
|
|
124
|
+
- `defensive_distance` — average distance from a team's own goal at which it
|
|
125
|
+
makes defensive actions (higher = higher defensive line / more proactive).
|
|
126
|
+
|
|
127
|
+
## Possession-adjusted defensive metrics (padj_*)
|
|
128
|
+
|
|
129
|
+
`padj_clearances`, `padj_interceptions`, `padj_pressures`, `padj_tackles`,
|
|
130
|
+
`padj_tackles_and_interceptions` (season, per-90) — raw counts adjusted
|
|
131
|
+
proportionally to the team's possession volume, so low-possession teams' high
|
|
132
|
+
raw defensive counts are normalised for fair cross-team comparison.
|
|
133
|
+
|
|
134
|
+
## Progression and territory
|
|
135
|
+
|
|
136
|
+
- `deep_progressions` — passes, dribbles and carries into the opposition final
|
|
137
|
+
third.
|
|
138
|
+
- `deep_completions` — successful passes within ~20 m of the opposition goal.
|
|
139
|
+
- `passes_into_box` / `op_passes_into_box` — successful passes into the box from
|
|
140
|
+
outside it (all / open play).
|
|
141
|
+
- `passes_inside_box` — passes completed both starting and ending in the box.
|
|
142
|
+
- `directness` (team) — distance gained towards goal during a shot-ending
|
|
143
|
+
possession divided by total distance travelled in the build-up (1.0 = perfectly
|
|
144
|
+
direct).
|
|
145
|
+
- `pace_towards_goal` (team) — average build-up speed (m/s) from start of
|
|
146
|
+
possession to shot, for shot-ending possessions.
|
|
147
|
+
- `pass_length` family — `s_pass_length` (avg completed), `p_pass_length` /
|
|
148
|
+
`ps_pass_length` (under pressure), `pass_length_ratio` (completed length ÷
|
|
149
|
+
attempted length), `pressured_change_in_pass_length`.
|
|
150
|
+
- Pass-direction proportions (season) — `forward_pass_proportion`,
|
|
151
|
+
`backward_pass_proportion`, `sideways_pass_proportion` (and `op_f3_*`
|
|
152
|
+
variants). Direction is defined by radian arcs of the pass-angle circle:
|
|
153
|
+
forwards = 11π/6→π/6, backwards = 5π/6→7π/6, sideways = the two remaining
|
|
154
|
+
arcs, where angle 0 = no change in y (towards the opponent goal line).
|
|
155
|
+
|
|
156
|
+
## Line-Breaking Passes (LBP) — requires 360 data
|
|
157
|
+
|
|
158
|
+
A pass is line-breaking when it crosses a defensive line (a row of sufficiently
|
|
159
|
+
close defenders) and makes enough progression toward the centre of the goal.
|
|
160
|
+
360 data also carries this as a per-event `line_breaking_pass` boolean. The
|
|
161
|
+
stats endpoints expose a large LBP suite:
|
|
162
|
+
|
|
163
|
+
- `lbp` / `lbp_completed` / `lbp_ratio` — attempted / completed / success %.
|
|
164
|
+
- `fhalf_*` and `f3_*` — restricted to opposition half / final third.
|
|
165
|
+
- `obv_lbp` — pass-OBV from line-breaking passes.
|
|
166
|
+
- `lbp_received` — line-breaking passes received.
|
|
167
|
+
- `lbp_to_space_{2,5,10}` — completed LBPs whose recipient had >2/5/10 m of
|
|
168
|
+
space; `*_received` variants; `average_lbp_to_space_distance` /
|
|
169
|
+
`*_received_distance` — average space of the recipient.
|
|
170
|
+
|
|
171
|
+
These (and the `ball_receipts_in_space_{2,5,10}`,
|
|
172
|
+
`average_space_received_in`, `*_passes_360`, `*_ball_receipts_360`,
|
|
173
|
+
`360_minutes`) metrics are derived from 360 data and only populated for matches
|
|
174
|
+
that have it. **Per-90 conversion for 360-derived season metrics uses
|
|
175
|
+
`player_season_360_minutes` / `team_season` 360 minutes, not the standard
|
|
176
|
+
minutes field** — see `player-season-stats.md`.
|
|
177
|
+
|
|
178
|
+
## Ball receipts in space (360)
|
|
179
|
+
|
|
180
|
+
- `average_space_received_in` — average value of space for all ball receipts
|
|
181
|
+
(`fhalf_` / `f3_` variants for opposition half / final third).
|
|
182
|
+
- `ball_receipts_in_space_{2,5,10}` — share of ball receipts made with more than
|
|
183
|
+
2/5/10 m of space. The 5 m set is a subset of the 2 m set; the 10 m set is a
|
|
184
|
+
subset of both.
|
|
185
|
+
|
|
186
|
+
## Outcome / involvement scores
|
|
187
|
+
|
|
188
|
+
- `positive_outcome_score` — how frequently the player is involved, while on the
|
|
189
|
+
pitch, in sequences that resolve with a positive outcome (a shot, a free kick
|
|
190
|
+
in the attacking half, or a corner).
|
|
191
|
+
- `positive_outcome` (season count) — possessions that connected through the
|
|
192
|
+
player and ended in such an outcome.
|
|
193
|
+
- `defensive_actions` — tackles, pressure events and fouls recorded
|
|
194
|
+
(`_90` per-90 in season).
|
|
195
|
+
- `shot_touch_ratio` — shots taken as a proportion of touches.
|
|
196
|
+
- `challenge_ratio` — % of duels entered where the player makes a tackle rather
|
|
197
|
+
than being dribbled past. `dribble_faced_ratio` — % of faced dribbles that
|
|
198
|
+
were stopped.
|
|
199
|
+
- `change_in_passing_ratio` (season) — pressured pass % minus overall pass %.
|
|
200
|
+
|
|
201
|
+
## Set-piece breakdown (team stats)
|
|
202
|
+
|
|
203
|
+
Team stats split attacking and conceding output by set-piece type: `corner`,
|
|
204
|
+
`free_kick` (indirect), `direct_free_kick`, `throw_in`, and aggregate `sp`.
|
|
205
|
+
For each: counts, `*_xg`, `xg_per_*`, `shots_from_*`, `goals_from_*`, and
|
|
206
|
+
`*_shot_ratio` / `*_goal_ratio`, each with a `_conceded` mirror. Also
|
|
207
|
+
`counter_attacking_shots` (shots within 15 s of a possession from own half),
|
|
208
|
+
`high_press_shots` (shots from possessions won within 5 s of a defensive action
|
|
209
|
+
in the opposition half), `shots_in_clear` (only the keeper between shooter and
|
|
210
|
+
goal) — all with `_conceded` mirrors.
|
|
211
|
+
|
|
212
|
+
## Suffix conventions
|
|
213
|
+
|
|
214
|
+
- `op_` — open play only (excludes set pieces).
|
|
215
|
+
- `np_` — non-penalty (excludes penalty shots/goals).
|
|
216
|
+
- `sp_` — set piece only.
|
|
217
|
+
- `fhalf_` — opposition (final) half of the pitch.
|
|
218
|
+
- `f3_` — final third.
|
|
219
|
+
- `padj_` — possession-adjusted.
|
|
220
|
+
- `_90` — per 90 minutes (player-season; uses `360_minutes` for 360 metrics).
|
|
221
|
+
- `_pg` — per game (team-season).
|
|
222
|
+
- `_conceded` — the value allowed to/by the opponent (team stats).
|
|
223
|
+
- `*_ratio` — a percentage or proportion.
|