# GitHub Contributors Scraper (`w3crawler/github-contributors-scraper`) Actor

Extract public ranked contributors and repository metadata from GitHub repositories with optional public profile enrichment.

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

## Pricing

from $2.99 / 1,000 contributors

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

### What does GitHub Contributors Scraper do?

**GitHub Contributors Scraper** extracts ranked public contributors for one or more public [GitHub](https://github.com) repositories through GitHub's documented REST API. It is an API-oriented alternative to manually reviewing a repository's contributor list and can optionally fetch each selected contributor's public profile.

The Actor uses direct, unauthenticated public requests. It does not access private repositories, log in, accept caller tokens, bypass access controls, or fabricate missing values. Proxy configuration is not supported or accepted; requests are sent directly to GitHub.

### Why use GitHub Contributors Scraper?

Use it for maintainer discovery, open-source project analysis, contribution ranking, and public profile context. Multiple repositories are normalized and deduplicated, processed sequentially, and limited to 20 repositories. Contributor rows and profile rows are intentionally separate: every normal row has a `recordType` and stable `recordId`, so bots, users, and profile enrichments cannot be confused. Transient timeouts and HTTP 408, 429, and 5xx responses receive bounded retries with backoff; other failures become explicit diagnostics.

### What data can it extract?

| Group       | Fields                                                                                            |
| ----------- | ------------------------------------------------------------------------------------------------- |
| Identity    | `recordType`, `recordId`, `repository`, `repositoryId`, `repositoryUrl`, `login`, `profileUrl`    |
| Ranking     | `contributorRank`, `contributions`, `contributorType`                                             |
| Profile     | `name`, `company`, `location`, `bio`, `avatarUrl`, `publicRepos`, `followers`, `following`        |
| Provenance  | `sourceUrl`, `extractionMethod`, `accessStatus`, `dataAvailable`, `enrichmentStatus`, `scrapedAt` |
| Diagnostics | `recordType=diagnostic`, `url`, `httpStatus`, `errorCode`, and bounded `error`                    |

### How to scrape GitHub contributors

1. Open the Actor's **Input** tab.
2. Enter `owner/repository` names or public GitHub repository URLs.
3. Choose the contributor limit and whether public profiles should be enriched.
4. Adjust the bounded timeout, delay, or transient retry count when needed.
5. Start the run and inspect normal records separately from diagnostics using `recordType`.

### How much will it cost to scrape GitHub contributors?

The Actor's cost depends on the Apify plan and the number of dataset items written. Each repository requires a metadata request and a contributors request; profile enrichment adds up to one request per contributor with a public profile URL. More repositories, contributors, retries, and longer timeouts can increase run time and compute. Sequential execution and a configurable delay keep traffic conservative.

### Input

See the input tab for the complete configuration. The accepted input is a JSON object:

#### Default smoke test

```json
{}
```

#### Multiple repositories

```json
{
  "repositories": ["apify/apify-cli", "https://github.com/octocat/Hello-World"],
  "maxContributors": 10
}
```

#### Profile enrichment

```json
{
  "repositories": ["apify/apify-cli"],
  "maxContributors": 3,
  "includeProfiles": true
}
```

#### Developer options

```json
{
  "repositories": ["apify/apify-cli"],
  "maxContributors": 3,
  "timeoutSecs": 30,
  "requestDelayMs": 100,
  "maxRequestRetries": 1
}
```

`repositories` accepts at most 20 unique public repositories and defaults to `apify/apify-cli` when omitted or empty. `maxContributors` is 1–100 per repository. `includeProfiles` is false by default. `timeoutSecs` is 5–120 seconds, `requestDelayMs` is 0–5000 milliseconds, and `maxRequestRetries` is 0–3. Unknown properties, malformed repository names, and unsupported proxy settings are rejected.

### Output

Contributor and profile rows share repository/login provenance but have different `recordType` values (`contributor` or `profile`) and stable IDs. A profile row is emitted only after its public profile request succeeds. Missing optional profile values are omitted. Diagnostics use `recordType=diagnostic`, `dataAvailable=false`, an `errorCode`, and the source URL; they are not successful contributor data. `OUTPUT_SUMMARY` reports requested and processed repositories, contributor/profile counts, retry-aware completion status, and diagnostic counts.

#### Contributor record

```json
{
  "recordType": "contributor",
  "recordId": "example%2Fproject:contributor:octocat",
  "repository": "example/project",
  "repositoryId": 123456,
  "repositoryUrl": "https://github.com/example/project",
  "contributorRank": 1,
  "login": "octocat",
  "profileUrl": "https://github.com/octocat",
  "contributions": 42,
  "contributorType": "User",
  "dataAvailable": true,
  "accessStatus": "public",
  "extractionMethod": "github_rest_api",
  "enrichmentStatus": "not_requested",
  "sourceUrl": "https://api.github.com/repos/example/project/contributors?per_page=3&anon=false",
  "scrapedAt": "2026-08-24T00:00:00.000Z"
}
```

#### Profile record

```json
{
  "recordType": "profile",
  "recordId": "example%2Fproject:profile:octocat",
  "repository": "example/project",
  "login": "octocat",
  "profileUrl": "https://github.com/octocat",
  "name": "Example Author",
  "publicRepos": 8,
  "followers": 12,
  "following": 4,
  "dataAvailable": true,
  "accessStatus": "public",
  "extractionMethod": "github_rest_api",
  "enrichmentStatus": "succeeded",
  "sourceUrl": "https://api.github.com/users/octocat",
  "scrapedAt": "2026-08-24T00:00:00.000Z"
}
```

#### Diagnostic record

```json
{
  "recordType": "diagnostic",
  "recordId": "example%2Fproject:diagnostic:REPOSITORY_REQUEST_FAILED:https%3A%2F%2Fapi.github.com%2Frepos%2Fexample%2Fproject",
  "repository": "example/project",
  "dataAvailable": false,
  "accessStatus": "unavailable",
  "extractionMethod": "github_rest_api",
  "httpStatus": 404,
  "url": "https://api.github.com/repos/example/project",
  "error": "Not found (HTTP 404)",
  "errorCode": "REPOSITORY_REQUEST_FAILED",
  "scrapedAt": "2026-08-24T00:00:00.000Z"
}
```

#### Run summary

```json
{
  "actor": "github-contributors-scraper",
  "status": "succeeded",
  "dataAvailable": true,
  "repositories": ["example/project"],
  "repositoriesRequested": 1,
  "repositoriesProcessed": 1,
  "contributorCount": 3,
  "profileRequestedCount": 3,
  "profileCount": 3,
  "normalRecordCount": 6,
  "diagnosticCount": 0,
  "completedAt": "2026-08-24T00:00:00.000Z"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

### Tips and advanced options

Use `includeProfiles=false` for the lowest request volume. Keep a delay when processing several repositories, increase retries only for transient failures, and keep contributor limits reasonable for unauthenticated GitHub API use. The summary status is `succeeded` when all work has normal results, `partial` when normal results coexist with diagnostics, and `blocked-or-empty` when no contributor rows were available. A missing profile is never represented as a fabricated profile record.

### FAQ, support, and responsible use

If a run has no normal rows, inspect `OUTPUT_SUMMARY` and the diagnostic `errorCode`; a rate limit, unavailable repository, timeout, or empty contributor list is reported explicitly. For bugs, include the run ID, input, summary, and representative diagnostic in the Actor's Issues tab. The API tab provides programmatic dataset and summary access.

Use only public data and follow GitHub's terms, API limits, robots guidance where applicable, and all privacy and data-protection laws. Our Actors do not extract private user data or bypass access controls, but public profile data can still be personal data; use it lawfully and consult qualified counsel when required. This Actor is not affiliated with GitHub.

### Local validation

```bash
npm ci
npm run check
npm test
apify validate-schema
apify run --purge --input-file test/inputs/live-smoke.json
npm run validate
```

# Actor input Schema

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

GitHub repository URLs or owner/repository names. Up to 20 unique public repositories are processed sequentially.

## `maxContributors` (type: `integer`):

Maximum ranked public contributors requested per repository.

## `includeProfiles` (type: `boolean`):

Fetch one public profile response for each contributor.

## `timeoutSecs` (type: `integer`):

Timeout applied to each public GitHub request.

## `requestDelayMs` (type: `integer`):

Delay between repository and profile requests.

## `maxRequestRetries` (type: `integer`):

Bounded retries for timeouts and transient HTTP statuses (408, 429, and 5xx). Other failures are not retried.

## Actor input object example

```json
{
  "repositories": [
    "apify/apify-cli"
  ],
  "maxContributors": 30,
  "includeProfiles": false,
  "timeoutSecs": 20,
  "requestDelayMs": 250,
  "maxRequestRetries": 1
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `runSummary` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("w3crawler/github-contributors-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("w3crawler/github-contributors-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 '{}' |
apify call w3crawler/github-contributors-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,w3crawler/github-contributors-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/e34ZmcKFtmZTjhuzt/builds/kzwhSlDfS1qjaXhvt/openapi.json
