GitHub's REST and GraphQL APIs know everything about a repository except whether it is trending; that list only exists as a web page. This repository is a compact, tested Python client for the GitHub Trending Scraper on Apify, which turns that page into rows you can analyse. Choose a period (today, this week or this month), optionally a language, and you receive each listed project with its rank, the stars it collected during that period, its lifetime stars, forks and primary language. The Actor runs in Apify's cloud, so the script on your side is a few dozen lines and needs no GitHub credentials. Output lands as results.json and results.csv, shaped for a DataFrame, a notebook cell or a nightly cron job.
Actor: GitHub Trending Scraper Β· Publisher: Devil Scrapes Β· Also in JavaScript: github-trending-scraper-javascript
- One row for every repository on the list, with its position, the
owner/namepair split into separate columns, the link, the tagline, the primary language, star and fork counts and the contributor avatars GitHub shows on the card. - Star velocity as its own number:
stars_in_windowcounts only the stars earned during the chosen period, kept apart from the lifetimestars_total, so you never diff two snapshots to estimate momentum. - Three periods, two filters: switch
sincebetweendaily,weeklyandmonthly, and narrow by programming language, spoken language or both, all producing the same row shape. - GitHub's ordering survives export: the
rankcolumn keeps position 1 at position 1 after the rows pass through CSV, a spreadsheet or a database sort. - No GitHub token or rate budget of your own: requests go out from the Apify run, and throttled or failed page loads are retried with backoff before anything is written.
- Every row is stamped with the window it came from and a UTC collection time, which makes stacking scheduled snapshots into a history table straightforward.
Run one job per language you care about, concatenate the CSVs and sum stars_in_window by language. A weekly cron that appends to a Parquet file gives you a time series of developer attention per ecosystem after a couple of months, without hand-copying anything from the browser.
Divide the stars gained in the period by the lifetime total and sort descending. Young repositories with a high ratio are the ones growing fastest relative to their size, a list analysts and investors usually assemble manually from several tabs.
Pull the weekly window for Python or Rust on Friday morning, filter out repositories you have already featured, and export the remainder to Markdown or HTML for a newsletter. The rank, description and html_url columns cover most of what a digest entry needs.
GitHub only shows the current state of the page. Saving each scheduled run with its scraped_at timestamp builds a record you can query later, for example to find every day a given repository appeared and how high it ranked.
You need an Apify account and an API token from Console β Settings β Integrations. Apify's free plan includes monthly usage credit; this Actor's event prices are listed under Pricing below.
git clone https://github.com/devilscrapes/github-trending-scraper-python.git
cd github-trending-scraper-python
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
export APIFY_TOKEN=your_token_here
python main.py # uses input.json
python main.py my-input.json --out data --max-charge 2The script starts the GitHub Trending Scraper, waits for it to finish, prints a link to the run in Apify Console and saves every result to results.json and results.csv. It exits with code 1 and the run's status message if the run fails.
The minimal integration is shown below. apify-client starts the Actor, blocks until the run completes and then iterates over the dataset, so a single loop gets you every trending row.
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("DevilScrapes/github-trending-scraper").call(run_input={'since': 'weekly', 'language': 'rust', 'maxResults': 10, 'proxyConfiguration': {'useApifyProxy': True}})
for item in client.dataset(run.default_dataset_id).iterate_items():
print(item)main.py forwards input.json to the Actor without changes. The bundled file asks for the weekly Rust list and caps it at 10 repositories, a quick and inexpensive way to see real rows. Edit since or language, or clear language to get the cross-language list.
{
"since": "weekly",
"language": "rust",
"maxResults": 10,
"proxyConfiguration": {
"useApifyProxy": true
}
}| Field | Type | Required | Default | Allowed values |
|---|---|---|---|---|
since |
string | no | "daily" |
daily, weekly, monthly |
language |
string | no | "" |
β |
spokenLanguage |
string | no | "" |
β |
maxResults |
integer | no | 25 |
β |
proxyConfiguration |
object | no | {"useApifyProxy": true} |
β |
Each dataset row represents a single repository as it appeared on the page at collection time. Counts are integers, the language and tagline can be null when GitHub omits them, and built_by is a list of avatar URLs that may be empty.
| Field | Type | Always present |
|---|---|---|
rank |
integer | yes |
full_name |
string | yes |
owner |
string | no |
name |
string | no |
html_url |
string | yes |
description |
string or null | no |
language |
string or null | no |
stars_total |
integer | no |
stars_in_window |
integer | no |
forks |
integer | no |
built_by |
array | no |
scraped_at |
string | no |
window |
string | no |
| Event | Price (USD) |
|---|---|
| Actor start | $0.2 |
| Result emitted | $0.002 |
Prices as configured on 2026-08-20. The Actor page always shows the current price. Runs are billed to the Apify account that owns the token. Use --max-charge to cap what a single run can cost.
This pandas example (pip install pandas) computes a momentum ratio, ranks languages by stars earned in the window and writes the ten fastest-growing repositories to a CSV.
import json
import pandas as pd
rows = pd.DataFrame(json.load(open("results.json", encoding="utf-8")))
rows["language"] = rows["language"].fillna("unknown")
rows["momentum"] = rows["stars_in_window"] / rows["stars_total"].clip(lower=1)
by_language = (
rows.groupby("language")["stars_in_window"]
.agg(["count", "sum"])
.sort_values("sum", ascending=False)
)
print(by_language.to_string())
breakouts = rows.sort_values("momentum", ascending=False).head(10)
breakouts[["rank", "full_name", "stars_in_window", "stars_total", "momentum", "html_url"]].to_csv(
"breakouts.csv", index=False
)
print(breakouts[["full_name", "stars_in_window", "momentum"]].to_string(index=False))Neither the REST nor the GraphQL API exposes the Trending list. You can search repositories by star count or creation date, but that is a different ranking from the one GitHub publishes on the page. This Actor reads the page itself, so your numbers match what visitors see.
No. The only credential is your Apify API token. The run does not touch your GitHub account or consume its API rate limit.
GitHub usually lists around 25 projects per period and language combination, and maxResults can trim that further. For a broad survey, run the script once per language and combine the CSVs in pandas.
Yes. Call main.main(["input.json", "--out", "snapshots/2026-10-18"]) from a notebook, or put python main.py in a crontab. A nonzero exit code signals a failed run, so a scheduler can alert on it.
No. Only the repositories list is collected. Topic filters are not offered either, because the Trending page itself has none.
Set APIFY_TOKEN first: export the token in the same shell, or put it in a local.envfile your shell loads. Never commit it.- Run finished with
FAILEDorABORTED: open the printed Console link; the run log says why. Input validation errors name the field. - Fewer rows than expected: a
--max-chargecap also limits how many results can be charged. Raise the cap or lower the limits in your input. - Something looks wrong in the data: open an issue on the Actor page so the maintainers see it.
- GitHub Trending Scraper on Apify Store
- JavaScript version of this example
- All Devil Scrapes Actors
- Apify web scraping cookbook
Related Actors:
- GitHub Repo Scraper β fuller metadata for any repository that catches your eye on Trending.
- GitHub Organization Scraper β profile data for the organizations behind the projects that keep climbing.
- Hacker News Scraper β see whether a climbing repository is also being discussed on Hacker News.
MIT licensed example code. The Actor itself runs on Apify and is maintained by Devil Scrapes. Not affiliated with GitHub, Inc..