# GitHub Email & Lead Enricher — Devs to CRM Leads | Official API (`bovi/github-profile-email-enricher`) Actor

Enrich GitHub user profiles into lead records with email, company, location, socials, metrics, and confidence. Run with usernames, orgs, repos, or search queries; add an optional token. Pricing: $0.0049 per github-lead event on the Free plan.

- **URL**: https://apify.com/bovi/github-profile-email-enricher.md
- **Developed by:** [Vitalii Bondarev](https://apify.com/bovi) (community)
- **Categories:** Lead generation, Developer tools
- **Features:** Limited permissions
- **Stats:** 35 total users, 6 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.75 / 1,000 github leads

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Email & Lead Enricher

Extract public GitHub developer profiles through the official GitHub REST API and turn them into lead records with email, company, location, socials, metrics, and confidence. No buyer key or login is required.

- Build recruiting lists from usernames, public organization members, repository contributors, or user-search matches.
- Enrich sales and CRM records with company, location, bio, socials, hireable status, and public metrics.
- Source developers behind an open-source project from `owner/repo` contributor inputs.
- Recover public emails from profiles or public commits when available, with the source on each row.

### What you get

Each returned person is an enriched developer lead; organizations are not returned.

| Field family | Fields | What it contains |
|---|---|---|
| Identity | `type`, `login`, `name`, `html_url` | Account type, login, display name, and profile URL. Leads use `type: "user"`. |
| Email | `email`, `email_source` | Profile or public-commit email. Source is `profile`, `commit`, or `none`. |
| Profile context | `company`, `location`, `bio`, `blog`, `twitter_username` | Company, location, biography, website, and social context; missing values can be `null`. |
| Work signal | `hireable` | GitHub’s open-to-work signal as Boolean or `null`. |
| Public metrics | `followers`, `following`, `public_repos`, `public_gists` | Public account and activity metrics. |
| Account dates | `account_created_at`, `profile_updated_at` | Account creation and profile update timestamps. |
| Resolution | `query` | Resolving input, such as `username`, `org:<name>`, `repo:<owner/repo>`, or `search:<query>`. |
| Collection time | `scraped_at` | UTC time associated with the record. |
| Quality | `parse_confidence`, `warnings` | Numeric confidence and normalization warnings. |

### Sample output

This is one real dataset record. The fields and values are copied exactly from the dataset sample, except the personal email address is shown as the literal value '<hidden for privacy>' to avoid exposing personal data.

```json
{
  "type": "user", "login": "torvalds", "name": "Linus Torvalds",
  "html_url": "https://github.com/torvalds",
  "email": "<hidden for privacy>", "email_source": "commit",
  "company": "Linux Foundation", "location": "Portland, OR",
  "blog": null, "twitter_username": null, "hireable": null, "bio": null,
  "followers": 329688, "following": 0, "public_repos": 12, "public_gists": 1,
  "account_created_at": "2011-09-03T15:26:22Z",
  "profile_updated_at": "2026-10-16T15:33:53Z",
  "query": "username", "scraped_at": "2026-10-28T02:26:35Z",
  "parse_confidence": 1, "warnings": []
}
```

### Pricing

This is pay per event. `github-lead` is one enriched developer lead and is charged once for every person record returned, including records without a public email.

| Plan | Price |
|---|---:|
| Free plan | $0.0049 per `github-lead` event |
| Bronze plan | $0.004851 per `github-lead` event |
| Silver plan | $0.004802 per `github-lead` event |
| Gold plan | $0.004753 per `github-lead` event |
| Platinum plan | $0.004704 per `github-lead` event |
| Diamond plan | $0.004655 per `github-lead` event |

Free-plan examples: 100 returned leads cost $0.49; 1,000 cost $4.90; 10,000 cost $49.00.

The Apify Free plan includes $5 of monthly platform usage credit. At this Actor’s Free-plan event price, that credit corresponds to 1,020 charged leads.

Actor charges and platform usage are separate. For this pay-per-event Actor, compute, Apify Proxy traffic including residential traffic, and storage are included in event prices and paid by the Actor developer. This Actor does not use “Pay per event + usage”, so the buyer does not separately pay platform usage.

### How to use

1. Choose any combination of direct usernames, organization logins, `owner/repo` repositories, and a GitHub user-search query.
2. Set `maxResults` to the maximum total number of leads across all inputs.
3. Enable `enrichEmailFromCommits` to check public commits for an email hidden from the profile; it is enabled by default.
4. Add an optional `githubToken` to raise the GitHub rate limit to 5,000 requests per hour. A token is not required for public data.
5. Run the Actor and inspect `email_source`, `parse_confidence`, and `warnings`.
6. Repeat the run through Apify Schedules; weekly is a reasonable starting point for a recurring developer-lead refresh.

```json
{
  "usernames": ["torvalds", "gvanrossum"],
  "maxResults": 2,
  "enrichEmailFromCommits": true,
  "disableUsageStats": false
}
```

Export the dataset as JSON or CSV, or read it through the Apify dataset API.

### Input parameters

| Parameter | What it does | Default |
|---|---|---|
| `usernames` | GitHub logins to enrich directly. | Empty list |
| `orgs` | Resolves every public member of each organization. | Empty list |
| `repos` | Resolves contributors from `owner/repo` repositories. | Empty list |
| `searchQuery` | GitHub user-search query, including syntax such as `location:berlin language:python`. | Empty string |
| `maxResults` | Maximum total leads across all inputs; must be at least `1`. | `100` |
| `enrichEmailFromCommits` | Checks public commit history when the profile email is hidden. | `true` |
| `githubToken` | Optional token for public API requests; raises the rate limit to 5,000 requests per hour and needs no scopes for public data. | Not set |
| `proxyConfiguration` | Apify proxy configuration; the schema default uses the `RESIDENTIAL` group. | {"useApifyProxy":true,"apifyProxyGroups":\["RESIDENTIAL"]} |
| `disableUsageStats` | Disables the usage statistics record described below. | `false` |

Inputs can be combined. Duplicate logins are removed case-insensitively, and `maxResults` applies to the combined resolved list. Without a token, anonymous access uses rotated proxy sessions. With a token and the untouched default proxy configuration, access is direct; an explicitly changed proxy configuration is used as supplied.

### Limits and edge cases

| Condition | What the buyer sees | What to do |
|---|---|---|
| No usable public email | The lead is returned and charged; `email` is `null` and `email_source` is `none` when recovery finds nothing. | Keep the row or filter on `email != null`. |
| Hidden profile email with commit recovery enabled | Public commits on the user’s own recent repositories are checked; real author emails can produce `email_source: "commit"`. | Leave `enrichEmailFromCommits` enabled for recovery. |
| Only excluded noreply addresses are found | They are not used as contact emails; the lead can still be returned. | Treat `email_source: "none"` as no recoverable public email. |
| User has no public repositories | Commit recovery is skipped because there is no repository source. | Use the returned profile fields. |
| Organization is placed in `usernames` | The organization is skipped because leads are people. | Put it in `orgs` to resolve public members. |
| Repository lacks `owner/repo` | The repository is skipped during resolution. | Use the owner and name separated by one slash. |
| No users can be resolved | The run reports `0 leads, nothing charged` and stores `OUTPUT` with `error: "no_users_resolved"`. | Check spelling and provide usernames, organizations, repositories, or a search query. |
| Profile lookup fails or reaches a rate limit | It is retried once with a fresh session; a second failure is recorded, while successful leads can still return. | Add a `githubToken` and rerun. |
| Commit-email lookup fails after profile fetch | The lead continues and can have a `null` email. | Use its `warnings` or rerun with recovery enabled. |
| Anonymous access reaches its per-IP limit | Anonymous access is limited to 60 requests per hour per IP; sessions are rotated. | Use the default Residential proxy or provide a token. |
| Search exceeds GitHub’s search limit | GitHub user search is capped at 1,000 results, and `maxResults` also applies. | Narrow the query or use targeted runs. |
| Repository has more contributors than the request reads | Up to 100 contributors are read and anonymous entries are skipped. | Use targeted repositories or additional input modes. |

### FAQ

#### How much does it cost to scrape GitHub developer leads?

The Free plan is $0.0049 per `github-lead` event. Each returned person is one event, including a person without a public email; 100 results cost $0.49 on Free.

#### What happens if a GitHub user has no public email?

The person can still be returned with profile, company, location, social, hireable, metric, and URL fields. When enabled, the Actor checks public commits for a real email and excludes privacy noreply addresses.

#### Why is my result empty?

Possible causes include unresolved usernames, an organization supplied through `usernames`, an invalid repository value, or GitHub access failures. Check the input format, use a public organization or `owner/repo`, and consider adding a `githubToken`.

#### What should I do if the Actor is not working?

Check the run status and inputs. A failed profile lookup is retried once with a fresh session; if it fails again, add the optional token and review `failedCount` and `failedDetails` in the run’s `OUTPUT` value when available.

#### Is it legal to use this public GitHub data?

The Actor collects public profile, organization-member, repository-contributor, user-search, and public-commit data through the official GitHub REST API. Whether a use is legal or allowed depends on source terms and applicable law for your use case, including how you contact people; this Actor provides no legal guarantee.

### Related actors

- [GitHub Scraper API — Repositories, Users & Data Export](https://apify.com/bovi/github-scraper) — for broader GitHub repository, user, or data-export results.
- [Email Finder — Name + Domain to Work Email + Score](https://apify.com/bovi/email-finder) — for a name and domain when a work-email result with a score is needed.
- [Bulk Email Verifier — Validate Emails, MX, Disposable & Role](https://apify.com/bovi/bulk-email-verifier) — for validating a list of emails, including MX, disposable, and role checks.

### Usage statistics

This Actor creates a small, content-free summary at the end of each run, used only to monitor reliability and improve this Actor. No input values, credentials or scraped data are sent.

A copy of the exact record for your run is saved as `USAGE_STATS` in your own Apify key-value store.

To opt out, set `disableUsageStats` to `true` in the input. Nothing is sent then.

[Full list of collected fields](https://api.apify.com/v2/key-value-stores/v9rgHjMKLDGtHf8tD/records/index.html)

# Actor input Schema

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

GitHub logins to enrich directly. Examples: \['torvalds', 'gvanrossum']. Each becomes one enriched lead.

## `orgs` (type: `array`):

GitHub org logins — every PUBLIC member of each org is enriched. Example: \['apify', 'huggingface']. Great for sourcing leads from a company's open-source team.

## `repos` (type: `array`):

Repositories whose CONTRIBUTORS you want as leads. Format 'owner/repo'. Example: \['apify/crawlee', 'psf/requests']. Reach the developers behind a project.

## `searchQuery` (type: `string`):

GitHub user-search query — matching users are enriched. Supports GitHub search syntax: 'location:berlin language:python', 'fullstack followers:>500'.

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

Maximum total enriched leads across all inputs. Default 100.

## `enrichEmailFromCommits` (type: `boolean`):

When a user hides their profile email (most do), mine their public commit history for the email they push with. Excludes GitHub's privacy noreply addresses. Adds ~1 API call per user. Recommended ON.

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

Optional personal access token (generate free at github.com/settings/tokens — no scopes needed for public data). Raises the rate limit to 5000 req/hr. Without it the actor rotates Apify proxy IPs to stay within the anonymous limit.

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

Apify proxy. Defaults to Residential — keep it on so requests rotate IPs and never hit GitHub from a single address.

## `disableUsageStats` (type: `boolean`):

See the README Usage statistics section for details.

## Actor input object example

```json
{
  "usernames": [
    "torvalds",
    "gvanrossum"
  ],
  "maxResults": 100,
  "enrichEmailFromCommits": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "disableUsageStats": false
}
```

# Actor output Schema

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

Dataset of enriched developer leads (login, name, email, email_source, company, location, hireable, followers, public_repos, twitter_username, html_url, parse_confidence).

# 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 = {
    "usernames": [
        "torvalds",
        "gvanrossum"
    ],
    "maxResults": 100,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("bovi/github-profile-email-enricher").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 = {
    "usernames": [
        "torvalds",
        "gvanrossum",
    ],
    "maxResults": 100,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("bovi/github-profile-email-enricher").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 '{
  "usernames": [
    "torvalds",
    "gvanrossum"
  ],
  "maxResults": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call bovi/github-profile-email-enricher --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bovi/github-profile-email-enricher"
        }
    }
}
```

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/sbagqSJ58PKLpXqlK/builds/5vEiIHakMpeZyhrLP/openapi.json
