You cannot verify a single address on a catch-all domain. The server says yes to every name, so a probe proves nothing. What you can do is label the risk, size it before you spend, and send in order: verified first, catch-all last.
TL;DR
- Catch-all domains accept mail for any name, so SMTP probes return "valid" for fake addresses. Treat the result as a risk band, not a yes or no.
- Time: about 20 minutes. Sizing costs 0 records. A 25-person test page costs 25.
- LeadOcean labels each email (
verified,catch_all_valid,catch_all,risky, and more) so you can filter by band in the query.
Prerequisites
- A LeadOcean API key, exported as
$LEADOCEAN_API_KEY. The Free plan gives 1,000 records for life, no card, 5 requests a second. curlandjq.- A target audience in mind (title, country, function).
Step 1: Know what you are dealing with
Send a probe to a made-up name on the domain. If it is accepted, the domain is accept-all.
dig +short MX acme.com
nc -v mx.acme.com 25 # run on a domain you control or may test
RCPT TO:<zz-not-a-real-name-91827@acme.com>
250 means accept-all. 550 means the server rejects unknown users.A 250 on a fake name means any real name will also get a 250. Background: what is a catch-all email and catch-all emails explained.
Do not do this per lead. It is slow, many servers rate-limit or greylist probes, and it still cannot tell you if Jane is real.
Some accept-all domains are not truly open. Some servers accept the message and bounce it later, which a probe cannot see. Others silently drop it. In both cases the probe says "valid" and the mail never lands, so a clean probe on an accept-all domain is weak evidence.
Step 2: Pull the status with the email, not after it
LeadOcean stores an emailStatus on each person. These are the values that matter:
| Status | Meaning for sending |
|---|---|
verified | Mailbox confirmed. Send. |
catch_all_valid | Accept-all domain, but LeadOcean confirmed the mailbox through the provider's identity check (Microsoft 365 managed tenants and Google Workspace only). Send second. |
catch_all | Accept-all domain, no signal. Send last, in small batches. |
risky, unknown, untested, role, derived | Skip, or test first. |
invalid, disposable, spam_trap, abuse | Exclude. |
Filter values are exact strings. Check them first.
curl -s "https://api.leadocean.io/v1/enums/email_status" -H "x-api-key: $LEADOCEAN_API_KEY" | jq '.'In an AI client with the LeadOcean MCP server connected, ask for leadocean_list_enum_values with name: "email_status" instead. Both are free.
One trap: as a filter, catch_all also matches catch_all_valid. Filter on catch_all_valid alone for the confirmed set (API reference, October 2026).
Step 3: Size each band for free
Count the audience once per band. A count spends no records. Filters are arrays, and the count is a query parameter on search with limit=1:
for s in verified catch_all_valid catch_all; do
echo -n "$s: "
curl -s "https://api.leadocean.io/v1/people/search?count=true&limit=1" \
-H "x-api-key: $LEADOCEAN_API_KEY" -H "Content-Type: application/json" \
-d "{\"jobLevel\":[\"VP\"],\"jobFunction\":[\"Sales & Business Development\"],\"country\":[\"CA\"],\"emailStatus\":[\"$s\"]}" \
| jq -r '.meta.total'
doneThe same count through MCP is leadocean_count_leads with the same filters. It also returns distinctCompanies, which tells you how many domains the band spans.
Step 4: Pull and send in order
Pull the verified band first, with a small page to test.
curl -s "https://api.leadocean.io/v1/people/search" \
-H "x-api-key: $LEADOCEAN_API_KEY" -H "Content-Type: application/json" \
-d '{
"jobLevel": ["VP"],
"jobFunction": ["Sales & Business Development"],
"country": ["CA"],
"emailStatus": ["verified"],
"limit": 25
}' | jq '.meta'Then follow a simple send plan:
- Send the
verifiedband at normal volume. - Send
catch_all_validnext, at about half your normal daily volume. - Send
catch_alllast, in batches of 50 to 100, and watch bounces for two days before the next batch. - Suppress every hard bounce. LeadOcean does not refund records for bounced emails, so read the status before you send.
Pull more with the cursor from the previous page. One search pages to 10,000 rows. Narrow the filters if you hit meta.depthCapped. For files over a few thousand rows, use POST /v1/exports (up to 50,000 rows a request, 500,000 a day, not on Free). The CSV carries email_1_address and email_1_status, so you can split bands in a spreadsheet.
Step 5: Do the same from an AI client
With the LeadOcean MCP server connected (https://api.leadocean.io/mcp, OAuth sign-in, no key pasted), you can run the sizing in plain language. Paste this prompt:
Using leadocean_count_leads, count VPs in Sales & Business Development in
Canada three times: emailStatus verified, catch_all_valid, catch_all.
Pass facets=false. Report total and distinctCompanies for each, and tell
me which band is largest. Do not call any tool that spends records.The count tool is free, so the model can try several filter sets without touching your 1,000 Free records. Ask it to spend records only after you pick a band.
What you get
Counts from leadocean_count_leads, run 2026-10-21. Filters: jobLevel VP, jobFunction Sales & Business Development, country CA. One emailStatus per row.
| emailStatus | People | Distinct companies |
|---|---|---|
verified | 1,854 | 1,392 |
catch_all_valid | 0 | 0 |
catch_all | 3,720 | 2,567 |
On this slice, the catch-all band is about twice the verified band. None of it is labelled catch_all_valid.
Filter to verified only and you drop roughly two thirds of the reachable list. Send to all of it blind and about two in three emails go to domains that cannot confirm the mailbox. Use bands.
These are counts by email status, one status each, not mailable totals. Your numbers will differ with other filters.
Export column names, from the API reference:
email_1_address,email_1_status,email_2_address,email_2_status
jane.doe@acme.com,verified,,This is the export header from the API reference, with a placeholder row.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key | Re-copy the key from app.leadocean.io and export $LEADOCEAN_API_KEY |
| 429 | Above your plan's rate limit (5 a second on Free, 200 on Agency) | Honour Retry-After, or move to a plan with a higher limit |
| 402 | Free records spent | Move to Solo or Agency. The Free 1,000 records do not refill |
200 with empty data and meta.total 0 | Wrong enum string, such as Catch-All instead of catch_all | Check strings with GET /v1/enums or leadocean_list_enum_values |
| Count looks like a count, but data is empty | You sent count=true, so data is empty by design | Drop count=true to get rows |
| Export refused | Over 50,000 rows a request, 500,000 a day, or you are on Free | Split the export by band or country; bulk CSV needs a paid plan |
FAQ
Can any tool verify a catch-all email for certain?
No. A catch-all server accepts every name, so no outside check can prove the mailbox. Tools can only add signals and label the risk. Compare how vendors label it in best catch-all email verifiers.
Should I send to catch-all addresses at all?
Yes, in order and in small batches. On the slice above, skipping them would drop most of the list. Send them last and stop if bounces climb.
What bounce rate should I tolerate?
Set your own threshold with your sender's guidance. Pause the batch when it breaks, then suppress the bounced addresses before the next one.
Does sizing cost records?
No. Counts, enum lookups and filter lookups are free. Records are spent only when a person is returned. See pricing.
Size your catch-all risk before you send
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →