A recruiter friend told me she spends 20 minutes per candidate checking their GitHub. She clicks through repos, reads READMEs, counts stars.
I built her a script that does it in 3 seconds. No API key needed.
The Problem
GitHub profiles tell a story — but reading that story manually is slow. You want to know:
- What languages does this person actually use?
- Do they maintain their projects or abandon them?
- Are their repos getting traction (stars, forks)?
- How active have they been recently?
The GitHub REST API gives you all of this — without authentication for public data.
Quick Start: 30-Line Portfolio Analyzer
import requests
from collections import Counter
from datetime import datetime
def analyze_portfolio(username):
repos = requests.get(
f"https://api.github.com/users/{username}/repos",
params={"per_page": 100, "sort": "updated"}
).json()
if isinstance(repos, dict): # Error response
return f"Error: {repos.get('message', 'Unknown')}"
languages = Counter()
total_stars = 0
active_repos = 0
for repo in repos:
if repo["fork"]: # Skip forks
continue
if repo["language"]:
languages[repo["language"]] += 1
total_stars += repo["stargazers_count"]
# Check if updated in last 90 days
updated = datetime.strptime(repo["updated_at"], "%Y-%m-%dT%H:%M:%SZ")
if (datetime.now() - updated).days < 90:
active_repos += 1
original = [r for r in repos if not r["fork"]]
return {
"username": username,
"total_repos": len(original),
"total_stars": total_stars,
"top_languages": dict(languages.most_common(5)),
"active_repos_90d": active_repos,
"most_starred": max(original, key=lambda r: r["stargazers_count"])["name"] if original else None
}
# Example
result = analyze_portfolio("torvalds")
for key, value in result.items():
print(f"{key}: {value}")
Output:
username: torvalds
total_repos: 7
total_stars: 188000+
top_languages: {"C": 3, "None": 2}
active_repos_90d: 2
most_starred: linux
Level 2: Contribution Heatmap via Events API
Want to see when someone codes? The Events API shows recent activity:
def get_activity_pattern(username):
events = requests.get(
f"https://api.github.com/users/{username}/events/public",
params={"per_page": 100}
).json()
hour_counts = Counter()
day_counts = Counter()
event_types = Counter()
for event in events:
dt = datetime.strptime(event["created_at"], "%Y-%m-%dT%H:%M:%SZ")
hour_counts[dt.hour] += 1
day_counts[dt.strftime("%A")] += 1
event_types[event["type"]] += 1
peak_hour = hour_counts.most_common(1)[0] if hour_counts else None
peak_day = day_counts.most_common(1)[0] if day_counts else None
return {
"peak_coding_hour": f"{peak_hour[0]}:00 UTC ({peak_hour[1]} events)" if peak_hour else "No data",
"most_active_day": f"{peak_day[0]} ({peak_day[1]} events)" if peak_day else "No data",
"top_activities": dict(event_types.most_common(3))
}
Level 3: Compare Two Developers
Building a hiring tool? Compare candidates side by side:
def compare_developers(user1, user2):
p1 = analyze_portfolio(user1)
p2 = analyze_portfolio(user2)
print(f"{Metric:<25} {user1:<20} {user2:<20}")
print("-" * 65)
for key in ["total_repos", "total_stars", "active_repos_90d"]:
print(f"{key:<25} {str(p1[key]):<20} {str(p2[key]):<20}")
print(f"\n{user1} top langs: {p1['top_languages']}")
print(f"{user2} top langs: {p2['top_languages']}")
compare_developers("torvalds", "gvanrossum")
Rate Limits (Important!)
- Without auth: 60 requests/hour per IP
- With token: 5,000 requests/hour
- Tip: For bulk analysis, add a token via headers:
headers = {"Authorization": "token ghp_your_token_here"}
requests.get(url, headers=headers)
Real-World Use Cases
- Recruiters: Screen candidates before interviews
- Open source maintainers: Find active contributors to invite
- Developers: Audit your own profile before job hunting
- Teams: Track team activity across repos
Full Code on GitHub
I packaged this into a complete CLI tool with pretty output: github-portfolio-analyzer
I build tools that turn public APIs into useful products. Currently exploring every free API I can find. If you are building something similar or need a technical writer for your developer blog, reach out: Spinov001@gmail.com
Top comments (0)