# GitHub Scraper: Repos, Releases, Issues, PRs & Contributors (`winterlock/github-repo-scraper`) Actor

Export GitHub repository stats, releases with asset download counts, issues, pull requests, contributors, commits and repository search results. Official REST API, no HTML parsing. Works without a token; add one to lift the rate limit.

- **URL**: https://apify.com/winterlock/github-repo-scraper.md
- **Developed by:** [Alex Burton](https://apify.com/winterlock) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 repository (details or search hit)s

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## GitHub Scraper: Repos, Releases, Issues, PRs & Contributors

Export GitHub data to JSON, CSV or Excel without writing a line of API code. Everything comes from GitHub's official REST API, so nothing here breaks when GitHub redesigns its website.

One Actor, seven jobs:

| Mode | What you get |
|---|---|
| **Repository details** | Stars, forks, watchers, open issues, language, licence, topics, size, default branch, archived and fork flags, created/updated/pushed dates |
| **Releases** | Every release with its tag, notes, author, dates and **per-asset download counts**, plus a total across assets |
| **Issues** | Title, state, body, author, labels, assignees, milestone, comment count and dates |
| **Pull requests** | The same plus merged state, draft flag, head and base branches and requested reviewers |
| **Contributors** | Every contributor with their commit count |
| **Commits** | SHA, subject, full message, author and date (author email on request), optionally filtered by branch and start date |
| **Repository search** | Any GitHub search query, ranked, with full repository stats for each hit |

### Why use this one

- **Release download counts.** Most GitHub scrapers stop at stars. This one totals the download count of every binary attached to every release, which is the only public measure of how much a desktop or CLI tool is actually used.
- **Seven datasets, one Actor.** Track a competitor's repository, its release cadence, its issue backlog and who is contributing, without stitching together four tools.
- **Honest about rate limits.** The Actor reads GitHub's rate-limit headers on every response and warns you in the log before the budget runs out, instead of silently returning half a dataset.
- **Pull requests are separated from issues.** GitHub's issues endpoint quietly mixes pull requests in. This Actor filters them out by default so "Issues" means issues.

### Read this before your first run: the rate limit

GitHub allows **60 requests an hour from an anonymous IP address**. That is enough for about 60 repositories in Repository details mode, or 6,000 issues, and nothing more.

Adding a **free personal access token** raises the limit to **5,000 requests an hour**. The token needs no scopes at all for public data.

1. Go to github.com/settings/tokens and generate a fine-grained or classic token.
2. Tick no scopes. Public data needs none.
3. Paste it into the **GitHub token** field. It is stored encrypted and never appears in the dataset.

Repository search is limited separately: 10 queries a minute anonymously, 30 with a token.

### How to use it

1. Choose **What to scrape**.
2. Add **Repositories** as `owner/name` or GitHub links, or write **Search queries**.
3. Paste a **GitHub token**.
4. Click **Start**, then download the results or pull them through the Apify API.

#### Example input: every release of a repository with download counts

```json
{
  "mode": "releases",
  "repositories": ["yt-dlp/yt-dlp"],
  "maxResultsPerRepo": 50,
  "githubToken": "ghp_your_token_here"
}
```

#### Example input: open bugs across several repositories

```json
{
  "mode": "issues",
  "repositories": ["apify/crawlee", "scrapy/scrapy"],
  "issueState": "open",
  "labels": ["bug"],
  "maxResultsPerRepo": 500
}
```

#### Example input: find fast-growing Python projects

```json
{
  "mode": "searchRepos",
  "searchQueries": ["language:python stars:>5000 pushed:>2026-01-01"],
  "searchSort": "stars",
  "maxResultsPerRepo": 100
}
```

### Output

Each item carries a `type` field: `repo`, `release`, `issue`, `pullRequest`, `contributor` or `commit`.

**Repository**

```json
{
  "type": "repo",
  "repo": "apify/crawlee",
  "owner": "apify",
  "description": "Crawlee—A web scraping and browser automation library",
  "language": "TypeScript",
  "stars": 15234,
  "forks": 661,
  "watchers": 92,
  "openIssues": 118,
  "license": "Apache-2.0",
  "topics": ["crawler", "scraping", "playwright"],
  "defaultBranch": "master",
  "isArchived": false,
  "pushedAt": "2026-10-15T09:21:44Z",
  "url": "https://github.com/apify/crawlee"
}
```

**Release**

```json
{
  "type": "release",
  "repo": "yt-dlp/yt-dlp",
  "tag": "2026.10.01",
  "name": "yt-dlp 2026.10.01",
  "publishedAt": "2026-10-01T22:14:03Z",
  "isPrerelease": false,
  "assetCount": 12,
  "totalDownloads": 2841905,
  "assets": [
    { "name": "yt-dlp.exe", "downloads": 1204551, "sizeBytes": 12894720, "contentType": "application/octet-stream" }
  ]
}
```

### Pricing

Pay only for results:

| Result | Price |
|---|---|
| Repository (details or search hit) | $5.00 per 1,000 |
| Release, issue, pull request, contributor or commit | $1.00 per 1,000 |

Set a maximum spend per run in the run options and the Actor stops cleanly when it is reached.

### Limits to know about

- **The rate limit is the real constraint**, not this Actor. See the section above. Without a token, expect runs to stop early.
- **Repository search returns at most 1,000 results per query**, a GitHub limit. Narrow the query with `stars:`, `pushed:` or `language:` ranges to go deeper.
- **Contributors are capped at 500 by GitHub** on very large repositories, and anonymous contributors are not included.
- **`watchers`** is GitHub's subscriber count. GitHub's own `watchers_count` field is a duplicate of the star count, so it is deliberately not used here.
- Private repositories need a token with repository access. Without one they return nothing.

### FAQ

**Do I need a token?** No, but a run without one is limited to 60 requests an hour, which is very little. A free token with no scopes lifts it to 5,000.

**Is my token safe?** It is stored as an encrypted secret input, sent only to api.github.com, and never written to the dataset or the log.

**Can I track a repository daily?** Yes. Create a schedule in Apify Console and connect the dataset to Slack, Google Sheets, Zapier or Make.

**Why are some issues missing?** By default pull requests are filtered out of Issues mode. Turn on *Include pull requests in Issues mode* to keep them.

### Feedback

Found a bug or need a field that is missing? Open an issue on the Actor's **Issues** tab.

# Actor input Schema

## `mode` (type: `string`):

Repository facts, releases and their download counts, issues, pull requests, contributors, commits, or a repository search.

## `repositories` (type: `array`):

Use owner/name (apify/crawlee) or paste a GitHub link. Needed by every mode except Repository search.

## `searchQueries` (type: `array`):

For Repository search. Full GitHub search syntax works, for example: language:python stars:>1000 pushed:>2026-01-01

## `searchSort` (type: `string`):

Best match is GitHub's own relevance ranking.

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

Without a token GitHub allows only 60 requests an hour from one IP address, which is enough for a handful of repositories at most. A free personal access token with no scopes raises that to 5,000 an hour. Create one at github.com/settings/tokens. It is stored encrypted and is never written to the dataset.

## `issueState` (type: `string`):

For Issues and Pull requests. Open is what most people want; All returns closed ones too and uses more of the request budget.

## `labels` (type: `array`):

Keep only issues carrying all of these labels, for example bug, help wanted.

## `includePullRequestsInIssues` (type: `boolean`):

GitHub treats pull requests as issues. They are filtered out by default so Issues mode returns only real issues.

## `branch` (type: `string`):

Leave empty for the repository's default branch.

## `since` (type: `string`):

For example 2026-01-01T00:00:00Z. Leave empty for no limit.

## `includeAuthorEmails` (type: `boolean`):

For Commits. Off by default: author emails are personal data. Turn on only if you have a lawful reason to process them.

## `maxResultsPerRepo` (type: `integer`):

Each 100 results costs one API request against your rate limit.

## `maxItems` (type: `integer`):

Stop the run after saving this many items. Leave empty for no limit.

## `maxConcurrency` (type: `integer`):

GitHub counts every request against your hourly limit, so raising this spends the budget faster.

## `proxyConfiguration` (type: `object`):

Anonymous rate limits are counted per IP address, so a proxy can help when running without a token. A token is the better fix.

## Actor input object example

```json
{
  "mode": "repoDetails",
  "repositories": [
    "apify/crawlee"
  ],
  "searchQueries": [
    "language:python stars:>10000"
  ],
  "searchSort": "bestMatch",
  "issueState": "open",
  "includePullRequestsInIssues": false,
  "includeAuthorEmails": false,
  "maxResultsPerRepo": 100,
  "maxConcurrency": 4,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

# 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 = {
    "repositories": [
        "apify/crawlee"
    ],
    "searchQueries": [
        "language:python stars:>10000"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("winterlock/github-repo-scraper").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 = {
    "repositories": ["apify/crawlee"],
    "searchQueries": ["language:python stars:>10000"],
}

# Run the Actor and wait for it to finish
run = client.actor("winterlock/github-repo-scraper").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 '{
  "repositories": [
    "apify/crawlee"
  ],
  "searchQueries": [
    "language:python stars:>10000"
  ]
}' |
apify call winterlock/github-repo-scraper --silent --output-dataset

```

## MCP server setup

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

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/ur90ZdjgsfP6W4dFn/builds/B26OggP9ZkvSxZBzd/openapi.json
