# GitHub Repo Search API - Stars, Language, Date, Official API (`neverempty/github-repo-search`) Actor

Searches GitHub repositories through the official API and returns flat rows with stars, forks, license, topics and freshness. Adds stars-per-year and days-since-last-push, tells you plainly about GitHub's 1,000-result cap, and waits out rate limits instead of stopping half way.

- **URL**: https://apify.com/neverempty/github-repo-search.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Developer tools, AI, MCP servers
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$10.00 / 1,000 repository returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## GitHub Repo Search API - Stars, Language, Date, Official API

Search GitHub repositories through the **official REST API** and get flat, analysis-ready rows: stars, forks, language, license, topics, and how alive the project actually is.

### The thing every GitHub scraper runs into

**GitHub's search API will never return more than 1,000 results**, no matter how many matches exist. Ask for page 11 and it answers `HTTP 422`. A search that reports 7,670 matches still gives you 1,000 of them.

Measured on 2026-08-25: `language:javascript stars:>1000` → **7,670 matches, 1,000 retrievable**.

Most scrapers either stop with a partial result and say nothing, or fail outright. This one **says so in the log, in plain words, and tells you how to work around it** — split the query by date, e.g. `created:2024-01-01..2024-06-30`, and run it again.

The same goes for rate limits. GitHub allows **10 searches per minute anonymously, 30 with a token**. When you hit that ceiling, this Actor waits for the reset and carries on, rather than handing you half a dataset.

### Three columns the raw API does not give you

| Column | Why it matters |
|---|---|
| **`daysSinceLastPush`** | `0` means it was touched today; `900` means it is abandoned. No date arithmetic on your side |
| **`starsPerYear`** | 40,000 stars over ten years is not the same story as 40,000 over one. Brand-new repos are floored at one month so they cannot fake a huge rate |
| **`ageDays`** | How long the project has existed |

### A column deliberately left out

**`watchers`.** GitHub's search API does not return real watcher counts — the `watchers_count` field is a historical alias that equals the star count. Measured: a repo with 44,408 stars reports 44,408 "watchers". Publishing that as a watcher number would be handing you a fabricated statistic, so it is not in the output at all.

### What you get

```json
{
  "fullName": "facebook/react",
  "owner": "facebook",
  "ownerType": "Organization",
  "url": "https://github.com/facebook/react",
  "description": "The library for web and native user interfaces.",
  "homepage": "https://react.dev",
  "language": "JavaScript",
  "stars": 247689,
  "forks": 51000,
  "openIssues": 980,
  "license": "MIT",
  "licenseName": "MIT License",
  "topics": ["javascript", "react", "frontend", "ui"],
  "isFork": false,
  "isArchived": false,
  "createdAt": "2013-05-24T16:15:54Z",
  "pushedAt": "2026-08-25T00:00:00Z",
  "daysSinceLastPush": 0,
  "ageDays": 4841,
  "starsPerYear": 18691.8,
  "sizeKb": 1024000,
  "defaultBranch": "main",
  "source": "GitHub REST API (official)"
}
```

### Input

```json
{
  "query": "language:python stars:>500 pushed:>2026-01-01",
  "sort": "stars",
  "maxResults": 500,
  "excludeArchived": true
}
```

| Field | Default | Meaning |
|---|---|---|
| `query` | `language:javascript stars:>1000` | Any GitHub search query, exactly as on github.com |
| `sort` | `stars` | `stars`, `forks`, `updated`, `help-wanted-issues`, `best-match` |
| `order` | `desc` | Biggest first, or smallest first |
| `maxResults` | `100` | Up to 1,000 — GitHub's own hard limit |
| `minStars` | `0` | Extra filter applied after fetching |
| `excludeForks` / `excludeArchived` | `false` | Drop forks / archived projects |
| `githubToken` | empty | Optional. Raises the limit from 10 to 30 searches per minute. **No scopes needed** for public repositories |
| `waitForRateLimit` | `true` | Wait out the limit instead of returning a partial result |

### Typical uses

- Finding maintained alternatives to a library (`daysSinceLastPush` sorts the living from the dead)
- Competitive and ecosystem research
- Building lists of projects by language, topic or licence
- Tracking which tools are actually gaining traction (`starsPerYear`, not lifetime stars)
- Due diligence on dependencies: licence, archived status, issue backlog

### FAQ

**Do I need a token?**
No. Without one you get 10 searches per minute, which is enough for a few hundred results. With one, 30 per minute.

**Is a token safe to paste here?**
The field is marked secret, and public repository search needs **no scopes at all** — create a token with nothing ticked.

**How do I get more than 1,000 results?**
Split the query. `created:2020-01-01..2020-12-31`, then 2021, and so on. Each slice gets its own 1,000.

**Does it scrape github.com?**
No. It uses `api.github.com`, GitHub's documented REST API, with the versioned API header.

**What if my search matches nothing?**
Zero rows and a log line saying the search succeeded but matched nothing — not an error, and not a silent blank.

### Other tools by NeverEmpty

Every NeverEmpty Actor follows the same rule: it never returns an empty result to mean two different things, and it only charges for rows that actually carry an answer.

- **[ats-jobs-api](https://apify.com/neverempty/ats-jobs-api)** - every open job from a Greenhouse, Lever, Ashby or Workable board, one schema
- **[link-checker](https://apify.com/neverempty/link-checker)** - broken links on a site, with blocked told apart from dead
- **[domain-lookup](https://apify.com/neverempty/domain-lookup)** - WHOIS, DNS, MX, SPF, DMARC and SSL expiry for a list of domains

### Support

Something missing or wrong? Open an issue on the **Issues** tab with the query you used.

# Actor input Schema

## `query` (type: `string`):

A GitHub search query, exactly as you would type it on github.com. Examples: "language:python stars:>500", "machine learning pushed:>2026-01-01", "org:apify". GitHub returns at most 1,000 results per query - split by date range to get more.

## `sort` (type: `string`):

Which field GitHub sorts on before the 1,000-result cut-off is applied.

## `order` (type: `string`):

Descending puts the biggest or newest first.

## `maxResults` (type: `integer`):

How many repositories to return. GitHub itself caps any single search at 1,000 - asking for more will not fail silently, it will tell you in the log.

## `minStars` (type: `integer`):

Drop repositories below this star count after fetching. Usually better to put stars:>N in the query itself.

## `excludeForks` (type: `boolean`):

Skip repositories that are forks of another project.

## `excludeArchived` (type: `boolean`):

Skip repositories the owner has archived (read-only, no longer maintained).

## `githubToken` (type: `string`):

A personal access token raises the search rate limit from 10 to 30 requests per minute. No scopes are needed for public repositories. Leave empty to run without one.

## `waitForRateLimit` (type: `boolean`):

When GitHub says to slow down, wait until the limit resets and continue, instead of stopping with a partial result.

## Actor input object example

```json
{
  "query": "language:javascript stars:>1000",
  "sort": "stars",
  "order": "desc",
  "maxResults": 100,
  "minStars": 0,
  "excludeForks": false,
  "excludeArchived": false,
  "waitForRateLimit": true
}
```

# Actor output Schema

## `results` (type: `string`):

All repositories produced by this run.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/github-repo-search").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/github-repo-search").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call neverempty/github-repo-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/github-repo-search"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/lwPiVaIdisjM7YQkX/builds/59zTZb9wZV9l1cj51/openapi.json
