user analytics
Languages, streaks, own-commit breakdown, profile views, the SVG card, and the canonical card routes that wrap the same data.
Default language exclusions on /{username}/languages and /{username}/contributions/breakdown are Markdown, JSON, YAML, and XML. /{username}/stats and /{username}/stats/svg default to excluding nothing unless you pass exclude or excluded.
exclude is a comma-separated string. excluded is the older repeatable query (?excluded=HTML&excluded=CSS). If excluded is present it wins.
Own-commit attribution#
With attributed=true (the default), language percentages count only commits the requested user authored. Forks contribute the patches they wrote, not the upstream codebase. Other people’s commits in the user’s repos are ignored. Vendored paths such as node_modules, dist, lockfiles, and minified bundles are skipped.
Walking diffs costs hundreds of GitHub calls and will not finish in one request. Each walk has a wall-clock deadline and caches per repo, keyed by pushed_at. Repos are remeasured only after a new push.
/{username}/languagesand/{username}/statsnever fall back to whole-repo language bytes in attributed mode. A cold cache can return a thin or empty mix./{username}/reposreads the attribution cache. It does not walk diffs./{username}/contributions/breakdownreportscoverage,partial,cache_enabled,status, andmessage. Check those first when the split looks empty.
status on the breakdown is one of complete, deadline, rate_limited, cache_disabled.
Without Redis, nothing accumulates between requests. Set REDIS_URL, or UPSTASH_REDIS_REST_URL plus UPSTASH_REDIS_REST_TOKEN.
Warm the cache:
python scripts/warm_attribution.py tashifkhan
Or hit the breakdown until coverage climbs:
for i in $(seq 6); do
curl -s https://github-stats.tashif.codes/tashifkhan/contributions/breakdown \
| python -c 'import json,sys; d=json.load(sys.stdin); print(d["coverage"], d["status"])'
done
Tuning knobs, all optional: ATTRIBUTION_INLINE_DEADLINE (3.5s inside a normal request), ATTRIBUTION_BREAKDOWN_DEADLINE (8s), ATTRIBUTION_MAX_COMMITS_PER_REPO (200), ATTRIBUTION_MAX_COMMIT_DETAILS (600), ATTRIBUTION_RATE_LIMIT_FLOOR (500 GitHub calls kept in reserve), ATTRIBUTION_CACHE_TTL_SECONDS (7 days).
Canonical summary#
- Method and path.
GET /{username} - Response. Envelope.
data.totalSolvedis total commits.data.totalActiveDaysis days with at least one contribution.
curl -s https://github-stats.tashif.codes/tashifkhan
Canonical profile#
- Method and path.
GET /{username}/profile - Response. Envelope.
datahasdisplayName,username,avatar,country(GitHub location),company,bio,websites, andsocial(github,twitter,linkedin).
Complete statistics#
- Method and path.
GET /{username}/stats - Query.
exclude,excluded,attributed(defaulttrue) - Response. Envelope plus the older flat fields:
topLanguages,totalCommits,longestStreak,currentStreak,profile_visitors,contributions. Canonicaldatamaps commits tototalSolvedand languages totopicAnalysis.
curl -s "https://github-stats.tashif.codes/tashifkhan/stats?exclude=HTML,CSS"
{
"status": "success",
"message": "retrieved",
"topLanguages": [{"name": "Python", "percentage": 45.0}],
"totalCommits": 2068,
"longestStreak": 25,
"currentStreak": 10,
"profile_visitors": 1234,
"contributions": {},
"platform": "github",
"username": "tashifkhan",
"cached": false,
"data": {
"totalSolved": 2068,
"topicAnalysis": [{"topic": "Python", "count": 45}]
}
}
Stats SVG card#
- Method and path.
GET /{username}/stats/svg - Query.
theme(darkdefault, orlight),exclude,excluded,attributed(defaulttrue) - Response.
image/svg+xml, cached 24 hours viaCache-Control. Commits, stars, streaks, language bars.
curl -s "https://github-stats.tashif.codes/tashifkhan/stats/svg?theme=light&exclude=HTML,CSS" -o stats.svg
Contribution heatmap#
- Method and path.
GET /{username}/heatmap - Query.
view(alldefault,last_365, oryear).yearis required whenview=year. Aliases such as365andlast365map tolast_365. Passingyearwithview=allbecomesview=year. - Response. Envelope.
dataincludesdailyContributions, streaks,availableYears, and window fields (view,year,startDate,endDate). Yearly totals always describe full history even when the daily grid is sliced.
Invalid view is 400. view=year without year is 400.
Badges#
- Method and path.
GET /{username}/badges - Response. Envelope. GitHub profile achievements:
count,active,listof{id, name, icon, level}.
Programming languages#
- Method and path.
GET /{username}/languages - Query.
exclude,excluded,attributed(defaulttrue),include_forks(defaulttrue) - Response. JSON array, not the envelope.
curl -s "https://github-stats.tashif.codes/tashifkhan/languages?exclude=HTML,CSS"
[
{"name": "Python", "percentage": 45.0},
{"name": "JavaScript", "percentage": 30.0}
]
Set attributed=false to sum whole-repo language bytes, including other contributors and upstream code in forks.
Contribution history#
- Method and path.
GET /{username}/contributions - Query.
starting_year(optional integer, defaults to account creation year) - Response. Envelope. Canonical heatmap lives in
data. The older payload is merged onto the root:contributionskeyed by year,totalCommits,longestStreak,currentStreak.
curl -s "https://github-stats.tashif.codes/tashifkhan/contributions?starting_year=2022"
Own-commit contribution breakdown#
- Method and path.
GET /{username}/contributions/breakdown - Query.
exclude,excluded,include_forks(defaulttrue) - Response.
ContributionLanguageStats. Per-repo commits, additions, deletions, files, language mix, andcontribution_percentage.methodiscommits,estimated, orcontributor_stats.
{
"username": "tashifkhan",
"languages": [
{"name": "Python", "percentage": 52.4, "lines": 18420, "files": 210}
],
"total_additions": 35150,
"total_deletions": 9820,
"total_commits": 742,
"files_changed": 1904,
"repos_analyzed": 24,
"forks_analyzed": 3,
"coverage": 0.8,
"partial": true,
"status": "deadline",
"message": "",
"cache_enabled": true,
"repositories": []
}
Profile views#
- Method and path.
GET /{username}/profile-views - Query.
increment(defaulttrue),base(optional integer, sets the stored count for migration) - Response.
{ "username", "views", "incremented" }
curl -s "https://github-stats.tashif.codes/tashifkhan/profile-views?increment=false"