How eurocoeff Updates Its Data Daily
One of the most common questions we receive: where does eurocoeff's data come from, and how can I be confident it's accurate? This page describes the data pipeline, sources, and validation steps in detail. We've kept it transparent on purpose — both because trust is the foundation for data sites, and because honest methodology disclosure is central to the UEFA coefficient debate.
Data sources
eurocoeff uses two primary sources for match data:
- football-data.org — an established, licensed API for live match results, standings, and competition data. This delivers real-time updates during CL, EL, and UECL match days.
- 5-jahres-wertung.de — a German sister site that maintains historical UEFA coefficient data going back to the 1970s. This provides the historical baseline for our archives and supplies data derived from official UEFA publications.
We do not scrape uefa.com directly. Instead we work with data providers who source official UEFA data under license, and supplement that with the extensive historical database of 5-jahres-wertung.de.
The pipeline architecture
Here's the exact flow that runs every night and during match days:
- 06:15 UTC daily: A cron job on a Hostinger VPS starts a Docker container with the scraper. The scraper pulls current match results and standings from the sources.
- Database update: Pulled data is written to a PostgreSQL 16 database (eurocoeff-postgres container). This database serves as the source-of-truth and contains the full history of all scrape runs for audit purposes.
- API endpoint: A Fastify API container (eurocoeff-api, port 3210) exposes current data as a JSON endpoint, secured by an API token.
- GitHub Actions trigger: After a successful scrape, the VPS sends a repository_dispatch trigger to the eurocoeff GitHub workflow. That workflow:
-
Build and deploy:
- Pulls current data from the VPS API
- Writes it to
src/data/uefa-data.json - Runs
bun run buildto generate a complete static site - Pushes the build to GitHub
- Cloudflare Pages detects the push and auto-deploys (typically within 2-3 minutes)
During active Champions League, Europa League, or Conference League match days, the pipeline runs more frequently — typically every 30 minutes between 18:00 and 24:00 UTC, to keep live standings and the matchday widget current.
Validation and error handling
Several validation steps prevent corrupt data from reaching the live site:
- JSON schema validation: Before new data is written to the database, the scraper checks structure (all expected fields present, numeric values in plausible range, no nulls in required fields).
- Sanity checks vs. previous values: If an association coefficient changes by more than 5 points compared to the previous snapshot, an alert fires and the build stops. Such jumps are impossible in normal season flow and signal a scraping error.
- Build failure recovery: If the GitHub workflow fails, the last successful build remains live. The site is never deployed with half-baked data.
- Manual correction path: For reported data errors (via the contact page), there's a fast override path. Corrections typically ship within 24 hours.
What we don't do
For transparency, a few deliberate constraints:
- We don't make predictive calculations for unfinished games — league- phase points are only written to the database after the final whistle. That means during an ongoing match the previous standings apply. This is intentional, to avoid showing wrong standings while a match is in progress.
- We don't have live betting odds. eurocoeff is a pure data and analysis site, not a betting or tipping platform.
- We don't generate future match outcomes through prediction models in the 5-year ranking. The "what-if simulator" on the main page is explicitly designed as a manual input tool — you choose a scenario, we show the consequence.
Accuracy and known limits
Values on eurocoeff typically match official UEFA values to two decimal places. Discrepancies can occur in the following cases:
- Day of result verification: When UEFA officially corrects a match result (rare but possible), eurocoeff can take up to 24 hours for the correction to be reflected.
- Penalty point deductions: UEFA occasionally imposes point deductions on clubs (FFP violations, behind-closed-doors matches). These are manually maintained and not automated.
- Early-season disambiguation: In the first weeks of a new season there can be small discrepancies until all qualifying rounds are fully ingested into our database.
Technical architecture (summary)
For technically interested readers, the stack overview:
- VPS pipeline: Hostinger VPS, Docker Compose, PostgreSQL 16, Fastify API
- CI/CD: GitHub Actions, repository_dispatch trigger
- Frontend: React 18, Vite 5, TypeScript, Tailwind CSS
- Hosting: Cloudflare Pages (static), automatic deploy on main branch
- Data format: Single-file JSON snapshot (~720 KB), bundled at build time
More architectural detail is on the About page.
Feedback and corrections
If you find a data inaccuracy or have a methodology suggestion, email us at [email protected]. We take corrections seriously and are transparent when we introduce an error — the next snapshot reflects the correction.