GitHub Repos, Trending & Releases API — No Token Needed avatar

GitHub Repos, Trending & Releases API — No Token Needed

Pricing

from $0.60 / 1,000 repositories

Go to Apify Store
GitHub Repos, Trending & Releases API — No Token Needed

GitHub Repos, Trending & Releases API — No Token Needed

GitHub repository facts — stars, forks, watchers, issues, language, licence, topics, README — plus trending repos by language, search in GitHub's syntax, releases with download counts and organisation repos. No token needed. No user or profile scraping. $1 per 1,000 repositories.

Pricing

from $0.60 / 1,000 repositories

Rating

0.0

(0)

Developer

Insight Solutions

Insight Solutions

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

9 days ago

Last modified

Share

Repository facts — stars, forks, watchers, open issues, language, licence, topics, dates, and the README on request — plus GitHub trending for any language and period, repository search in GitHub's own query syntax, releases with assets and download counts, and an organisation's repositories. All as rows in one schema, and no token needed for small runs.

Read from GitHub's REST API (api.github.com) and, where GitHub only publishes HTML, from github.com — the trending page, and two fallbacks for when the API's anonymous limit is reached.

The honest part first. Without a token, GitHub allows 60 requests an hour per IP address to its API, and 10 searches a minute. That is what GitHub's own /rate_limit endpoint reported for this Actor's capture, through the proxy and without it. It is plenty for the default run (2 of the 60) and for a few dozen repositories; for hundreds, add your own free token and the limit becomes 5,000 an hour. When the limit is reached anyway, the Actor does not just stop — see When GitHub says "rate limit exceeded".

At a glance

Input — this is the Store prefill; paste it and run:

{ "repos": ["apify/crawlee", "https://github.com/microsoft/playwright"], "trending": ["all"], "trendingSince": "daily" }

Two repositories and today's trending list: 2 API requests and 1 page, a few seconds, about a cent.

Output — one row per repository, search hit, trending repository or release, with the same columns on every row. The ones you will use most are fullName, stars, forks, language, license, topics, pushedAt and url; trending rows add starsToday, release rows add tag, publishedAt and assets. Anything that could not be read comes back as a free diagnostic row (rowType: "diagnostic", errorType, error) instead of a charge.

Price — $1 per 1,000 repositories on the FREE tier, $0.30 per 1,000 search results, $0.50 per 1,000 trending repositories, $0.30 per 1,000 releases, plus $0.001 per run charged only once a run has returned a row. Diagnostic rows, rate-limited requests, repositories that do not exist, duplicates and empty searches are free, and a run that returns nothing bills nothing. Pay-per-event, no browser, limited permissions — works over the Apify MCP server (mcp.apify.com) and with agentic (x402) payments.

From code — client.actor("insight.solutions/github-repos-api").call(run_input={…}) with apify-client, or

POST https://api.apify.com/v2/acts/insight.solutions~github-repos-api/run-sync-get-dataset-items
.


What you get

A repository (repos and orgs):

{
"rowType": "repo",
"source": "api.github.com",
"fullName": "apify/crawlee",
"owner": "apify",
"ownerType": "Organization",
"repoId": 66670819,
"url": "https://github.com/apify/crawlee",
"homepage": "https://crawlee.dev",
"description": "Crawlee—A web scraping and browser automation library for Node.js to build reliable crawle…",
"language": "TypeScript",
"topics": ["apify", "automation", "crawler", "crawling", "headless"],
"license": "Apache License 2.0",
"licenseSpdx": "Apache-2.0",
"stars": 25991,
"forks": 1688,
"watchers": 136,
"openIssues": 136,
"size": 175831,
"defaultBranch": "master",
"archived": false,
"isFork": false,
"createdAt": "2016-08-26T18:35:03.000Z",
"pushedAt": "2026-10-05T18:33:18.000Z",
"hasDiscussions": true,
"viaHtmlFallback": false
}

A trending repository (trending):

{
"rowType": "trending-repo",
"source": "github.com",
"fullName": "tester-army/e2e",
"description": "Next generation e2e testing framework for web and mobile apps.",
"language": "TypeScript",
"stars": 4644,
"forks": 193,
"starsToday": 1430,
"trendingPeriod": "daily",
"trendingLanguage": "all",
"rank": 1
}

A search result (searchQueries):

{
"rowType": "search-result",
"query": "topic:web-scraping",
"rank": 1,
"totalCount": 21549,
"fullName": "firecrawl/firecrawl",
"stars": 188896,
"forks": 10029,
"language": "TypeScript",
"license": "GNU Affero General Public License v3.0",
"pushedAt": "2026-10-05T22:40:01.000Z",
"incompleteResults": false
}

A release (includeReleases):

{
"rowType": "release",
"fullName": "apify/crawlee",
"releaseId": 399016570,
"tag": "v3.18.2",
"releaseName": "v3.18.2",
"isPrerelease": false,
"publishedAt": "2026-09-29T09:58:35.000Z",
"url": "https://github.com/apify/crawlee/releases/tag/v3.18.2",
"notes": "## [3.18.2](https://github.com/apify/crawlee/compare/v3.18.1...v3.18.2) (2026-09-29)\n\n### …",
"notesFormat": "markdown",
"assets": [],
"assetCount": 0,
"totalDownloads": 0,
"tarballUrl": "https://api.github.com/repos/apify/crawlee/tarball/v3.18.2",
"viaAtomFallback": false
}

Assets carry { name, size, downloads, url, contentType } each, and totalDownloads sums them. (Crawlee publishes to npm, so its releases have none.)


Quick start

You wantInput
Stars, forks and licence for a list of repositories{ "repos": ["apify/crawlee", "vercel/next.js", "https://github.com/microsoft/playwright"] }
Today's trending repositories, all languages{ "trending": ["all"] }
This week's trending Python and Rust{ "trending": ["python", "rust"], "trendingSince": "weekly" }
The most-starred web-scraping repositories{ "searchQueries": ["topic:web-scraping"], "searchSort": "stars", "maxResults": 100 }
Rust projects pushed this month with 500+ stars{ "searchQueries": ["language:rust stars:>500 pushed:>2026-09-01"] }
Everything an organisation publishes{ "orgs": ["apify"], "maxResults": 200 }
Releases and download counts for your dependencies{ "repos": ["cli/cli", "nodejs/node"], "includeReleases": true, "maxReleasesPerRepo": 20 }
README text for an LLM pipeline{ "repos": ["apify/crawlee"], "includeReadme": true, "maxTextChars": 50000 }
A big runadd "githubToken": "<your token>" to any of the above

Use cases

  • Track open-source projects — stars, forks, open issues and last push for the repositories you depend on or compete with, on a schedule.
  • Spot what is rising — the trending lists give the stars gained today, this week or this month, per language, ranked as GitHub ranks them.
  • Build a dataset — any GitHub search (topic:, language:, stars:, pushed:, org:, in:description) as rows, with the rank and the total match count.
  • Watch releases — new versions with their notes, prerelease flag and, where a project ships binaries, per-asset download counts.
  • Feed an LLM or an agent — repository facts plus the README text, one flat JSON array, no browser.

When GitHub says "rate limit exceeded"

Every API response tells the caller how much of its quota is left. When it runs out, GitHub answers 403 with x-ratelimit-remaining: 0 and the time it resets. This Actor reads that before doing anything else, and then:

  1. Rotates the proxy session once. Without a token GitHub counts per IP, and a fresh proxy session is a different exit IP with its own allowance. An exit that has already said "0 left" is rotated away from before the next request, so no request is wasted on a refusal it could predict.
  2. Falls back, where GitHub publishes the same facts unmetered:
    • a repository is read from its github.com page — stars, forks, watchers, open issues, licence, topics, homepage, default branch and creation date, exact (the page carries stargazerCount: 25993 even where it displays "26k"). Such a row has viaHtmlFallback: true and no language, size, pushedAt or has* columns, because the page does not carry them;
    • releases are read from the repository's releases.atom feed. Such a row has viaAtomFallback: true; the feed holds only the newest ten releases, carries no assets and no download counts, and dates each release by its last update, so publishedAt is null and the date is in updatedAt.
  3. Otherwise — a search, an organisation listing, a README, a language breakdown — returns a free rate-limited row with resetAt, the time GitHub said the quota comes back, and the rest of the run carries on. Rows already returned are kept.

After two refusals in a row from fresh exits, the Actor stops asking the API until the reset, because every exit it can reach is then dry. A search limit (10 a minute) that resets within a minute is waited out when the run has the time.

With a token the quota belongs to the token, not the IP, so rotating would buy nothing and is skipped; the fallbacks still apply.

How much fits in one run without a token

Each repository is one API request, plus one for includeReadme, one for includeLanguages and one per 100 releases. An organisation or a search is one request per 100 results. Trending lists, repository pages and release feeds are not counted at all. So: two repositories and trending — 2 of 60. Fifty repositories with README and releases — about 150 requests, which the Actor spreads over three proxy sessions and rotates past. Several hundred repositories needs a token, or most rows will come from the page fallback.

The token

Optional. Create a fine-grained personal access token with read-only access to public repositories and no other permissions, and paste it into githubToken. It raises the limit to 5,000 an hour and search to 30 a minute. It is stored by Apify as a secret input, sent only to api.github.com in the Authorization header, never logged, and never put on a row. If GitHub refuses it (401), the run carries on without it and says so in one free row.


Input

FieldTypeDefaultWhat it does
reposstring[][] (prefill: two)owner/repo or any github.com link to it → repo rows. Deduplicated case-insensitively
orgsstring[][]Organisation logins → their public repositories, most recently updated first, as repo rows, up to maxResults each
searchQueriesstring[][]GitHub search syntax → search-result rows
searchSortenumstarsstars, forks, updated, or best-match (GitHub's relevance)
trendingstring[][] (prefill: all)all or language slugs (python, typescript, rust) → trending-repo rows
trendingSinceenumdailydaily, weekly, monthly
includeReleasesboolfalserelease rows for every repos / orgs repository
maxReleasesPerRepoint10Newest first
includeReadmeboolfalseREADME text on repo rows — one extra request each
includeLanguagesboolfalseBytes per language on repo rows — one extra request each
maxTextCharsint20000README and release notes are cut here, with "…"
maxResultsint100Per search query, per organisation, per trending list. Max 1,000
githubTokenstring (secret)—Your own token: 5,000 requests an hour instead of 60
maxConcurrencyint3Requests in flight, at most 3, 250 ms apart
maxRunSecsint240Time budget, max 3600
proxyConfigurationobject{ "useApifyProxy": true }Datacenter

At least one of repos, orgs, searchQueries or trending is needed; a run with none of them stops before sending a request.


Output reference

rowType is one of five. Four are charged, one is free.

rowTypeChargedWhat it is
repoyesOne repository from repos or from an organisation's listing
search-resultyesOne repository a search returned, with query, rank and totalCount
trending-repoyesOne repository on a trending list, with starsToday, trendingPeriod, trendingLanguage and rank
releaseyesOne release, with tag, publishedAt, notes and assets
diagnosticnoAnything that could not be read

Every row carries ok, rowType, input, error, errorType, scrapedAt, source, sourceUrl, and null in every column that does not apply — so a CSV export is one rectangular table however the run was configured.

Three GitHub quirks, handled

  • watchers is the number of people watching. GitHub's API also has a watchers_count, which is a legacy alias of the star count (25,991 and 25,991 on Crawlee). This Actor never uses it: watchers is subscribers_count (136 on Crawlee), which only the single-repository endpoint returns — so it is null on search and organisation rows rather than wrong.
  • openIssues includes open pull requests, because that is how GitHub counts open_issues_count. On Crawlee: 96 issues + 40 pull requests = 136.
  • size is kilobytes of the git repository, as GitHub reports it.

starsToday is named for the default daily list; on a weekly or monthly list it is that period's gain, and trendingPeriod says which.

Diagnostic rows

errorType is one of:

errorTypeMeans
invalid-inputAn entry that is not a repository, organisation or trending list; a search query GitHub rejected (422); a token GitHub refused
not-foundGitHub answered 404 — the repository, organisation or trending language does not exist publicly
rate-limitedGitHub's quota was used up and there was no fallback; resetAt says when it comes back
blockedAn exit IP was refused even after one rotation
httpGitHub answered with an error (5xx after a retry, or a page that did not parse)
timeoutA request took longer than 30 seconds
deadlineThe run's maxRunSecs ran out before this entry was read
empty-searchA search with no matches, or a trending list with nothing on it

None of them is ever charged for. A run whose entries were all usable but produced only these finishes SUCCEEDED with zero results, a status message that says so, and a free diagnostic row per entry; nothing is charged, start fee included. A run finishes FAILED only when there was nothing usable to attempt, or the Actor itself hit an error.


No people, by design

This Actor reads repositories, never people. A repository's owner is part of its public name — sindresorhus/awesome cannot be named without sindresorhus — so owner (the login) and ownerType are on every repository row, and nothing else about any account is: no display name, email, bio, avatar, location or follower count. There is no user or profile scraping, /users/ is never called, an organisation input that turns out to be a personal account is refused, and the authors of releases, commits and issues are never read. If you are looking for a tool that collects developers' emails, this is deliberately not it.


What you are never charged for

  • Every diagnostic row.
  • Repositories, organisations and trending languages that do not exist.
  • Requests GitHub rate-limited or refused.
  • A repository that appears twice — in repos and in its organisation's listing, or under two spellings — is returned and charged once.
  • A README or a language breakdown: they ride on the repository row.
  • An empty search, and anything past GitHub's 1,000-result search ceiling.
  • A run that returns nothing at all: it finishes SUCCEEDED with zero results and a "0 results" status message, and bills nothing, start fee included.

Pricing

EventWhat it isFREEBRONZESILVERGOLD
actor-startOnce per run, only after the run has returned a row$0.001$0.001$0.001$0.001
repoOne repository, README and languages included$0.001$0.001$0.0008$0.0006
search-resultOne search hit$0.0003$0.0003$0.00024$0.00018
trending-repoOne trending repository$0.0005$0.0005$0.0004$0.0003
releaseOne release, assets included$0.0003$0.0003$0.00024$0.00018

$1 per 1,000 repositories.

RunCost (FREE)
The default input — 2 repositories + 14 trending (as in the test capture)$0.010
The default input on a day with the usual 25 trending$0.0155
Trending (25) + 100 search results + 10 repositories with 10 releases each$0.084
One organisation's 100 repositories$0.101
A 1,000-result search$0.301

Charging is charge-after-push: rows are in your dataset before the event is recorded. ACTOR_MAX_TOTAL_CHARGE_USD is respected — the run stops fetching when it is reached and finishes SUCCEEDED saying so.


Proxy

The default is { "useApifyProxy": true } — Apify's datacenter pool. GitHub answered the capture through it with the same quota numbers as with no proxy at all. Here the proxy does real work: without a token GitHub meters per IP, so each of the three request slots runs on its own proxy session, and a session whose quota runs out is swapped for a fresh one. You can switch to residential; you will not get different data. Without any proxy the run still works, but it shares your own address's 60 an hour and has nothing to rotate to.

The run holds itself to three requests in flight, 250 ms apart, pauses 250–600 ms between successive pages of one search or listing, and runs searches one at a time, because search has its own limit.


Use it from an AI agent, or from code

One JSON object in, one flat array out — the shape agent runtimes want. The Actor runs with limited permissions, uses pay-per-event pricing and never enters Standby, so it works over the Apify MCP server and with x402 agentic payments. The Integrations tab pushes results to Slack, a webhook, Zapier, Make, Google Sheets, Snowflake or BigQuery.

curl -X POST "https://api.apify.com/v2/acts/insight.solutions~github-repos-api/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"trending":["python","rust"],"trendingSince":"weekly","maxResults":10}'
# pip install apify-client
from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("insight.solutions/github-repos-api").call(run_input={
"searchQueries": ["topic:web-scraping stars:>500"],
"searchSort": "stars",
"maxResults": 200,
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
if row["rowType"] == "search-result":
print(row["rank"], row["fullName"], row["stars"], row["language"],
row["license"], row["pushedAt"], sep=" | ")
elif row["rowType"] == "diagnostic":
print("skipped:", row["errorType"], row["error"], row.get("resetAt"))

FAQ

Do I need a GitHub token? No. The default run uses 2 of the 60 requests an hour GitHub gives an anonymous IP. Add your own token when you want hundreds of repositories, long release histories or many searches.

What happens when the anonymous limit is reached? The Actor rotates to a fresh proxy exit once; if that is out too, a repository is read from its github.com page and releases from the Atom feed, and anything else returns a free rate-limited row with resetAt. See When GitHub says "rate limit exceeded".

Why are some watchers null? Because only the single-repository endpoint returns the real number of watchers. Search and organisation listings carry only the legacy watchers_count, which is the star count under another name, and this Actor will not pass that off as watchers.

Can I get more than 1,000 search results? Not for one query — GitHub stops there however it is paged, and its total_count (23,061 for stars:>1000 pushed:>2026-09-01) is the number of matches, not the number you can read. Split the query by a qualifier (stars:1000..5000, stars:>5000; or created: ranges) and run the pieces.

Does it read private repositories? No. Only public data, without login, whether or not you give a token.

Does it scrape developer profiles or emails? No, and that is deliberate — see No people, by design.

Is this affiliated with GitHub? No. This Actor is not affiliated with GitHub. It reads GitHub's public REST API and public pages and links back to every repository and release on github.com.


Limitations

  • The anonymous limit is GitHub's: 60 requests an hour per IP for the API, 10 a minute for search. The Actor works around it as described above, but a big run without a token will lean on the fallbacks, and fallback rows carry less.
  • Repository-page fallback rows have no language, size, pushedAt or has* switches — the page does not carry them.
  • Atom-feed release rows are the newest ten only, with no assets, no download counts and no publishedAt.
  • Search returns at most 1,000 results per query. totalCount tells you how many there were.
  • Trending is a web page, not an API. It usually lists 25 repositories (the capture this Actor was built on had 14), GitHub decides what is on it, and its layout can change; when the list does not parse, the run returns a free row saying so rather than a wrong number.
  • openIssues includes pull requests, as GitHub counts it.
  • The upstream format may change. GitHub versions its API (this Actor pins X-GitHub-Api-Version: 2022-11-28), but the trending page, repository pages and feeds are not versioned.

Our other Actors

Every Insight Solutions Actor is pay-per-result with no browser, no login and no API key, and every one of them returns free diagnostic rows instead of billing for failures. Prices are per 1,000 results.

Video, audio & social

News, documents & the web

Business, finance & jobs

Apps & games