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

How-to guide

How to Find a Journalist's Email Address (2026)

Look the address up in a data source, guess from a newsroom pattern only when the lookup is empty, and check the status before anything is sent.

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

You find a journalist's email by looking it up in a data source first and guessing from a newsroom name pattern only when the lookup is empty. A lookup returns an address someone has already tested. A guess is a coin flip you must verify.

Journalist addresses come from four places. A data provider holds a work address it collected and checked. A byline page, press page or masthead lists a shared desk inbox. A newsroom name pattern gives you a guess. A social profile sometimes shows a tips address, which is not the reporter's own.

Only the first is worth building a process around. The other three are fallbacks, and this guide follows that order.

Journalists are a hard audience to email. Newsrooms rotate staff, reporters move between outlets, and inboxes are full of pitches. Size the audience first so you know how many people a relevant pitch can reach.

This guide uses the LeadOcean API. Every step has a request you can run.

TL;DR

  • It takes about 15 minutes to size the audience, find one journalist's address and read its status.
  • The walkthrough spends about 4 records: up to 3 from the search and 1 from the reveal. Counts are free.
  • Pitch only verified, catch_all_valid or catch_all addresses. Anything you guessed gets verified first.

Prerequisites

  • A LeadOcean API key from app.leadocean.io. The free plan has 1,000 records, one-off, and no card.
  • The key in your shell as $LEADOCEAN_API_KEY.
  • curl and jq.
  • A target outlet domain. The examples use dailyacme.com.
bash
export LEADOCEAN_API_KEY="paste-your-key-here"

Step 1: Size the journalist audience for free

Count how many journalists you can mail before you spend a record. Send count=true and limit=1 as query parameters. Arrays go comma-separated.

bash
curl -s -G https://api.leadocean.io/v1/people/search \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  --data-urlencode "title=Journalist,Reporter" \
  --data-urlencode "salesRegion=NORAM" \
  --data-urlencode "emailStatus=verified,catch_all_valid,catch_all" \
  --data-urlencode "count=true" \
  --data-urlencode "limit=1" | jq '.meta | {total, totalIsExact, countOnly}'

salesRegion takes NORAM, LATAM, EMEA or APAC. Swap in country=GB for one market. REST meta.total stops at 100,000, so a big region comes back as a floor with totalIsExact false.

Title values are keywords, so "Reporter" also matches "Senior Reporter" and "Reporter and Producer". Add "jobFunction": ["Writing/Editing"] to narrow to editorial staff.

Step 2: Find the journalist at your target outlet

Search by outlet domain and title. The search returns a thin row with no address in it. The row carries a person_id and flags that say whether we hold an email.

bash
curl -s https://api.leadocean.io/v1/people/search \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": ["dailyacme.com"],
    "title": ["Journalist", "Reporter"],
    "limit": 3
  }' | jq '.data[] | {person_id: .meta.source_ids.person_id, contact_data}'

Each person returned costs 1 record. Keep limit small. Check the title before you pick one, because an "Editor" and a "Reporter" cover different beats.

Many reporters are freelancers with no outlet domain. Search for them by title and country alone, then read the has_email flag on each row.

Step 3: Reveal the address

Send the person_id to enrich with reveal_email set to true. Enrich takes exactly one of linkedin_url, email, phone or person_id. There is no name plus domain lookup, which is why Step 2 comes first.

bash
curl -s https://api.leadocean.io/v1/people/enrich \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"person_id": "PERSON_ID_FROM_STEP_2", "reveal_email": true}' \
  | jq '.data.contact_data | {email_status, contact_emails}'

This costs 1 record. A person we hold nothing for is a 404 and costs nothing. If you only want a deliverable work address, GET /v2/people/email/work with the same person_id returns one current-employer address or null. It costs 1 record per call, even when it finds nothing.

Step 4: Read the status before you send

The status says how far to trust the address. verified was tested. catch_all_valid means we confirmed the mailbox on a domain that accepts everything. catch_all means the domain accepts everything and the mailbox is unproven.

bash
curl -s https://api.leadocean.io/v1/people/enrich \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"person_id": "PERSON_ID_FROM_STEP_2", "reveal_email": true}' \
  | jq -r '.data.contact_data
    | select(.email_status | IN("verified","catch_all_valid","catch_all"))
    | .contact_emails[0].email'

Empty output means the status failed the filter. LeadOcean gives no refund for bounced emails, so this check is your only protection. Treat catch_all as sendable at low volume, not as proof. Our catch-all explainer covers why.

Step 5: Fall back to a newsroom pattern

When the data holds no address, build candidates from the journalist's name and the outlet domain. Most newsrooms use one of four shapes. Pick the one you can confirm from a known address at the same outlet, such as a masthead or corrections inbox.

PatternExample for Jane Doe at Daily Acme
first.lastjane.doe@dailyacme.com
first initial, lastjdoe@dailyacme.com
firstjane@dailyacme.com
lastdoe@dailyacme.com
bash
first="jane"; last="doe"; domain="dailyacme.com"
printf '%s\n' "$first.$last@$domain" "${first:0:1}$last@$domain" "$first@$domain" "$last@$domain"

Large outlets often run on a parent company domain, so the address may not match the site you read. A reporter at a regional paper can sit on a group domain shared by dozens of titles.

Never send to a candidate you have not verified. Run each one through an email verifier you trust first. A domain that accepts all mail cannot confirm any single mailbox, so a guess there stays a guess.

Step 6: Verify and pitch in small batches

Verify before the first send, then start small. A spam complaint from a reporter counts against your sending domain.

Send 20 to 50 pitches first and watch the bounce count. If more than a few bounce, stop and re-check the status filter in Step 4. Keep each message short and tied to the reporter's recent beat, not a generic release.

What you get

Step 1 is free. We ran it with leadocean_count_leads on 2026-10-21, and it spent 0 records. The counts are mailable journalists (verified, catch_all_valid or catch_all, the tool default), not every journalist we hold. The title filter is Journalist or Reporter.

RegionMailable journalistsExact
NORAM31,333Yes
EMEA21,348Yes
APAC8,469Yes
LATAM1,630Yes
Worldwide73,455Yes

Worldwide spans 16,697 distinct employers. Without the email filter the same titles match 432,344 people.

Some records carry a country but no sales region, so the four regions add up to less than the worldwide figure. The REST call in Step 1 shows a count above 100,000 as a floor, because REST meta.total stops there. The MCP tool reports exact totals.

A revealed person comes back in the shape below. This is the response shape from the API reference, with placeholder values.

json
{
  "success": true,
  "data": {
    "profile_data": { "...": "name, title, company" },
    "contact_data": {
      "has_email": true,
      "email_status": "verified",
      "email_type": "work",
      "contact_emails": [
        { "email": "jane.doe@dailyacme.com", "type": "work", "status": "verified" }
      ]
    }
  }
}

Troubleshooting

ErrorCauseFix
401The x-api-key header is missing, or the key is wrong or revoked.Copy a fresh key from the app and reload $LEADOCEAN_API_KEY.
402Your records are spent. On Free the 1,000 are a one-off allowance and do not reset.Check GET /v1/account, or move to Solo ($97 a month) or Agency ($497 a month).
429Over your plan's rate on one key (5 a second on Free, 50 on Solo, 200 on Agency), or a paid plan's fair-use window is reached.Wait the Retry-After seconds and retry. GET /v1/account shows which limit applies.
Empty resultsA filter value is not an exact enum string, such as Writing for Writing/Editing.Call leadocean_list_enum_values for job_function and pass the exact string.
404 on enrichWe hold nothing for that person.Nothing was charged. Try another person_id or fall back to Step 5.
Export refusedOne export is capped at 50,000 rows a request and 500,000 rows a day.Split the job across requests and days, or narrow the filters.

FAQ

Is it legal to email a journalist you do not know?

Rules differ by country, and this guide is not legal advice. Check the law where your recipient sits and keep your pitch relevant to their beat. Ask your own counsel about anything in doubt.

Why does the search not show the email?

Search returns a thin row with flags such as has_email and email_status. The address comes from enrich with reveal_email set, and that call costs 1 record.

How many journalists can I get on the free plan?

You have 1,000 records, one-off. Each journalist costs about 2: 1 from search and 1 from the reveal. That is roughly 500 journalists, minus any 404s that cost nothing.

Can I pull a whole region at once?

Yes, on a paid plan. Bulk CSV export is included on Solo and Agency, not on Free. The Exports page in the app takes the same filters, shows the record price before you start, and gives you a CSV. POST /v1/exports does the same by API, up to 50,000 rows a request.

Should I pitch the reporter or the editor?

Pitch the reporter who covers the beat, and copy no one. Editors get the volume, so they skim. A reporter who wrote on your topic last month reads a short, specific note.

For the same recipe on other titles, see VP of Sales, VP of Marketing and VP of Engineering. More recipes live in the blog hub. Plans are on pricing.

Size your journalist list free, then pull verified addresses

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

Get your free API key →