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

How-to guide

How to Find Work Emails in Claude Code (2026)

One command, one browser sign-in, then two prompts. Count for free, search, reveal only the addresses you want.

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

You find work emails in Claude Code by adding the LeadOcean MCP server with one command, then asking Claude to count, search and reveal. Counting is free. Revealing one address costs 1 record.

TL;DR

  • Setup takes about 8 minutes. The two prompts after it take about 2.
  • The run below spends 7 LeadOcean records: 5 people returned by search, 2 reveals. Counting spends 0.
  • Search never returns addresses. Only leadocean_get_lead with reveal_email does, so you pay for an address only when you ask for it.

Prerequisites

  • Claude Code installed. The Claude Code MCP docs, September 2026, cover adding a remote server.
  • A LeadOcean account. Start free: no card, 1,000 records, one-off.
  • For Step 6 only: an API key from your account, exported as $LEADOCEAN_API_KEY. The MCP steps need no key.

Step 1: Add the server

Run one command. Claude Code recommends the HTTP transport for remote servers. The full setup page is Connect LeadOcean to Claude Code.

bash
claude mcp add --transport http leadocean https://api.leadocean.io/mcp
claude mcp list

A fresh server shows ! Needs authentication until you sign in. Do not add a --header "Authorization: ..." flag. The server uses OAuth 2.1, so there is no key to paste.

The command saves to local scope, which is the current project only. Add --scope user to load it in every project.

Step 2: Sign in

Start claude, run /mcp, pick leadocean and choose to authenticate. Your browser opens on LeadOcean. Sign in, approve, and return to the terminal.

The tools appear without a restart. Run /mcp again to see the server connected with 13 tools. Seven of them are free, including leadocean_count_companies for company counts.

Claude Code registers itself as an OAuth client. LeadOcean supports dynamic client registration at https://api.leadocean.io/oauth/register (scope mcp).

Step 3: Decide which tools run without asking

Claude Code asks before it calls a tool unless a permission rule says otherwise. Allow the free tools and keep a prompt on the two that spend records. The permissions docs, September 2026, describe allow and ask rules.

Put this in .claude/settings.json. Tool names are mcp__, the server name, then the tool.

json
{
  "permissions": {
    "allow": [
      "mcp__leadocean__leadocean_count_leads",
      "mcp__leadocean__leadocean_list_filters",
      "mcp__leadocean__leadocean_list_enum_values",
      "mcp__leadocean__leadocean_get_account"
    ],
    "ask": [
      "mcp__leadocean__leadocean_search_leads",
      "mcp__leadocean__leadocean_get_lead"
    ]
  }
}

Now Claude counts as often as it likes and stops to ask before it spends. That is your spend guard for an agent that can loop.

Step 4: Count before you spend

Counting is free, however many times you run it. Ask for a count first.

text
Count VP-level sales leaders in the UK. Count only, do not pull anyone.
Tell me which filters you used and which email statuses the count includes.

Claude calls leadocean_count_leads with jobLevel VP, jobFunction Sales & Business Development and country GB. By default it counts people whose best email is verified, catch_all_valid or catch_all.

Ask for emailStatus: ["verified"] if you want the strict number. If a filter value is rejected, Claude should call leadocean_list_enum_values and use the exact string it returns.

Step 5: Search, then reveal the work email

Now pull a small sample. Search returns profiles and flags, never addresses. Reveal only the rows you want.

text
Search 5 people: jobLevel VP, jobFunction "Sales & Business Development",
country GB, emailType work, emailStatus verified. Then call leadocean_get_lead
with reveal_email true for the first 2 person_ids only. Show email,
email_status and verified_batch_date in a table. Stop after 2 reveals.
Do not call any other tool that spends records.

leadocean_search_leads costs 1 record per person returned, so 5. Each leadocean_get_lead costs 1 record, so 2. A get_lead call that finds nobody costs nothing. The same reveal also returns career history (past roles, education) in resume_data when we hold it, at no extra record.

Claude Code shows each spending call and waits for your yes, because of Step 3. Approve the search, then approve each reveal.

Step 6: Run the same lookup from the shell

For scripts and cron jobs, skip the agent and call the REST API. Take the person_id from a search row (meta.source_ids.person_id). The id below is a placeholder.

bash
curl -s "https://api.leadocean.io/v2/people/email/work?person_id=123456789" \
  -H "x-api-key: $LEADOCEAN_API_KEY"

This returns one current work address or data: null. It costs 1 record per call, including a call that finds nothing. The MCP server and the REST API count against the same account.

What you get

Step 4 is a count. On 2026-10-01, leadocean_count_leads returned two exact totals for VP, Sales & Business Development, United Kingdom:

FilterTotalRecords spent
Default mailable (verified, catch_all_valid, catch_all)3,1460
emailStatus: ["verified"] only7510

Those are mailable counts, not everyone we hold for those filters.

Step 5 returns one revealed person per call. This is the response shape from the API reference, with placeholder values:

json
{
  "success": true,
  "data": {
    "contact_data": {
      "contact_emails": [
        {
          "email": "jane.doe@acme.com",
          "type": "work",
          "status": "verified",
          "verified_batch_date": "2026-09-20",
          "priority": 1,
          "score": 0.0
        }
      ],
      "has_email": true,
      "email_status": "verified",
      "email_type": "work"
    }
  }
}

The first block holds the full contact record for one person.

Step 6 returns a smaller body, also a placeholder:

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

verified_batch_date is the run our own verifier tested the address in. A null there means the check was not ours. It does not mean the address is unverified.

Cost of the run, from the per-tool prices in the LeadOcean MCP docs, September 2026: 5 returned by search plus 2 reveals is 7 records. On the free plan that leaves 993 of 1,000. Step 6 adds 1 record per call.

Read the status before you send

There is no refund or credit for bounced emails, so read email_status on every reveal.

  • verified: our verifier sent to the address and it accepted. Safe to send.
  • catch_all_valid: a catch-all domain where we confirmed the mailbox exists. Safe to send.
  • catch_all: the domain accepts everything, so the mailbox is unconfirmed. It can bounce.
  • untested: we hold the address and have not checked it. Verify first.
  • invalid, risky, role, disposable: checked and not safe to send to.

Ask for emailType: ["work"] on purpose. work_other is an address at a former employer, and it is the one most likely to bounce.

When to export instead

Five people from chat is a test. For a list of 5,000, do not loop leadocean_get_lead in a prompt. Use the Exports page in the app at app.leadocean.io, or POST /v1/exports.

Exports take up to 50,000 rows a request and 500,000 a day. Size the list with a free count first, then export with the filters you tested here.

Troubleshooting

ErrorCauseFix
! Needs authentication in claude mcp listThe OAuth window was closed before you approved.Run /mcp, pick leadocean and authenticate again.
401Missing or wrong x-api-key on a REST call (Step 6).Check $LEADOCEAN_API_KEY in the shell. MCP sign-in uses OAuth, not a key.
402Your 1,000 free records are spent. The free plan is one-off.Run leadocean_get_account to check. Move to Solo at $97 a month.
429Above your plan's rate (5 requests a second on Free, 200 on Agency), or a fair-use window was reached.Honour Retry-After and retry. Ask Claude to work in small batches.
Empty resultsA filter value is not in the catalogue, such as an invented job function.Call leadocean_list_enum_values and pass the exact string, for example Sales & Business Development.
data: null from the work endpointNo current-employer address is verified, catch_all_valid or catch_all.It does not mean the person has no email. Try a different person from the search.

FAQ

Do I need an API key to find work emails in Claude Code?

No. The MCP server signs you in with OAuth. You need $LEADOCEAN_API_KEY only for REST calls like Step 6.

Why does search not return the email?

Search returns thin profiles and flags: has_email, email_status and email_type. Addresses come only from leadocean_get_lead with reveal_email. You pay for an address only when you ask for it.

Can Claude Code run up my record count by looping?

Only if you let it. The Step 3 ask rules stop it before every spending call. Add a limit to the prompt too, such as "stop after 2 reveals".

What does it cost to run this at scale?

The free plan holds 1,000 records, one-off. Solo is $97 a month, with a fair-use pace instead of credits. Agency is $497 a month for teams. See pricing.

Where else can I run this flow?

The same server works in VS Code and Claude. The Find Work Email skill packages the steps for one named person.

Find your first verified work email from Claude Code

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

Get your free API key →