PremiAnalytics Web API

Premier League data, in your code.

Standings, club & player season stats, per-match detail and news over a simple JSON REST API — for your notebooks, bots, dashboards and apps.

Plans & limits

PlanAPI accessRate limitMonthly requests
Data Fan planNot available
Data Supporter plan120 req/min300/mo (resets on the 1st)
Data Ultras plan240 req/minUnlimited*

* “Unlimited” pauses at 5,000 requests/month as a safety check (contact us to lift). We may also temporarily suspend access for safety reviews. Keys stop working on cancellation or downgrade to Data Fan (they work again if you re-subscribe). Rate limits and monthly quotas are subject to change.

See pricing →

All 24 endpoints. Full parameter and response-schema definitions live in the Swagger docs.

League table

The official league table: results, goal difference, last-5 form, attendance and each club’s top scorer.

  • GET /league-table/overall
    Overall table (points, GD, form, top scorer, …)
  • GET /league-table/home-away
    The table split into home and away records

Squad aggregates

Season aggregates per club across four categories: standard, shooting, goalkeeping and miscellaneous.

  • GET /squad/standard-stats
    Goals, assists, minutes and core stats per club
  • GET /squad/shooting
    Shots, on-target %, conversion
  • GET /squad/goalkeeping
    Saves, save %, clean sheets
  • GET /squad/misc-stats
    Cards, fouls, tackles, aerials

Opponent aggregates

What each club *conceded* to its opponents — useful for defensive analysis. Same four categories.

  • GET /opponent/standard-stats
    Conceded goals/assists and core against-stats
  • GET /opponent/shooting
    Shots faced
  • GET /opponent/goalkeeping
    Opposing keepers’ stats
  • GET /opponent/misc-stats
    Opponents’ cards, fouls, …

Player stats

Per-player season aggregates. Filter with club= or player=. Includes per-90 variants.

  • GET /team/standard-stats
    Goals, assists, minutes, per-90s
  • GET /team/shooting
    Shots, SoT, conversion
  • GET /team/playing-time
    Minutes, starts/subs, team +/-
  • GET /team/misc-stats
    Tackles won, interceptions, cards
  • GET /team/goalkeeper-stats
    Keeper aggregates (save %, CS, GA90)

Matches

Per-match data: results and upcoming schedules, plus per-match player stats and minute-by-minute events.

  • GET /matches/fixtures
    Results (score, venue, attendance)
  • GET /matches/fixtures/{match_id}
    A single fixture
  • GET /matches/schedules
    Upcoming (unplayed) matches
  • GET /matches/player-stats
    Per-match player stats
  • GET /matches/keeper-stats
    Per-match keeper stats
  • GET /matches/events
    Goals, cards, subs with minute
  • GET /matches/team-stats
    Per-match team stats (possession, …)

News

Published news articles (JA/EN).

  • GET /news
    Published news list
  • GET /news/{news_id}
    A single article

Common parameters: season (e.g. 25/26; defaults to current), plus club, player, match_id and gameweek filters.

Base URL
https://premie-backend-lvuzwxd3aq-uc.a.run.app/v1
Auth
X-API-Key: pak_…

Issue keys in Settings > Web API

Format
GET / JSON

All endpoints are read-only

Your first request

curl -H "X-API-Key: YOUR_API_KEY" \
  "https://premie-backend-lvuzwxd3aq-uc.a.run.app/v1/league-table/overall"

Query past seasons with ?season=25/26 (omit for the current season). Check your remaining monthly quota via the X-Monthly-Remaining response header.

Integrate it into your code

Ready-to-run implementations in five languages. Copy, set your API key as an environment variable, run.

top_scorers.py
"""PremiAnalytics Web API — 得点ランキング上位5名を表示する例。

事前準備: pip install requests
API キーは環境変数 PREMIA_API_KEY に設定してください。
"""
import os
import time

import requests

BASE_URL = "https://premie-backend-lvuzwxd3aq-uc.a.run.app/v1"
API_KEY = os.environ["PREMIA_API_KEY"]

session = requests.Session()
session.headers["X-API-Key"] = API_KEY


def get(path: str, **params) -> list[dict]:
    """GET リクエスト。429(レート制限)は Retry-After に従い1回だけ再試行する。"""
    for attempt in range(2):
        resp = session.get(f"{BASE_URL}{path}", params=params, timeout=15)
        if resp.status_code == 429 and attempt == 0:
            wait = int(resp.headers.get("Retry-After", "60"))
            print(f"rate limited — {wait}s 待機して再試行します")
            time.sleep(wait)
            continue
        resp.raise_for_status()
        # 月間クォータの残量はレスポンスヘッダーで確認できる
        remaining = resp.headers.get("X-Monthly-Remaining")
        if remaining is not None:
            print(f"(今月の残りリクエスト: {remaining})")
        return resp.json()
    raise RuntimeError("unreachable")


def main() -> None:
    players = get("/team/standard-stats", season="26/27")
    top5 = sorted(players, key=lambda p: (p["gls"] or 0), reverse=True)[:5]
    for i, p in enumerate(top5, start=1):
        print(f"{i}. {p['player']} ({p['club']}) — {p['gls']:g} goals, {p['ast']:g} assists")


if __name__ == "__main__":
    main()

Every sample implements the same task (top 5 scorers of 26/27) with error handling, rate-limit retry and quota checking. Pass your API key via an environment variable — never hard-code it.

Errors & response headers

Status codes

  • 401 Unauthorized
    Missing or invalid X-API-Key header
  • 403 Forbidden
    Valid key but plan not eligible (Fan / cancelled) or key suspended
  • 404 Not Found
    No data for the given id
  • 429 Too Many Requests
    Rate limit or monthly quota exceeded — retry after Retry-After seconds

Quota headers (every response)

  • X-Monthly-Limit
    Your monthly request cap
  • X-Monthly-Used
    Requests used this month
  • X-Monthly-Remaining
    Requests remaining
  • Retry-After
    On 429 only: seconds until retry

Start pulling data

API keys are available on Data Supporter ($6/mo) and above.