# Overview

Source: https://www.pitchkitjs.com/docs/data

> Load real open football data in one call — and when not to bother.

`@pitchkit/data-providers` takes you from a match id to chart-ready data without a pipeline in
between. It's a separate, optional package with no dependency on `@pitchkit/core` or
`@pitchkit/react` — its only runtime dependency is `csv-parse`, for SkillCorner's CSV files.

```bash
npm install @pitchkit/data-providers
```

```tsx
import { fetchMatchEvents, shots, isGoal } from "@pitchkit/data-providers/statsbomb";
import { Scatter, VerticalPitch } from "@pitchkit/react";

const events = await fetchMatchEvents(3943043); // Spain 2–1 England, Euro 2024 final
const spain = shots(events).filter((shot) => shot.team.name === "Spain");

<VerticalPitch type="statsbomb">
  <Scatter
    data={spain}
    x={(s) => s.x}
    y={(s) => s.y}
    fill={(s) => (isGoal(s) ? "orange" : "steelblue")}
  />
</VerticalPitch>;
```

That's the whole path. No adapter, no field mapping, no coordinate conversion.

## You probably don't need this

PitchKit's layers take **accessor functions**, so they already read whatever shape your data is
in — that's the point of the [coordinates guide](/docs/guides/coordinates). If you have your
own pipeline, point `x`/`y` at your own fields and skip this package entirely. Nothing in
`@pitchkit/react` depends on it.

It exists for the cases where fetching real data is the friction: tutorials, prototypes,
learning the API, and agent-assisted builds where a complete runnable example beats a schema
description.

## How the loaders are shaped

Four layers, each usable on its own:

| Layer              | What it does                                                                                   |
| ------------------ | ---------------------------------------------------------------------------------------------- |
| `parse*`           | Pure — already-loaded JSON in, typed objects out. No network.                                  |
| `load*` / `fetch*` | Fetch and parse in one call. `load*` takes any URL; `fetch*` builds the open-data URL for you. |
| Selectors          | Narrow a mixed feed: `shots()`, `passes()`, `carries()`, `ofType()`.                           |
| Predicates         | Compose with `.filter()`: `isGoal`, `isComplete`, `isCorner`, `isCross`, …                     |

Two principles run through all of it, and they're worth knowing before you read the provider
pages:

**The provider's data stays the provider's.** Field names keep their original spelling, values
keep their original strings — a StatsBomb outcome is `"Off T"`, not a re-spelled
`"off-target"`. You can read StatsBomb's own spec alongside these types with no mapping table
in between. The one exception is coordinates: `location` arrays are *also* surfaced as
`x`/`y`/`endX`/`endY`, because that's what a PitchKit accessor wants.

**Interpretation lives in functions, not fields.** There's no invented `complete: boolean` on a
pass — there's an `isComplete(pass)` you apply. The data stays a faithful record; the reading
of it is opt-in and inspectable. It also covers what a per-event-type accessor structurally
can't: a corner isn't a StatsBomb event type, it's a *kind of pass*, so it can only be a
predicate.

## Providers

* **[StatsBomb](/docs/data/statsbomb/events)** — open data: competitions, matches, lineups,
  [events](/docs/data/statsbomb/events) and [360 tracking](/docs/data/statsbomb/360).
  * Source: [statsbomb/open-data](https://github.com/statsbomb/open-data) ·
    [specifications](https://github.com/statsbomb/open-data/tree/master/doc) ·
    [free data hub](https://statsbomb.com/what-we-do/hub/free-data/)
* **[SkillCorner](/docs/data/skillcorner/tracking)** — broadcast tracking at 10 fps, plus the
  derived [dynamic events](/docs/data/skillcorner/dynamic-events) and
  [phases of play](/docs/data/skillcorner/phases-of-play).
  * Source: [SkillCorner/opendata](https://github.com/SkillCorner/opendata) ·
    [documentation](https://skillcorner.github.io/opendata/) ·
    [skillcorner.com](https://skillcorner.com/)
* **[Wyscout](/docs/data/wyscout/events)** — the Pappalardo et al. dataset: 1,941 matches of
  event data across the 2017/18 big-five leagues, plus World Cup 2018 and Euro 2016.
  * Source: [figshare collection](https://figshare.com/collections/Soccer_match_event_dataset/4415000) ·
    [data paper](https://www.nature.com/articles/s41597-019-0247-7) ·
    [event mirror](https://github.com/koenvo/wyscout-soccer-match-event-dataset)

SkillCorner also has its own pitch type. Its coordinates are metres from the centre spot, so
`<Pitch type="skillcorner">` plots them raw — no lifting, no conversion:

```tsx
<Pitch type="skillcorner" dimensions={{ length: match.pitch_length, width: match.pitch_width }}>
  <Scatter data={frame.player_data} x={(p) => p.x} y={(p) => p.y} />
</Pitch>
```

Wyscout has its own pitch type too — a 0–100 percentage grid like Opta's, but with a
different origin: top-left with y increasing downward, where Opta's is bottom-left with y
increasing upward. `<Pitch type="wyscout">` plots its coordinates raw:

```tsx
<Pitch type="wyscout">
  <Scatter data={shots} x={(s) => s.x} y={(s) => s.y} />
</Pitch>
```

## Licensing

This package ships **no data** — it fetches from whatever URL you give it. The default URLs
point at each provider's own open-data repository, and **every provider asks to be credited**
in anything you publish from their data:

* **StatsBomb** —
  [open-data](https://github.com/statsbomb/open-data) is released under StatsBomb's own user
  agreement rather than an OSI licence. Read the
  [usage terms](https://statsbomb.com/what-we-do/hub/free-data/free-data-usage-terms/) before
  you rely on it.
* **SkillCorner** — [opendata](https://github.com/SkillCorner/opendata) is MIT-licensed, and
  SkillCorner ask for credit and a mention when you publish work built on it.
* **Wyscout** — the [Pappalardo et al. dataset](https://www.nature.com/articles/s41597-019-0247-7)
  is CC BY 4.0, the most permissive of the three; cite the paper in anything you publish. Its
  official release (figshare) has no per-match JSON file, so events are fetched from a
  community mirror that splits the same archive per match with no field renamed — the
  reference files (competitions, teams, players) come from figshare directly.
