
Github Trending
- 3.1k installs
- 262 repo stars
- Updated July 11, 2026
- hoodini/ai-agents-skills
github-trending is a skill that fetches GitHub trending repositories via Cheerio scraping or Search API fallback for dashboards and discovery features.
About
github-trending fetches GitHub trending repositories and developer discovery data for dashboards and popular project tracking. GitHub provides no official trending API, so the recommended approach scrapes github.com/trending with Cheerio parsing article.Box-row elements for owner, name, description, language, stars, forks, and starsToday. URL patterns support optional language path segments and since=daily weekly or monthly query parameters. A Next.js API route example caches server-side fetches with one-hour revalidation and a React useTrending hook consumes the local endpoint. Alternative Approach 2 uses the official GitHub Search API with created date, minimum stars, and language filters at ten requests per minute unauthenticated or thirty with a token. parseNumber handles k suffix star counts. Important constraints: no official API, respect rate limits with aggressive caching, monitor HTML structure changes, always send User-Agent headers, and scrape server-side only to avoid CORS. TypeScript interfaces document TrendingRepo and GitHubRepo shapes. Triggers include GitHub trending, trending repos, popular repositories, and GitHub discover requests.
- No official GitHub trending API; Cheerio scrape of article.Box-row is the recommended path.
- Supports language filters and since=daily, weekly, or monthly trending windows.
- Next.js API route with one-hour revalidate cache and React useTrending hook example.
- GitHub Search API fallback with created date and stars filters and token rate limits.
- Server-side only scraping with User-Agent required; monitor HTML structure breakages.
Github Trending by the numbers
- 3,140 all-time installs (skills.sh)
- +17 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #182 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
github-trending capabilities & compatibility
- Capabilities
- cheerio scrape of github.com/trending · language and since period url building · next.js cached api route pattern · github search api fallback queries · react usetrending hook consumption
- Works with
- github
- Use cases
- api development · web scraping · research
- Runs
- Local or remote
What github-trending says it does
GitHub does NOT provide an official trending API.
Each trending repo is in an article.Box-row element
Do scraping server-side to avoid CORS issues
npx skills add https://github.com/hoodini/ai-agents-skills --skill github-trendingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3.1k |
|---|---|
| repo stars | ★ 262 |
| Security audit | 2 / 3 scanners passed |
| Last updated | July 11, 2026 |
| Repository | hoodini/ai-agents-skills ↗ |
How do I build a trending repositories dashboard when GitHub has no official trending API?
Scrape or search GitHub trending repositories for dashboards with language and daily weekly monthly filters.
Who is it for?
Developers building trending repo rails or discovery dashboards who can run server-side scraping with Cheerio and caching.
Skip if: Skip for client-only browser scraping without a backend or when official GitHub rate limits cannot be managed.
When should I use this skill?
User asks for GitHub trending repos, popular repositories dashboard, trending developers, or github.com/trending data.
What you get
Structured TrendingRepo objects with owner, stars, forks, language, and starsToday from a cached server-side scrape or search endpoint.
- trending repository lists
- trending developer rankings
By the numbers
- Covers 2 data types: trending repositories and trending developers
- Documents 2 approaches: direct scraping and GitHub Search API
Files
GitHub Trending Data
Access GitHub trending repositories and developers data.
Important Note
GitHub does NOT provide an official trending API. The trending page at github.com/trending must be scraped directly or use the GitHub Search API as an alternative.
Approach 1: Direct Web Scraping (Recommended)
Scrape github.com/trending directly using Cheerio:
import * as cheerio from 'cheerio';
interface TrendingRepo {
owner: string;
name: string;
fullName: string;
url: string;
description: string;
language: string;
languageColor: string;
stars: number;
forks: number;
starsToday: number;
}
async function scrapeTrending(options: {
language?: string;
since?: 'daily' | 'weekly' | 'monthly';
} = {}): Promise<TrendingRepo[]> {
// Build URL: github.com/trending or github.com/trending/typescript?since=weekly
let url = 'https://github.com/trending';
if (options.language) {
url += `/${encodeURIComponent(options.language)}`;
}
if (options.since) {
url += `?since=${options.since}`;
}
const response = await fetch(url, {
headers: {
'User-Agent': 'Mozilla/5.0 (compatible; TrendingBot/1.0)',
},
});
if (!response.ok) {
throw new Error(`Failed to fetch trending: ${response.status}`);
}
const html = await response.text();
const $ = cheerio.load(html);
const repos: TrendingRepo[] = [];
// Each trending repo is in an article.Box-row element
$('article.Box-row').each((_, element) => {
const $el = $(element);
// Get repo link (e.g., /owner/repo)
const repoLink = $el.find('h2 a').attr('href')?.trim() || '';
const [, owner, name] = repoLink.split('/');
// Get description
const description = $el.find('p.col-9').text().trim();
// Get language
const language = $el.find('[itemprop="programmingLanguage"]').text().trim();
// Get language color from the colored dot
const langColorStyle = $el.find('.repo-language-color').attr('style') || '';
const langColorMatch = langColorStyle.match(/background-color:\s*([^;]+)/);
const languageColor = langColorMatch ? langColorMatch[1].trim() : '';
// Get stars (total)
const starsText = $el.find('a[href$="/stargazers"]').text().trim();
const stars = parseNumber(starsText);
// Get forks
const forksText = $el.find('a[href$="/forks"]').text().trim();
const forks = parseNumber(forksText);
// Get stars today/this week/this month
const starsTodayText = $el.find('.float-sm-right, .d-inline-block.float-sm-right').text().trim();
const starsToday = parseNumber(starsTodayText);
if (owner && name) {
repos.push({
owner,
name,
fullName: `${owner}/${name}`,
url: `https://github.com${repoLink}`,
description,
language,
languageColor,
stars,
forks,
starsToday,
});
}
});
return repos;
}
function parseNumber(text: string): number {
const clean = text.replace(/,/g, '').trim();
if (clean.includes('k')) {
return Math.round(parseFloat(clean) * 1000);
}
return parseInt(clean) || 0;
}Approach 2: GitHub Search API (Official Alternative)
Use GitHub's Search API to find recently created repos with high stars:
interface GitHubSearchResult {
total_count: number;
items: GitHubRepo[];
}
interface GitHubRepo {
full_name: string;
html_url: string;
description: string;
language: string;
stargazers_count: number;
forks_count: number;
created_at: string;
}
async function getTrendingViaSearch(options: {
language?: string;
days?: number;
minStars?: number;
} = {}): Promise<GitHubRepo[]> {
const days = options.days || 7;
const minStars = options.minStars || 100;
// Calculate date N days ago
const date = new Date();
date.setDate(date.getDate() - days);
const since = date.toISOString().split('T')[0];
// Build search query
const queryParts = [
`created:>${since}`,
`stars:>=${minStars}`,
];
if (options.language) {
queryParts.push(`language:${options.language}`);
}
const query = queryParts.join(' ');
const response = await fetch(
`https://api.github.com/search/repositories?q=${encodeURIComponent(query)}&sort=stars&order=desc&per_page=25`,
{
headers: {
'Accept': 'application/vnd.github.v3+json',
'Authorization': `Bearer ${process.env.GITHUB_TOKEN}`, // Optional but recommended
'User-Agent': 'TrendingApp/1.0',
},
}
);
if (!response.ok) {
throw new Error(`GitHub API error: ${response.status}`);
}
const data: GitHubSearchResult = await response.json();
return data.items;
}Note: The Search API has rate limits (10 requests/minute unauthenticated, 30/minute with token).
Next.js API Route (Server-Side Scraping)
// app/api/trending/route.ts
import { NextRequest } from 'next/server';
import * as cheerio from 'cheerio';
export async function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams;
const language = searchParams.get('language') || '';
const since = searchParams.get('since') || 'daily';
try {
let url = 'https://github.com/trending';
if (language) url += `/${encodeURIComponent(language)}`;
url += `?since=${since}`;
const response = await fetch(url, {
headers: { 'User-Agent': 'Mozilla/5.0 (compatible)' },
next: { revalidate: 3600 }, // Cache for 1 hour
});
const html = await response.text();
const repos = parseGitHubTrending(html);
return Response.json(repos);
} catch (error) {
console.error('Trending scrape failed:', error);
return Response.json(
{ error: 'Failed to fetch trending repos' },
{ status: 500 }
);
}
}
function parseGitHubTrending(html: string) {
const $ = cheerio.load(html);
const repos: any[] = [];
$('article.Box-row').each((_, el) => {
const $el = $(el);
const repoLink = $el.find('h2 a').attr('href') || '';
const [, owner, name] = repoLink.split('/');
repos.push({
owner,
name,
fullName: `${owner}/${name}`,
url: `https://github.com${repoLink}`,
description: $el.find('p.col-9').text().trim(),
language: $el.find('[itemprop="programmingLanguage"]').text().trim(),
stars: parseNumber($el.find('a[href$="/stargazers"]').text()),
forks: parseNumber($el.find('a[href$="/forks"]').text()),
starsToday: parseNumber($el.find('.float-sm-right').text()),
});
});
return repos;
}
function parseNumber(text: string): number {
const clean = text.replace(/,/g, '').trim();
if (clean.includes('k')) return Math.round(parseFloat(clean) * 1000);
return parseInt(clean) || 0;
}React Hook
import { useState, useEffect } from 'react';
function useTrending(options: { language?: string; since?: string } = {}) {
const [repos, setRepos] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
async function fetchTrending() {
setIsLoading(true);
try {
const params = new URLSearchParams();
if (options.language) params.set('language', options.language);
if (options.since) params.set('since', options.since);
const response = await fetch(`/api/trending?${params}`);
if (!response.ok) throw new Error('Failed to fetch');
setRepos(await response.json());
} catch (err) {
setError(err instanceof Error ? err.message : 'Unknown error');
} finally {
setIsLoading(false);
}
}
fetchTrending();
}, [options.language, options.since]);
return { repos, isLoading, error };
}Important Considerations
1. No Official API: GitHub's trending page has no official API - scraping is the only option 2. Rate Limiting: Respect GitHub's servers - cache aggressively 3. HTML Structure Changes: GitHub may change their HTML - monitor for breakages 4. User-Agent: Always include a User-Agent header 5. Server-Side Only: Do scraping server-side to avoid CORS issues
Resources
- GitHub Trending Page: https://github.com/trending
- GitHub Search API: https://docs.github.com/en/rest/search
Related skills
How it compares
Use github-trending when you need the same data shown on GitHub's trending page rather than generic repository search results.
FAQ
Does GitHub provide an official trending API?
No. The trending page at github.com/trending must be scraped or approximated via the Search API.
What rate limits apply to the Search API fallback?
Ten requests per minute unauthenticated and thirty per minute with a GITHUB_TOKEN bearer token.
Should trending scraping run in the browser?
No. Scrape server-side to avoid CORS and include a User-Agent header on all requests.
Is Github Trending safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.