If you're actively solving DSA problems across multiple platforms (LeetCode, GeeksforGeeks, Codeforces, TakeUForward) and also contributing to GitHub, wouldn't it be amazing to have one unified dashboard showing all your coding stats? In this tutorial, I'll show you how I built a Complete Coding Stats Aggregator that combines:
- DSA Stats from Codolio (LeetCode, GFG, Codeforces, etc.)
- TakeUForward progress separately
- GitHub Activity (commits, stars, PRs, active days)
All exported to a single coding-stats.json file!
π― What We're Building
A Python script that:
- β Fetches coding stats from Codolio API (all platforms except TUF)
- β Fetches TakeUForward stats separately (to avoid duplication)
- β Fetches GitHub activity stats from Codolio's GitHub proxy
- β
Combines everything into
coding-stats.json - β Categorizes DSA problems by difficulty: Easy, Medium, Hard
π Step 1: Reverse Engineering the APIs
1.1 Finding the Codolio API
Goal: Get your DSA stats from all platforms (except TUF)
- Open Codolio Profile: Go to codolio.com and log in
-
Open Developer Tools:
- Windows/Linux:
F12orCtrl+Shift+I - Mac:
Cmd+Option+I
- Windows/Linux:
- Go to Network Tab: Click on the "Network" tab
-
Reload the Page: Press
Ctrl+R(Windows/Linux) orCmd+R(Mac) - Filter Requests: Type "user" in the filter box
-
Locate the API Call: Look for a request to
https://api.codolio.com/user -
Extract Headers:
- Click on the request
- Go to "Headers" section
- Find
authorizationheader - Copy the entire Bearer token (starts with
Bearer eyJ...)
API Endpoint: https://api.codolio.com/user
What you need:
- Authorization token (Bearer token from headers)
1.2 Finding the TakeUForward API
Goal: Get your TUF-specific stats
-
Open Your TUF Profile: Visit
https://takeuforward.org/profile/YOUR_USERNAME -
Open Developer Tools:
F12 - Go to Network Tab: Click "Network"
-
Reload Page:
Ctrl+R - Filter: Type "dsa-progress"
- Find the Endpoint: Look for:
https://backend-go.takeuforward.org/api/v1/shared/profile/dsa-progress/YOUR_USERNAME
API Endpoint: https://backend-go.takeuforward.org/api/v1/shared/profile/dsa-progress/{username}
What you need:
- Your TUF username (no authentication required!)
1.3 Finding the GitHub Stats API (via Codolio)
Goal: Get GitHub activity stats
- On Codolio Profile: Make sure your GitHub is connected
-
Open Developer Tools:
F12 - Network Tab: Click "Network"
- Navigate to GitHub Section: Click on your GitHub stats in Codolio
- Filter: Type "github"
- Find the Endpoint: Look for:
https://api.codolio.com/github/profile?userKey=YOUR_PROFILE_NAME
API Endpoint: https://api.codolio.com/github/profile?userKey={profileName}
What you need:
- Your Codolio profile name (username)
π οΈ Step 2: Understanding the Data Structures
2.1 Codolio Response (DSA Stats)
{
"data": {
"platformProfiles": {
"platformProfiles": [
{
"platform": "leetcode",
"totalQuestionStats": {
"easyQuestionCounts": 150,
"mediumQuestionCounts": 200,
"hardQuestionCounts": 50,
"totalQuestionCounts": 400
}
},
{
"platform": "gfg",
"totalQuestionStats": {
"basicQuestionCounts": 100,
"schoolQuestionCounts": 50,
"easyQuestionCounts": 120,
"mediumQuestionCounts": 80,
"hardQuestionCounts": 30,
"totalQuestionCounts": 380
}
},
{
"platform": "tuf",
"totalQuestionStats": { /* we skip this */ }
}
]
}
}
}
Key Points:
- Contains multiple platforms in one response
- Some platforms (like GFG) have
basicQuestionCountsandschoolQuestionCountsβ treat as Easy - TUF is included but we skip it to avoid double-counting
2.2 TakeUForward Response
{
"data": {
"data": {
"solvedEasy": 45,
"solvedMedium": 60,
"solvedHard": 15,
"totalSolved": 120
}
}
}
2.3 GitHub Response (via Codolio)
{
"data": {
"githubProfile": "naman08",
"stars": 42,
"issues": 15,
"totalActiveDays": 365,
"pushRequestsCount": 89,
"totalContributions": 1247
}
}
π» Step 3: Writing the Complete Aggregator Script
3.1 Install Required Package
pip install requests
3.2 The Complete Script
Create a file aggregator.py:
import requests
import json
import os
# =========================
# 1οΈβ£ CODOLIO (ALL EXCEPT TUF)
# =========================
codolio_url = "https://api.codolio.com/user"
codolio_headers = {
"authorization": "Bearer YOUR_TOKEN_HERE", # π₯ REPLACE THIS
"accept": "*/*",
"referer": "https://codolio.com/"
}
res = requests.get(codolio_url, headers=codolio_headers)
if res.status_code != 200:
print("β Codolio Error:", res.status_code)
exit()
data = res.json()
platforms = data["data"]["platformProfiles"]["platformProfiles"]
codolio_easy = codolio_medium = codolio_hard = codolio_total = 0
for p in platforms:
if p.get("platform") == "tuf":
continue # β Skip TUF to avoid duplicates
q = p.get("totalQuestionStats")
if not q:
continue
# Standard difficulty counts
codolio_easy += q.get("easyQuestionCounts") or 0
codolio_medium += q.get("mediumQuestionCounts") or 0
codolio_hard += q.get("hardQuestionCounts") or 0
# Platform-specific easy categories (GFG, etc.)
# Treat "basic" and "school" level as Easy
codolio_easy += q.get("basicQuestionCounts") or 0
codolio_easy += q.get("schoolQuestionCounts") or 0
codolio_total += q.get("totalQuestionCounts") or 0
print(f"β
Codolio: {codolio_total} problems")
# =========================
# 2οΈβ£ TUF OFFICIAL API
# =========================
tuf_url = "https://backend-go.takeuforward.org/api/v1/shared/profile/dsa-progress/YOUR_USERNAME" # π₯ REPLACE
tuf_headers = {
"accept": "application/json, text/plain, */*",
"origin": "https://takeuforward.org",
"referer": "https://takeuforward.org/"
}
res = requests.get(tuf_url, headers=tuf_headers)
if res.status_code != 200:
print("β TUF Error:", res.status_code)
exit()
tuf_data = res.json()["data"]["data"]
tuf_easy = tuf_data["solvedEasy"]
tuf_medium = tuf_data["solvedMedium"]
tuf_hard = tuf_data["solvedHard"]
tuf_total = tuf_easy + tuf_medium + tuf_hard
print(f"β
TUF: {tuf_total} problems")
# =========================
# 3οΈβ£ FINAL DSA COMBINED
# =========================
final_easy = codolio_easy + tuf_easy
final_medium = codolio_medium + tuf_medium
final_hard = codolio_hard + tuf_hard
final_total = final_easy + final_medium + final_hard
print(f"π Total DSA: {final_total} problems")
# =========================
# 4οΈβ£ GITHUB STATS (FROM CODOLIO)
# =========================
github_url = "https://api.codolio.com/github/profile?userKey=YOUR_PROFILE_NAME" # π₯ REPLACE
github_headers = {
"accept": "*/*",
"referer": "https://codolio.com/"
}
try:
res = requests.get(github_url, headers=github_headers, timeout=15)
if res.status_code != 200:
raise Exception(f"GitHub API error {res.status_code}")
github_json = res.json()
gh = github_json.get("data", {}) # β
Extract the "data" object
github_data = {
"githubProfile": gh.get("githubProfile"),
"stars": gh.get("stars", 0),
"issues": gh.get("issues", 0),
"totalActiveDays": gh.get("totalActiveDays", 0),
"pushRequestsCount": gh.get("pushRequestsCount", 0),
"commits": gh.get("totalContributions", 0)
}
print(f"β
GitHub: {github_data['commits']} commits")
except Exception as e:
print(f"β οΈ GitHub fetch failed: {e}")
github_data = {}
# =========================
# 5οΈβ£ COMBINE & EXPORT JSON
# =========================
output = {
"codolio": {
"easy": codolio_easy,
"medium": codolio_medium,
"hard": codolio_hard,
"total": codolio_total
},
"tuf": {
"easy": tuf_easy,
"medium": tuf_medium,
"hard": tuf_hard,
"total": tuf_total
},
"final": {
"easy": final_easy,
"medium": final_medium,
"hard": final_hard,
"total": final_total
},
"github": github_data
}
# Create public directory if it doesn't exist
os.makedirs("public", exist_ok=True)
with open("public/coding-stats.json", "w") as f:
json.dump(output, f, indent=2)
print("\nπ coding-stats.json generated successfully!")
print(f"π Location: public/coding-stats.json")
3.3 Replace Placeholders
Before running, replace:
-
Line 10:
YOUR_TOKEN_HEREβ Your Codolio Bearer token -
Line 44:
YOUR_USERNAMEβ Your TakeUForward username -
Line 73:
YOUR_PROFILE_NAMEβ Your Codolio profile name (e.g.,naman08)
π€ Step 4: Run the Script
python aggregator.py
Expected Output:
β
Codolio: 630 problems
β
TUF: 120 problems
π Total DSA: 750 problems
β
GitHub: 1247 commits
π coding-stats.json generated successfully!
π Location: public/coding-stats.json
Generated File (public/coding-stats.json):
{
"codolio": {
"easy": 270,
"medium": 280,
"hard": 80,
"total": 630
},
"tuf": {
"easy": 45,
"medium": 60,
"hard": 15,
"total": 120
},
"final": {
"easy": 315,
"medium": 340,
"hard": 95,
"total": 750
},
"github": {
"githubProfile": "naman08",
"stars": 42,
"issues": 15,
"totalActiveDays": 365,
"pushRequestsCount": 89,
"commits": 1247
}
}
π Step 5: Automate with GitHub Actions
Create .github/workflows/update-stats.yml:
name: Update Coding Stats
on:
schedule:
- cron: '0 0 * * *' # Run daily at midnight UTC
workflow_dispatch: # Allow manual trigger
jobs:
update-stats:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install dependencies
run: pip install requests
- name: Run aggregator script
env:
CODOLIO_TOKEN: ${{ secrets.CODOLIO_TOKEN }}
TUF_USERNAME: ${{ secrets.TUF_USERNAME }}
CODOLIO_PROFILE: ${{ secrets.CODOLIO_PROFILE }}
run: |
# Replace placeholders in script
sed -i "s/YOUR_TOKEN_HERE/$CODOLIO_TOKEN/g" aggregator.py
sed -i "s/YOUR_USERNAME/$TUF_USERNAME/g" aggregator.py
sed -i "s/YOUR_PROFILE_NAME/$CODOLIO_PROFILE/g" aggregator.py
# Run the script
python aggregator.py
- name: Commit and push changes
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add public/coding-stats.json
git diff --staged --quiet || git commit -m "π Update coding stats [$(date +'%Y-%m-%d')]"
git push
Add GitHub Secrets
Go to your repository β Settings β Secrets and variables β Actions β New repository secret:
-
CODOLIO_TOKEN: Your Bearer token (without "Bearer " prefix) -
TUF_USERNAME: Your TakeUForward username -
CODOLIO_PROFILE: Your Codolio profile name
π― Conclusion
You now have a fully automated coding stats aggregator that combines:
- β Multi-platform DSA progress (via Codolio + TUF)
- β GitHub activity metrics
- β Auto-updates via GitHub Actions
- β Ready-to-display JSON format
Perfect for portfolios, resumes, or tracking your coding journey!
Found this helpful? Star the repo and share with fellow developers! π
Happy Coding! π
Top comments (0)