Pre-Black Friday: 20% off, for as long as you stayEARLYBFon Solo and AgencyEnds Nov 28Start free

How-to guide

How to Find an Email From a GitHub Profile (2026)

Start with a GitHub username and end with a work email you can check before you send. Manual way first, then the API, then the bulk way.

Get your free API key →Free to start. No credit card. 1,000 records to spend whenever you like.

TL;DR

  • A GitHub profile gives you a name, a company and sometimes a public email. When the email is missing, take the name and company to LeadOcean and ask for the checked work email. Two calls.
  • It takes about 15 minutes the first time, mostly getting a key. Each person costs about 2 records of your 1,000 free ones: 1 for the search row, 1 for the email.
  • For a list, loop the same two calls over a file of names. The free plan allows 5 requests a second. Agency allows 200.

Prerequisites

  • A LeadOcean account and key from app.leadocean.io. The free plan has no card and 1,000 records, one-off. Free keys get both the search and enrich scopes.
  • The key in your shell as $LEADOCEAN_API_KEY.
  • curl, jq and git. For the bulk step, a file with one name,company pair per line.
bash
export LEADOCEAN_API_KEY="paste-your-key-here"

One rule first. GitHub's acceptable use policy bars using information from the service for spamming, including unsolicited email to users (GitHub policy, September 2026). Write to people you have a real reason to write to, and keep it short and relevant.

Step 1: Read the public profile

Start with the profile itself. GitHub's users endpoint returns the public fields, including name, company and email. It needs no key for a few calls (GitHub REST docs, September 2026).

bash
curl -s https://api.github.com/users/octocat | jq '{login, name, company, email, blog}'

If email holds an address, you are done with the manual route. Most profiles show null, because the owner chose not to publish one. That is their choice, so treat a blank field as a no.

Step 2: Check the commit log

Commits carry an author email. Clone one of the person's public repos and read it from the log.

bash
git clone --quiet https://github.com/octocat/Hello-World.git
cd Hello-World
git log --format='%an <%ae>' | sort | uniq -c | sort -rn | head

Many people hide this address. GitHub lets an account keep its email private and author web commits with a no-reply address instead (GitHub docs, September 2026). Skip anything with noreply in it. It forwards nowhere useful.

A commit address can also be old. It may point to a former employer or a personal inbox. Do not send to it without a second source.

Step 3: Find the person in LeadOcean

You now have a name and, usually, a company. Search on both. The body is flat JSON and every filter is an array. Each person returned costs 1 record, so keep limit small.

bash
curl -s -X POST "https://api.leadocean.io/v1/people/search" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "q": "Jane Doe",
    "companyName": ["Acme"],
    "limit": 3
  }' | jq -c '.data[] | {person_id: .meta.source_ids.person_id}'

Read the rows before you pick one. Check the title and company against the GitHub profile. If the profile lists a company website, filter on domain instead of companyName: a domain is an exact key, a name is not. If the name is common, add a title filter such as ["engineer"] or a country.

To size a role before you spend anything, send count=true as a query parameter with limit 1. On 21 October 2026, the free leadocean_count_leads MCP tool counted 26,970 mailable people with the title "Staff Engineer" in the US. Mailable here means a verified, catch-all valid or catch-all address, the tool's default.

Step 4: Get the work email

Send the person_id to the work email endpoint. It returns one address at the person's current employer, or data: null.

bash
curl -s -G "https://api.leadocean.io/v2/people/email/work" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  --data-urlencode "person_id=PERSON_ID_FROM_STEP_3" | jq

Only checked addresses come back: verified, catch_all_valid or catch_all. So null means "none that qualify", not "this person has no email". The call costs 1 record, found or not.

Do not guess jane@acme.com from a pattern. Guessed addresses bounce. LeadOcean gives no refund or credit-back for bounced emails, so read the status before you send.

Step 5: Run it over a list

Put one name,company pair per line in people.csv. Loop both calls and write one JSON line per person. The loop takes the first search row, so read a few results before you trust it.

bash
while IFS=, read -r name company; do
  id=$(curl -s -X POST "https://api.leadocean.io/v1/people/search" \
    -H "x-api-key: $LEADOCEAN_API_KEY" \
    -H "content-type: application/json" \
    -d "{\"q\": \"$name\", \"companyName\": [\"$company\"], \"limit\": 1}" \
    | jq -r '.data[0].meta.source_ids.person_id // empty')
  [ -z "$id" ] && continue
  curl -s -G "https://api.leadocean.io/v2/people/email/work" \
    -H "x-api-key: $LEADOCEAN_API_KEY" \
    --data-urlencode "person_id=$id" \
  | jq -c --arg name "$name" '{name: $name, email: .data.email, status: .data.status}'
  sleep 0.25
done < people.csv > results.jsonl

The sleep keeps you under 5 requests a second on the free plan. Records add up fast: 500 people spend up to 1,000. Run 20 first and read the hit rate.

When you have an audience and no list of names, skip the loop. POST /v1/exports takes search filters and writes a CSV, up to 50,000 rows a request and 500,000 a day. Bulk CSV export is not on the free plan. Solo at $97 a month includes it (pricing, October 2026).

Then filter on status before you send. Keep verified and catch_all_valid. Treat catch_all as a risk you size, not a green light.

bash
jq -c 'select(.email != null and (.status == "verified" or .status == "catch_all_valid"))' \
  results.jsonl > sendable.jsonl
wc -l sendable.jsonl

What you get

Both responses below are the response shape from the API reference. Every value is a placeholder, not a real record.

A search row carries the id you need at meta.source_ids.person_id. The profile fields sit under profile_data and are left out here.

json
{
  "success": true,
  "data": [
    {
      "profile_data": {},
      "meta": { "source_ids": { "person_id": "1234567890" } }
    }
  ],
  "meta": { "count": 1, "nextCursor": null }
}

The work email call returns success and data, with no meta object.

json
{
  "success": true,
  "data": {
    "email": "jane.doe@acme.com",
    "status": "verified",
    "verified_batch_date": "2026-09-20"
  }
}

Troubleshooting

ErrorCauseFix
401Missing, wrong or revoked keyRe-copy the key from app.leadocean.io and re-export $LEADOCEAN_API_KEY. The header is x-api-key.
429Above the plan's rate limit: 5 a second on Free, 200 on AgencyWait for Retry-After, add a sleep, or move to a plan with a higher limit.
402The free 1,000 records are spentCheck GET /v1/account, then see the pricing page.
Empty search resultsA filter value that does not match, or a company name written differentlyDrop companyName and search on q alone, then check enum values with leadocean_list_enum_values.
data: null on the work email callNo checked address at the current employerAccept the miss, or enrich by linkedin_url if you have it.
Export refusedMore than 50,000 rows a request or 500,000 a day, or a Free planSplit the export, or move to a plan with bulk CSV.

FAQ

Can I get an email from a GitHub username alone?

Only if the profile shows one or a commit exposes one. Many accounts publish neither. Take the name and company to a data source instead.

Is a commit email safe to use?

Not by itself. It can be old, personal or a no-reply address. Use it as a lead, and confirm with a checked work address.

How many records does one lookup cost?

About 2: one search row and one email call. A 404 on enrich costs nothing. The work email call costs 1 record even when it finds nothing.

Is it allowed to email people I find on GitHub?

GitHub's policy bars using its data for spam or unsolicited bulk email. Send relevant, individual messages and follow the laws that apply to you.

Where do I find people by role instead?

Turn a GitHub username into a checked work email

Free to start. No credit card. 1,000 records to spend whenever you like.

Get your free API key →