# GitHub Email Scraper & Tech Stack Extractor (Patch & MX) (`vesper_studio/github-developer-email-extractor`) Actor

GitHub Email Scraper & Lead Generation Actor. Extract verified developer emails (.patch commits, DCO Sign-off, Events API) & tech stacks from repo contributors, stargazers, or usernames. Built-in DNS MX deliverability check (<2% bounce). 100% HTTP, 256MB RAM.

- **URL**: https://apify.com/vesper_studio/github-developer-email-extractor.md
- **Developed by:** [Xavier Richard](https://apify.com/vesper_studio) (community)
- **Categories:** Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.50 / 1,000 results

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 Developer Email & Tech Stack Extractor (Commit Patch & MX Verified)

**GitHub Email Scraper & Developer Lead Generation Actor** — Extract verified developer emails, full profiles, and inferred tech stacks from **GitHub repository contributors**, **GitHub stargazers**, or **direct username lists**.

Unlike basic GitHub profile scrapers that fail when a developer hides their public profile email, this Actor inspects **public Git commit headers (`.patch`)**, **DCO sign-off trailers (`Signed-off-by:`)**, **GitHub Events API (`PushEvent`)**, and **Profile `README.md` repositories**, then validates every extracted email through a **native DNS MX deliverability engine (`node:dns/promises`)** to guarantee a **< 2% bounce rate**.

***

### Why Use This GitHub Email Extractor? (Value Proposition)

- **Bypasses Hidden Profile Emails Legitimately**: Over 80% of developers hide their email on their main GitHub profile page, yet expose their real corporate or personal email inside Git commit metadata (`.patch` headers and `Signed-off-by` trailers).
- **Competitor Stargazer & Contributor Poaching (`stargazers` & `contributors`)**: Target any open-source repository (e.g., `langchain-ai/langchain`, `rust-lang/rust`, `vercel/next.js`) to extract developers actively using or contributing to a specific technology or competitor DevTool.
- **Built-In DNS MX Verification (< 2% Bounce Rate)**: Every extracted email is checked against live DNS `MX` records (`resolveMx`), rejecting dead domains, RFC 7505 Null MX records, 250+ disposable email providers (`tempmail`, `guerrillamail`, `mailinator`, `yopmail`), and GitHub privacy masks (`@users.noreply.github.com`).
- **MX Provider Fingerprinting**: Automatically identifies whether the developer uses **Google Workspace**, **Microsoft 365**, **Proton Mail**, **OVHcloud**, **Zoho Mail**, **Fastmail**, **Cloudflare Email Routing**, or a custom corporate mail server.
- **Anti-False-Positive PR Merge Filter**: Intelligently cross-references commit author metadata against the target developer's identity so a maintainer merging an external contributor's Pull Request is never assigned the wrong email.
- **Ultra-Low Compute Cost (100% HTTP, 256 MB RAM)**: Powered by `got-scraping` without headless browsers (no Playwright/Puppeteer). Costs less than **$0.001 per 100 profiles** in Apify platform compute.

***

### Top Use Cases (Tech Recruiting, DevTools GTM & OSINT)

1. **Technical Recruiting & Executive Sourcing**: Find senior Rust, AI/LLM, Go, TypeScript, or Kubernetes engineers contributing to top open-source projects, filtered by location (`locationFilter: "France"`, `"Germany"`, `"United States"`, `"Remote"`).
2. **DevTools & B2B SaaS Growth (Stargazer Lead Gen)**: Extract developers who recently starred your repository or a competitor's repository (`targetMode: "stargazers"`) and enrich them with verified work emails and company names.
3. **AI Agent & Clay / n8n / Make Workflows**: Connect directly as an **MCP tool**, **Clay enrichment column**, or **n8n HTTP/Apify node** to turn a list of GitHub URLs (`targetMode: "direct_users"`) into MX-verified emails and tech stacks.

***

### 4-Stage Extraction & Qualification Pipeline

1. **Stage 1 — Target Profile Collection**:
   - **Contributors Mode (`contributors`)**: `GET https://api.github.com/repos/{owner}/{repo}/contributors`
   - **Stargazers Mode (`stargazers`)**: `GET https://api.github.com/repos/{owner}/{repo}/stargazers` (with `Accept: application/vnd.github.v3.star+json` to capture `starred_at` timestamps)
   - **Direct Users Mode (`direct_users`)**: Accepts raw GitHub usernames (`torvalds`) or profile URLs (`https://github.com/torvalds`). Automatically excludes `[bot]` accounts (`dependabot`, `renovate`, `github-actions`).
2. **Stage 2 — Multi-Vector Commit & Patch Email Extraction**:
   - **Step 2A (GitHub Public Events API)**: Scans `GET https://api.github.com/users/{username}/events/public` for `PushEvent` payloads (`payload.commits[*].author.email`).
   - **Step 2B (Commit `.patch` & DCO Fallback)**: Fetches raw Git commit patches (`GET https://github.com/{owner}/{repo}/commit/{sha}.patch`) on the source repository and the developer's most recently pushed repositories. Extracts emails via `/^From: .* <(.*@.*)>$/m` as well as `Signed-off-by:` and `Co-authored-by:` trailers.
   - **Step 2C (Zero-API-Quota Profile README Fallback)**: If all commits use `noreply`, inspects `https://raw.githubusercontent.com/{username}/{username}/HEAD/README.md` (costs 0 GitHub REST API quota).
3. **Stage 3 — Strict Filtering & Lead Prioritization**:
   - Strips `*@users.noreply.github.com`, `*@noreply.github.com`, placeholder emails (`test@test.com`, `user@localhost`, `example@domain.com`), local hostnames, and 250+ disposable domains.
   - Prioritizes custom corporate domains (`john.doe@company.com`) over consumer webmail (`gmail.com`) and flags shared role accounts (`info@`, `security@`, `support@`) as `"risky"`.
4. **Stage 4 — Native DNS MX Deliverability Verification**:
   - Executes `dns.resolveMx(domain)` with in-memory domain caching, timeout protection, and `mxProvider` deduction.

***

### Input Parameters (`input_schema.json`)

| Parameter           | Type       | Default                                        | Description                                                                                                                                                                                        |
| :------------------ | :--------- | :--------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `targets`           | `string[]` | `["langchain-ai/langchain", "rust-lang/rust"]` | List of GitHub repositories (`owner/repo` or full GitHub URLs) or developer usernames/profile URLs.                                                                                                |
| `targetMode`        | `string`   | `"contributors"`                               | `"contributors"`, `"stargazers"`, or `"direct_users"`.                                                                                                                                             |
| `maxUsersPerTarget` | `integer`  | `50`                                           | Maximum number of developers to analyze per target repository (`1` – `1000`).                                                                                                                      |
| `githubTokens`      | `string[]` | `[]`                                           | Optional pool of GitHub Personal Access Tokens (`ghp_...` / `github_pat_...`) to scale from 60 req/h to **5,000 req/h per token** with automatic rotation and `ETag` (`304 Not Modified`) caching. |
| `onlyWithEmail`     | `boolean`  | `true`                                         | Only output profiles in the Dataset when a real, non-noreply, MX-verified email address is found.                                                                                                  |
| `locationFilter`    | `string`   | `""`                                           | Optional geographic filter (e.g. `"France"`, `"Germany"`, `"London"`, `"Remote"`). Includes smart country-to-city matching (`"France"` matches `"Paris"`, `"Lyon"`, `"Nantes"`, etc.).             |
| `maxConcurrency`    | `integer`  | `5`                                            | Number of developer profiles processed in parallel (`1` – `20`).                                                                                                                                   |

***

### Input Example

```json
{
    "targets": ["langchain-ai/langchain", "rust-lang/rust"],
    "targetMode": "contributors",
    "maxUsersPerTarget": 50,
    "githubTokens": [],
    "onlyWithEmail": true,
    "locationFilter": "France",
    "maxConcurrency": 5
}
```

***

### Output Dataset Example

Each item in the Apify Dataset is normalized with the following JSON schema:

```json
{
    "username": "johndoe",
    "fullName": "John Doe",
    "email": "john.doe@company.com",
    "deliverability": "valid",
    "mxProvider": "Google Workspace",
    "company": "Acme Corp",
    "location": "Paris, France",
    "bio": "Building scalable Rust backends and AI agents.",
    "blog": "https://johndoe.dev",
    "twitter": "johndoe_dev",
    "publicReposCount": 42,
    "followersCount": 180,
    "techStack": ["Rust", "Python", "LangChain", "AI / LLM"],
    "sourceRepo": "rust-lang/rust",
    "sourceRole": "contributor",
    "commitProofUrl": "https://github.com/rust-lang/rust/commit/a1b2c3d4e5.patch",
    "scrapedAt": "2026-10-20T01:00:00.000Z"
}
```

In addition, the Actor writes a comprehensive **`RUN_SUMMARY`** record into the default Key-Value Store containing extraction telemetry, MX provider distribution, tech stack frequency, and rate-limit statistics.

***

### Frequently Asked Questions (FAQ)

#### Do I need a GitHub Personal Access Token (`githubTokens`)?

For small runs (up to ~15–20 developers), the Actor works **without any token** using unauthenticated GitHub requests (60 REST API req/h + unlimited `.patch` requests). For larger runs (`50` to `1,000` developers per target), adding one free GitHub PAT (`ghp_...` with no special permissions required) unlocks **5,000 requests/hour per token**.

#### How does `.patch` email extraction work?

Every public commit on GitHub can be viewed in raw Git patch format by appending `.patch` to the commit URL (`https://github.com/{owner}/{repo}/commit/{sha}.patch`). This header contains the author's `From: Name <email@domain.com>` and optional `Signed-off-by:` lines configured in their local `.gitconfig`.

#### Can I use this Actor with Clay, n8n, Make, or MCP AI Agents?

Yes. Set `targetMode: "direct_users"` and pass a list of GitHub usernames or profile URLs in `targets` to enrich existing candidate or prospect tables in Clay, n8n, or Make, or pass competitor repositories with `targetMode: "stargazers"` to automate weekly GTM lead generation.

# Actor input Schema

## `targets` (type: `array`):

List of GitHub repositories (e.g. \["langchain-ai/langchain", "rust-lang/rust"]) or full GitHub repository / profile URLs (e.g. "https://github.com/langchain-ai/langchain", "https://github.com/torvalds").

## `targetMode` (type: `string`):

Source of developers to analyze: repository contributors, repository stargazers (via application/vnd.github.v3.star+json), or a direct list of GitHub usernames/URLs.

## `maxUsersPerTarget` (type: `integer`):

Maximum number of developers to analyze per target repository (1 to 1,000).

## `githubTokens` (type: `array`):

Optional list of one or more GitHub Personal Access Tokens (ghp\_... or github_pat\_...) to increase rate limits from 60 req/h to 5,000 req/h per token with automatic quota rotation.

## `onlyWithEmail` (type: `boolean`):

When enabled (default), only outputs developer profiles for which a real, non-noreply, non-disposable email verified via DNS MX records was found.

## `locationFilter` (type: `string`):

Optional location filter (e.g. "France", "Germany", "Paris", "Remote"). Supports comma-separated values and automatic city-to-country matching (e.g. "France" matches "Paris, France", "Lyon", etc.).

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

Maximum number of developer profiles processed in parallel (keeps memory strictly below 256 MB).

## Actor input object example

```json
{
  "targets": [
    "langchain-ai/langchain",
    "rust-lang/rust"
  ],
  "targetMode": "contributors",
  "maxUsersPerTarget": 50,
  "githubTokens": [],
  "onlyWithEmail": true,
  "locationFilter": "",
  "maxConcurrency": 5
}
```

# Actor output Schema

## `leads` (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 = {
    "targets": [
        "langchain-ai/langchain",
        "rust-lang/rust"
    ],
    "githubTokens": [],
    "locationFilter": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("vesper_studio/github-developer-email-extractor").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 = {
    "targets": [
        "langchain-ai/langchain",
        "rust-lang/rust",
    ],
    "githubTokens": [],
    "locationFilter": "",
}

# Run the Actor and wait for it to finish
run = client.actor("vesper_studio/github-developer-email-extractor").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 '{
  "targets": [
    "langchain-ai/langchain",
    "rust-lang/rust"
  ],
  "githubTokens": [],
  "locationFilter": ""
}' |
apify call vesper_studio/github-developer-email-extractor --silent --output-dataset

```

## MCP server setup

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

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/7pOuzPTP54MyZiOY1/builds/7EgayCKnS0iDAZ0OM/openapi.json
