This project aims to predict Fantasy Premier League points for players using various data analysis and machine learning techniques.
This project is guided by GitHub Copilot, an AI-powered coding assistant that helps developers write code faster and with fewer errors.
The main goal of this project is to create a model that can accurately predict the points that players will score in the Fantasy Premier League. This can help fantasy football managers make better decisions when selecting their teams.
- ML-based Point Predictions: Uses expected goals (xG), expected assists (xA), clean sheets, and head-to-head data
- Opponent Analysis: Enriches players with opponent difficulty and fixture information
- Gameweek Forecasting: Predict player performance for future gameweeks
- Player Value Tracking: Track purchase prices vs current prices for all players
- Selling Price Calculation: Automatically calculates selling price with profit rules (keep 50% of profit, rounded down)
- Squad History: Store and view squad snapshots for each gameweek
- Database Caching: Reduce API calls by storing team data locally
- Recommended Transfers Price Display: Shows purchase price, current market value, and selling price for players being transferred out
- Free Transfer Management: Track free transfers (1 per week, max 2 banked)
- Points Deduction: Automatic calculation of -4 points for extra transfers
- Transfer History: Complete record of all transfers made
- Transfer Validation: Ensures valid position swaps and sufficient funds
- All FPL Chips Supported: Wildcard, Free Hit, Bench Boost, Triple Captain
- Availability Windows: Chips available at correct times (GW1-19, GW20-38)
- Usage Tracking: Track which chips have been used
- Chip Rules Enforcement:
- One chip per gameweek
- Free Hit cannot be used in consecutive gameweeks
- Saved transfers retained when using Wildcard/Free Hit
- Wildcard and Free Hit cannot be cancelled once confirmed
- Mock Data Support: Test without FPL API access using local mock data
- RESTful API: Clean, documented API endpoints
- Authentication & Security:
- JWT-based authentication
- NoSQL injection protection via input validation
- SSRF protection via URL whitelisting
- 4-tier rate limiting (auth, general API, read, write operations)
This application is hosted on Vercel and is configured via the vercel.json in the repository root. Vercel automatically deploys on every push to the main branch.
Vercel serves the React frontend as a static site and routes /api/* requests to a serverless Node.js function running the Express backend — all from a single deployment.
- Fork this repository and import it into your Vercel dashboard.
- Add the following environment variables in your Vercel project settings:
| Variable | Required | Description |
|---|---|---|
JWT_SECRET |
Yes | Secret for JWT token signing (see below) |
FRONTEND_URL |
No | Your Vercel deployment URL (for CORS) |
- Deploy — Vercel will run
npm install && npm run buildin thefrontenddirectory automatically.
Generate a secure JWT secret:
openssl rand -base64 32
See the Installation and Running the Application sections below.
You can also self-host on Render as two separate services.
- Create a new Web Service on Render
- Connect your GitHub repository and set the Root Directory to
backend - Configure the service:
- Runtime: Node
- Build Command:
npm install - Start Command:
npm start
- Add the following environment variables:
JWT_SECRET— A strong random secret (generate withopenssl rand -base64 32)FRONTEND_URL— The URL of your deployed frontend (e.g.https://your-app.onrender.com)PORTis automatically provided by Render
- Create a new Static Site on Render
- Connect your GitHub repository and set the Root Directory to
frontend - Configure the site:
- Build Command:
npm install && npm run build - Publish Directory:
dist
- Build Command:
- Add the following environment variable:
VITE_API_URL— The URL of your deployed backend (e.g.https://your-backend.onrender.com)
In production, the frontend reads VITE_API_URL and uses it as the base URL for all API requests. In local development, Vite's proxy handles /api requests to localhost:5000 and VITE_API_URL can be left empty.
backend/ # Express.js backend (API, FPL data proxy)
controllers/ # Backend controllers (business logic)
models/ # FPL data models and prediction logic
routes/ # Express route definitions
server.js # Backend entry point
frontend/ # React frontend (UI)
public/ # Static assets and index.html
src/ # Source code for React app
components/ # React components
hooks/ # Custom React hooks
App.js # Main React app
index.jsx # React entry point
package.json # Root scripts for running both frontend and backend together
vercel.json # Vercel deployment configuration
- Node.js (v18 or higher)
- npm (v8 or higher)
The backend supports several environment variables to configure behavior:
JWT_SECRET- Secret key for JWT token generation (required in production, defaults to 'changeme' in development)⚠️ Must be set to a secure random value in production- Generate with:
openssl rand -base64 32
USE_FPL_API- Controls data source for FPL data (default:'true')'true'- Use real FPL API (fantasy.premierleague.com)'false'- Use local mock data for testing (useful when API is unavailable or for development)
USE_COMPUTED_EP- Toggle between computed vs raw expected points (default:'true')'true'- Use computed expected points from ML model'false'- Use raw API expected points
INCLUDE_MANAGERS- Include manager placeholders in squads (default:'false')
Create a .env file in the backend directory:
# Example .env file
JWT_SECRET=your-secret-key-here
USE_FPL_API=true
USE_COMPUTED_EP=true
INCLUDE_MANAGERS=falseFor testing without FPL API access:
USE_FPL_API=falseThis will use mock data from backend/mockData/ that matches the exact structure of FPL API responses.
-
Clone the repository:
git clone https://github.com/ryanhall23/fpl-predictor.git cd fpl-predictor -
Install dependencies for all packages (npm workspaces handles frontend and backend automatically):
npm install
You can start both the backend and frontend together from the root directory:
npm start- This will run the backend on http://localhost:5000 and the frontend on http://localhost:5173.
Alternatively, to run them separately:
- Start the backend:
npm run start-backend
- In a new terminal, start the frontend:
npm run start-frontend
The backend provides comprehensive REST API endpoints for squad management, transfers, and chips.
Squad Management:
POST /api/squad/initialize- Initialize user's squad from FPL accountGET /api/squad/:userId- Get current squad with calculated valuesGET /api/squad/history/:userId/:gameweek- Get squad for specific gameweek
Transfers:
POST /api/transfers- Make a player transferGET /api/transfers/history/:userId- Get transfer historyGET /api/transfers/summary/:userId/:gameweek- Get gameweek transfer summary
Chips:
GET /api/chips/:userId?gameweek=N- Get available chips for gameweekPOST /api/chips/activate- Activate a chipPOST /api/chips/cancel- Cancel an active chip (if allowed)
FPL Data:
GET /api/bootstrap-static- All players, teams, and gameweeksGET /api/predicted-team- AI-predicted optimal teamGET /api/entry/:entryId/event/:eventId/recommended-transfers- Smart transfer suggestions
For complete API documentation, see backend/API_DOCUMENTATION.md
The application implements FPL's player pricing rules:
- Purchase Price: Price when player was added to squad
- Current Price: Live market price from FPL API
- Selling Price:
Purchase Price + floor((Current Price - Purchase Price) / 2)
Example:
- Bought player at £7.5m
- Current price rises to £7.8m
- Profit = £0.3m
- Selling price = £7.5m + floor(£0.3m / 2) = £7.5m + £0.1m = £7.6m
- 1 Free Transfer per gameweek (unused transfers carry over, max 2)
- -4 Points for each additional transfer beyond free transfers
- Wildcard: All transfers free for the gameweek
- Free Hit: Unlimited free transfers, squad reverts next gameweek
| Chip | Effect | Availability |
|---|---|---|
| Bench Boost | Bench players' points count | 2 chips: GW1-19, GW20-38 |
| Triple Captain | Captain points tripled (3x) | 2 chips: GW1-19, GW20-38 |
| Free Hit | Unlimited free transfers, reverts next GW | 2 chips: GW2-19, GW20-38 |
| Wildcard | All transfers free for the gameweek | 2 chips: GW2-19, GW20-38 |
Rules:
- Only one chip per gameweek
- Free Hit cannot be used in consecutive gameweeks
- Wildcard and Free Hit cannot be cancelled once confirmed
- Bench Boost and Triple Captain can be cancelled before deadline
- Saved free transfers are retained when using Wildcard or Free Hit