Skip to content

How to get GitHub repository stats as JSON

Last updated

GitHub’s API gives you a repository’s star count and its commit list, and leaves the arithmetic to you. gitdebt’s JSON API gives you finished health figures for any public repository: recent commit volume, bus factor, contributor count, the most-changed file and TODO movement. You need a terminal or a script. No account or API key is involved.

1. Pick the endpoint

All endpoints sit under https://api.gitdebt.com/api/repos/OWNER/REPO/ and answer GET:

Endpoint What it returns Size
health.json A fixed summary of the repository’s health Small, the same for any repository
stats.json Every row behind the site’s health charts: commit days, authors, files, languages, TODO days Large for an old repository
earned-badges.json The maintained, community and momentum signals with their verdicts Small
progress.json Whether the star history and the code analysis are done Small
stars.json, stars.csv Daily star history. See How to export GitHub star history to CSV or JSON One row per day with stars
report.md All of the above as one Markdown document, for people and coding agents Medium

Start with health.json. Use stats.json only when you draw your own charts.

2. Read health.json

curl

curl -s https://api.gitdebt.com/api/repos/OWNER/REPO/health.json \
  | jq '{last_commit_day, commits_window, commits_previous_window, bus_factor, contributors}'

JavaScript

const response = await fetch(
  "https://api.gitdebt.com/api/repos/OWNER/REPO/health.json",
);
if (response.status === 202) throw new Error("Not analyzed yet");
const health = await response.json();
console.log(health.last_commit_day, health.bus_factor);

Python

import requests

response = requests.get(
    "https://api.gitdebt.com/api/repos/OWNER/REPO/health.json", timeout=30
)
if response.status_code == 202:
    raise SystemExit("Not analyzed yet")
health = response.json()
print(health["last_commit_day"], health["bus_factor"])

Use requests, curl or fetch. The API’s edge refuses Python’s default urllib user agent with HTTP 403, so set a User-Agent header if you use urllib directly.

3. Know what each field means

These fields were present for facebook/react on 30 October 2026:

Field Meaning
ready true when a finished analysis backs the figures
analyzed_at When gitdebt last read the git history
archived Whether the repository is archived on GitHub
stars The current star count
window_days The length of the recent window, 90 days
commits_window Commits in the last 90 days
commits_previous_window Commits in the 90 days before that
last_commit_day The day of the most recent commit
commit_months Commits per month for the last 24 months, with empty months set to 0
total_commits All commits on the default branch, merge commits included
contributors People with commits, bots left out
bus_factor The fewest people whose commits add up to more than half of all commits
top_author_commits Commits by the person with the most
tracked_files Files in the history, dependency manifests and lock files left out
fix_changes File changes made by commits whose message reads like a fix
fresh_files Files changed in the last year
hotspot The file most commits touched, with its commit and fix counts
todo_delta_window TODO and FIXME markers added minus removed in the last 90 days
todo_outstanding TODO and FIXME markers added minus removed over the whole history
analysis_truncated Always false today, because gitdebt reads the whole history

Apart from total_commits, commit figures count non-merge commits on the default branch.

A falling commits_window against commits_previous_window and an old last_commit_day point to a slowdown. A bus_factor of 1 means one person wrote more than half of the commits. Bus factor: how to measure it from git history and its limits explains how far to trust that number.

4. Start the analysis for a new repository

health.json and stats.json read gitdebt’s database and never start work. For a repository nobody has analyzed yet, they answer:

HTTP/2 202
{"ready":false,"repo":"owner/repo"}

To queue the analysis, request the Markdown report once. It answers 202 with a Retry-After header while the work runs:

curl -s -o /dev/null -w '%{http_code}\n' https://api.gitdebt.com/api/repos/OWNER/REPO/report.md

Then poll the progress until the code analysis is done:

curl -s https://api.gitdebt.com/api/repos/OWNER/REPO/progress.json | jq '.analysis'
{"phase":"complete","complete":true,"processed_units":2,"total_units":2,"percent":100}

The analysis clones the repository, so a large repository takes longer than a small one. Add ?enqueue=0 to report.md to read without queueing anything.

5. Check many repositories

A script that checks your dependencies can loop over slugs. Stay under the rate limits per IP address: health.json and stats.json allow about 160 requests per 10 seconds, and report.md, stars.json and earned-badges.json about 40.

for slug in vitejs/vite evanw/esbuild facebook/react; do
  curl -s "https://api.gitdebt.com/api/repos/$slug/health.json" \
    | jq -r '[.repo, .last_commit_day, .commits_window, .bus_factor] | @tsv'
done

Each line prints the slug, the last commit day, the commits in 90 days and the bus factor.

Common errors

Status Body Cause
202 {"ready":false,...} No finished analysis yet. Do step 4
400 {"error":"invalid owner/repo"} The slug has characters GitHub does not allow
429 Too Many Requests! Wait for 5s Too many requests from one IP. Wait for the seconds in Retry-After
403 error code: 1010 The edge refused the client’s user agent. Send a User-Agent header

gitdebt reads public repositories only and cannot report on a private one. It also does not report issues, pull requests or releases. For those, use GitHub’s REST API with your own token.

To see the same figures drawn as charts, open the repository on gitdebt.