# GitHub User Scraper — Profiles, Repos & Orgs (`w3crawler/github-user-scraper`) Actor

Fetch public GitHub user or organization metadata, bounded public repositories, public organizations, and explicit diagnostics.

- **URL**: https://apify.com/w3crawler/github-user-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 users, repositories & organizations

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 User Scraper do?

GitHub User Scraper collects **public GitHub profiles**, bounded public repository lists, and public organizations using the [GitHub REST API](https://docs.github.com/en/rest) for one or more accounts. It preserves source URLs, record type, stable identity, access status, and timestamps; it does not access private areas or invent missing fields.

### Why use GitHub User Scraper?

Use this Actor for an auditable public profile export, lightweight repository and organization enrichment, or scheduled monitoring of accounts you are authorized to analyze. Profile, repository, organization, and diagnostic rows are explicitly discriminated, so downstream workflows can consume them safely. Apify provides run history, API access, scheduling, integrations, and monitoring around the extraction. Repository and organization counts are bounded per account, and the Actor uses documented public endpoints only. **Pinned repositories are opt-in** and require a caller-supplied GitHub token for the public GraphQL endpoint; ordinary REST repository results are never mislabeled as pinned. Proxy rotation is not used.

### What data can GitHub User Scraper extract?

| Record         | Useful fields                                                                                           | Description                                             |
| -------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| `profile`      | `login`, `accountType`, `name`, `bio`, `location`, `followers`, `publicRepos`, `profileUrl`             | Public user or organization profile data.               |
| `repository`   | `repositoryName`, `fullName`, `repositoryUrl`, `language`, `topics`, `stargazersCount`, `isPinned`      | Bounded public repositories for each processed account. |
| `organization` | `organizationLogin`, `organizationUrl`, `description`, `publicRepos`, `publicMembers`                   | Organizations exposed by a public user profile.         |
| Any row        | `recordType`, `recordId`, `dataAvailable`, `accessStatus`, `extractionMethod`, `sourceUrl`, `scrapedAt` | Stable contract and provenance fields.                  |
| `diagnostic`   | `url`, `error`, `errorCode`                                                                             | Minimal source failure details without fabricated data. |

### How to scrape GitHub users and repositories

1. Open the Actor in Apify Console and add account logins or `github.com` profile URLs to the Input tab.
2. Choose whether to include repositories, organizations, or token-backed pinned repositories, and set their per-account limits.
3. Start the run, review the dataset and `OUTPUT` summary, then connect the dataset through the API, an integration, or a schedule.

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

Apify billing follows the selected Actor pricing and compute used by each run; no fixed price is promised here. Each account can trigger profile, repository, organization, and optional GraphQL requests. More accounts, larger per-account limits, retries, and long timeouts increase request volume or run time. Use small limits for smoke tests and respect GitHub’s public rate limits.

### Input

See the input tab for the complete configuration. `accounts`, `usernames`, and `urls` are string arrays; `username` and `login` are single-value compatibility aliases. All supplied accounts are combined in that order, trimmed, validated, restricted to a one-segment public GitHub profile, deduplicated case-insensitively, and capped globally by `maxAccounts` (1–10, default 5). With no account, the default is `octocat`. Invalid values are rejected; the Actor does not silently fall back to the default after a malformed value.

`includeRepositories` and `includeOrganizations` default to `true`, with `maxRepositories` 1–50 (default 10) and `maxOrganizations` 1–50 (default 20) per account. `includePinnedRepositories` defaults to `false`; enabling it without `githubToken` produces a diagnostic. `githubToken` may also come from the `GITHUB_TOKEN` environment secret, is sent only as authorization, and is never written to output. Developer controls are `requestDelayMs` 0–2000 (default 100), `maxRetries` 1–4 (default 2), and `timeoutSecs` 5–120 (default 30). This Actor does not accept `startUrls`, browser settings, or proxy configuration.

#### Minimal run

```json
{}
```

#### Multiple accounts with enrichment

```json
{
  "accounts": ["octocat", "github", "torvalds"],
  "maxAccounts": 3,
  "includeRepositories": true,
  "maxRepositories": 3,
  "includeOrganizations": true,
  "maxOrganizations": 5,
  "requestDelayMs": 250
}
```

#### Public pinned repositories with developer controls

```json
{
  "accounts": ["octocat"],
  "includeRepositories": false,
  "includeOrganizations": false,
  "includePinnedRepositories": true,
  "githubToken": "<stored-in-console-secret>",
  "requestDelayMs": 0,
  "maxRetries": 1,
  "timeoutSecs": 30
}
```

### Output

Every row has a `recordType` and stable `recordId`. Normal rows are source-backed public data with `dataAvailable: true`; diagnostics use `dataAvailable: false`, `accessStatus: "unavailable"`, and only bounded failure metadata. Missing optional source fields are omitted. Repository limits are per account and the dataset is not a paginated global search; organization requests are user-only, while pinned repositories are user-only GraphQL results.

#### Profile row

```json
{
  "recordType": "profile",
  "recordId": "github-user:profile:octocat",
  "dataAvailable": true,
  "accessStatus": "public",
  "extractionMethod": "github_rest_api",
  "account": "octocat",
  "login": "octocat",
  "accountType": "User",
  "profileUrl": "https://github.com/octocat",
  "sourceUrl": "https://api.github.com/users/octocat",
  "scrapedAt": "2026-09-08T00:00:00.000Z"
}
```

#### Diagnostic row and run summary

```json
{
  "recordType": "diagnostic",
  "recordId": "github-user:diagnostic:account_request_failed:https%3A%2F%2Fapi.github.com%2Fusers%2Fmissing-user",
  "dataAvailable": false,
  "accessStatus": "unavailable",
  "extractionMethod": "github_rest_api",
  "url": "https://api.github.com/users/missing-user",
  "error": "Not Found",
  "errorCode": "ACCOUNT_REQUEST_FAILED",
  "scrapedAt": "2026-09-08T00:00:00.000Z"
}
```

`OUTPUT` summarizes status, normalized accounts, profile/repository/organization/diagnostic counts, request totals, optional pinned counts, sanitized rate-limit samples, configuration flags, duration, and completion time. You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

### Tips and advanced options

Start with one account and small per-account limits. Increase `requestDelayMs` or reduce concurrency pressure when public rate limits are low. `maxRetries` retries transient HTTP failures only; a source failure is retained as a diagnostic and does not become a fake profile or repository. Keep tokens in Apify secret input storage and do not paste them into shared examples or downstream logs.

### FAQ, support, and responsible use

If output contains diagnostics, inspect the row’s `errorCode`, `url`, and `OUTPUT` counts. GitHub may change public fields or rate limits between runs. Report bugs in the Actor’s Issues tab with the run ID, input, summary, and affected public URL. Use only information account owners made public, follow GitHub’s terms and rate limits, respect privacy and applicable law, and obtain legal advice for personal-data processing. This Actor is not affiliated with or endorsed by GitHub.

#### Local verification

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

# Actor input Schema

## `accounts` (type: `array`):

Public GitHub user or organization login names, or github.com profile URLs.

## `usernames` (type: `array`):

Compatibility alias for accounts.

## `username` (type: `string`):

Compatibility alias for one public GitHub login.

## `login` (type: `string`):

Compatibility alias for one public GitHub login or organization login.

## `urls` (type: `array`):

Compatibility alias for public github.com profile URLs.

## `maxAccounts` (type: `integer`):

Maximum unique accounts to process.

## `includeRepositories` (type: `boolean`):

Fetch a bounded list of public repositories for each account.

## `maxRepositories` (type: `integer`):

Maximum public repositories emitted per account.

## `includeOrganizations` (type: `boolean`):

List organizations that the public user profile exposes.

## `maxOrganizations` (type: `integer`):

Maximum public organizations emitted for each user account.

## `includePinnedRepositories` (type: `boolean`):

Use GitHub GraphQL for public user pins. Requires a caller-supplied githubToken; no token means an explicit diagnostic.

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

Optional caller-supplied token for higher public API limits and pinned repositories. Never included in output.

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

Polite delay between account workflows.

## `maxRetries` (type: `integer`):

Attempts for transient public API failures.

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

Timeout for each public API request.

## Actor input object example

```json
{
  "accounts": [
    "octocat"
  ],
  "maxAccounts": 5,
  "includeRepositories": true,
  "maxRepositories": 10,
  "includeOrganizations": true,
  "maxOrganizations": 20,
  "includePinnedRepositories": false,
  "requestDelayMs": 100,
  "maxRetries": 2,
  "timeoutSecs": 30
}
```

# Actor output Schema

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

No description

## `output` (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-user-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-user-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-user-scraper --silent --output-dataset

```

## MCP server setup

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