From Web
Access Web content
https://csgfantasy.com/
No sign-in is needed. Anonymous is right.
https://csgfantasy.com/api/v1Spec openapi.jsonTip add ?format=csv to any tableLimit 120 requests a minute. Repeat offenders get a time-out.No code. You paste five links, connect one key, and start dragging fields. About ten minutes.
Get it from the Microsoft Store (search Power BI Desktop) or from powerbi.microsoft.com/desktop. Open it and close the welcome screen. You are looking at a blank report.
Every table below is a link. Power BI reads it as a spreadsheet. Here is the click path, drawn out:
https://csgfantasy.com/api/v1/teams?format=csv
https://csgfantasy.com/api/v1/scores?format=csv
https://csgfantasy.com/api/v1/schedule?format=csv
https://csgfantasy.com/api/v1/weekly?format=csv
https://csgfantasy.com/api/v1/superbowl?format=csv
When all five are in, the Data pane on the right lists Teams, Scores, Schedule, WeeklyWinners, SuperBowl. That is your model.
Every table carries a gold teamKey column (league id plus team id), so a team is one thing across all eight leagues. Power BI usually spots the match and draws the lines itself. To check, open the Model view: the third icon on the left rail.
Power BI sums numbers on its own, so none of this needs a formula. When you want more, here are a few measures to paste in with Modeling New measure.
Total Points = SUM ( Scores[points] ) Games Played = CALCULATE ( COUNTROWS ( Scores ), Scores[final] = TRUE (), NOT ISBLANK ( Scores[points] ) ) Points per Game = DIVIDE ( [Total Points], [Games Played] ) Win % = DIVIDE ( CALCULATE ( COUNTROWS ( Scores ), Scores[result] = "W" ), [Games Played] ) Bench Points = SUM ( Scores[bench] ) Week High = CALCULATE ( MAX ( Scores[points] ), ALLEXCEPT ( Scores, Scores[week] ) ) PF Rank (all 80) = RANKX ( ALL ( Teams[teamKey] ), [Total Points], , DESC, DENSE ) Points vs Field Avg = [Points per Game] - CALCULATE ( [Points per Game], ALL ( Scores ) )
8 Home Refresh pulls the latest numbers. The site itself refreshes from ESPN about every ten minutes, so during games that is how live it gets.
Publish to the Power BI service and set a scheduled refresh under the dataset settings. Because the source is public web data, no gateway is needed. Set the web credentials to Anonymous, and if the connection test complains, tick Skip test connection.
If you would rather build it as code, add a blank query, open Advanced Editor, paste this, and name it CSG. Then each table is a one-liner like CSG("scores"). Using RelativePath and Query keeps the service happy on scheduled refresh, and a season parameter is one more field in the Query record.
(endpoint as text) as table =>
let
Raw = Web.Contents("https://csgfantasy.com", [RelativePath = "api/v1/" & endpoint, Query = [format = "csv"]]),
Csv = Csv.Document(Raw, [Delimiter = ",", Encoding = 65001, QuoteStyle = QuoteStyle.Csv]),
Table = Table.PromoteHeaders(Csv, [PromoteAllScalars = true])
in
TablePast seasons through the links: add &season=2025 to any of them.
Every table has a link. A spreadsheet can open a link. That is the whole tutorial.
https://csgfantasy.com/api/v1/teams?format=csv
https://csgfantasy.com/api/v1/rosters?format=csv
https://csgfantasy.com/api/v1/scores?format=csv
https://csgfantasy.com/api/v1/weekly?format=csv
Type this in cell A1. Sheets fills the table and re-fetches on its own about once an hour.
=IMPORTDATA("https://csgfantasy.com/api/v1/teams?format=csv")Swap teams for rosters, scores, points-leaders, weekly, superbowl, schedule, or leagues/CSG2/standings. Add &season=2025 for last year.
Python, R, a notebook, a cron job: plain JSON and CSV over HTTPS with open CORS.
import pandas as pd
scores = pd.read_csv("https://csgfantasy.com/api/v1/scores?format=csv")Subscribe once. Every matchup lands on your calendar with the opponent and projections in the title, the score and result once it is played, a Friday morning lineup reminder, and the $10 winner each Tuesday. It updates itself. You never open anything.
The Subscribe button uses a webcal:// link, which Outlook, Apple Calendar, and most phones understand. Google Calendar wants the plain link pasted into Add by URL.
A whole league, five games a week: https://csgfantasy.com/api/v1/leagues/CSG2/calendar.ics (swap CSG2 for yours).
Only the Tuesday $10 winners, across all 80 teams:
https://csgfantasy.com/api/v1/calendar/weekly-winners.ics
Every unplayed matchup carries an alarm for Friday at 8 AM Central, two days before Sunday's slate. Once the game is played, the title becomes the score and the reminder goes away.
Once ESPN finalizes a week, the top score across all eight leagues appears on the Tuesday after, on every feed. Yes, even on the feeds of the people who lost.
Every team has a link. Send someone theirs and they are subscribed in one tap. Pick their team above, copy, paste into the group chat. The commissioner's Tuesday winner event is the same on everyone's calendar, which settles a surprising number of arguments.
Four ways to get the numbers on a phone, from zero setup to a real dashboard. Pick the one that matches how much you like fiddling.
The site is built for phones. Added to the home screen it gets an icon and opens full screen like an app.
Build the sheet once on a computer, then it is a live spreadsheet in the Google Sheets app. Sheets refreshes the data on its own about once an hour, and pull-to-refresh in the app checks again.
=QUERY(IMPORTDATA("https://csgfantasy.com/api/v1/points-leaders?format=csv"), "select E,B,G,H,J order by H desc limit 10", 1)=IMPORTDATA("https://csgfantasy.com/api/v1/weekly?format=csv")=QUERY(IMPORTDATA("https://csgfantasy.com/api/v1/leagues/CSG2/standings?format=csv"), "select E,G,I,J,K order by I desc", 1)Swap CSG2 for your league. Add &season=2025 inside the link for last year. The column letters above match the CSV column order: E team, G record, H points for, I points against, J average.
A Shortcut that reads the digest out loud, shows it, or drops it in a widget. The API has a phone-sized summary endpoint that returns plain text, so the Shortcut is two steps.
https://csgfantasy.com/api/v1/summary?format=text
https://csgfantasy.com/api/v1/summary?format=text&league=CSG2
latestWinner, then Show Notification.https://csgfantasy.com/api/v1/summary
Install HTTP Shortcuts (free, open source, on Google Play and F-Droid). It puts a web request on your home screen as an icon or widget.
https://csgfantasy.com/api/v1/summary?format=text
Tasker users: an HTTP Request action to the same URL, then Say with %http_data, on a Tuesday 8:00 profile. Android widgets like KWGT can also read the JSON form directly.
If you followed the Power BI tutorial, the report you built can live on your phone with live data.
Excel on the phone can open the workbook from the spreadsheet tab too, but it cannot refresh a web query on its own. Refresh on the computer and the phone sees the saved numbers.
Every one of these works. Whether it should is between you and your conscience.
Base R reads the link directly. Six lines to a chart of every team's weekly points.
scores <- read.csv("https://csgfantasy.com/api/v1/scores?format=csv")
teams <- read.csv("https://csgfantasy.com/api/v1/teams?format=csv")
# points per game, best first
aggregate(points ~ team + league, data = scores, FUN = mean) |> (\(d) d[order(-d$points), ])() |> head(10)
# every team, every week, one line each (ggplot2)
library(ggplot2)
ggplot(scores, aes(week, points, group = teamKey, colour = league)) + geom_line(alpha = .6) + theme_minimal()Install DuckDB, then query the links like tables. No import step at all.
INSTALL httpfs; LOAD httpfs;
SELECT team, league, round(avg(points), 1) AS ppg, sum(bench) AS bench_regret
FROM read_csv_auto('https://csgfantasy.com/api/v1/scores?format=csv')
WHERE final
GROUP BY 1, 2
ORDER BY ppg DESC
LIMIT 10;One line. A sortable, filterable grid of all 80 teams appears. Works on any Windows box with no install.
Invoke-RestMethod "https://csgfantasy.com/api/v1/teams" | Select-Object -ExpandProperty teams | Out-GridView -Title "CSG Fantasy"
Swap teams for scores and -ExpandProperty scores for the week-by-week view.
Make the computer announce the points leaders out loud, with a bar chart in the console. Turn your speakers up in the office first. Or do not.
$top = (Invoke-RestMethod "https://csgfantasy.com/api/v1/points-leaders").leaders | Select-Object -First 5
Add-Type -AssemblyName System.Speech
$voice = New-Object System.Speech.Synthesis.SpeechSynthesizer
$voice.Speak("C S G Fantasy Football. Points leaders.")
$i = 1
foreach ($t in $top) {
$bar = "#" * [math]::Max(1, [math]::Round($t.pointsFor / 10))
$color = @("Yellow", "Cyan", "Green", "Magenta", "White")[$i - 1]
Write-Host ("{0}. {1,-30} {2,8:N1} {3}" -f $i, $t.team, $t.pointsFor, $bar) -ForegroundColor $color
$voice.Speak(("Number {0}. {1}, from {2}, with {3:N0} points." -f $i, $t.team, $t.league, $t.pointsFor))
$i++
}
$voice.Speak("The commissioner has final say.")Open Microsoft Copilot, paste a link, and ask it questions in English. It reads the CSV and does the math. This is either the future or the end of analytics, and it works today.
Read https://csgfantasy.com/api/v1/scores?format=csv and tell me which team has left the most points on the bench this season, and who the unluckiest team is (high points, low wins).
Copilot in Excel: after loading a table with Data › From Web, open Copilot and ask "rank these teams by points and highlight the top five". Same data, no formulas, questionable but effective.
Python, if you insist on being normal:
import pandas as pd
scores = pd.read_csv("https://csgfantasy.com/api/v1/scores?format=csv")
print(scores.groupby(["league", "team"])["points"].mean().sort_values(ascending=False).head(10))