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

How-to guide

How to Handle Catch-All Domains (Split, Count and Send)

A catch-all domain says yes to every address. Here is how to size the slice, split it from verified rows and send it without hurting your domain.

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

TL;DR

  • A catch-all domain accepts mail for any name, so no probe can prove one mailbox exists. Treat those rows as their own bucket, not as verified and not as invalid.
  • Sizing the split takes about 20 minutes and spends 0 LeadOcean records: counts are free. A 100-row test batch spends 100.
  • Send verified rows first, catch-all rows in small batches, and read emailStatus on every row before it reaches a sequencer.

Prerequisites

  • A LeadOcean API key in $LEADOCEAN_API_KEY. The Free plan (1,000 records for life, no card) is enough for this guide. Pricing.
  • curl and jq.
  • A sequencer or CSV workflow where you can tag rows by a status column.

Step 1: Know what the server is telling you

A catch-all server answers 250 to RCPT TO for every name, real or made up. That is why a verifier cannot confirm the mailbox (RFC 5321, September 2026).

text
RCPT TO:<jane.doe@acme.com>      250 OK   (maybe real)
RCPT TO:<zzq81x@acme.com>        250 OK   (definitely fake)

Same answer for both, so the result is "cannot confirm". Domains behind a secure email gateway can behave this way, because the gateway accepts first and filters later. See what is a catch-all email for the definition.

Step 2: Learn the status values

LeadOcean stores the verdict in emailStatus. There are 13 values. Four matter here.

bash
curl -s "https://api.leadocean.io/v1/enums/email_status" \
  -H "x-api-key: $LEADOCEAN_API_KEY" | jq '.'
ValueRead it as
verifiedMailbox confirmed. Send.
catch_all_validCatch-all domain, but the mailbox was confirmed through the provider's identity check (Microsoft 365 managed tenants and Google Workspace only). Send.
catch_allCatch-all domain, cannot confirm. Small batches.
risky, unknownDo not send by default.

By default a count treats verified, catch_all_valid and catch_all as mailable. Narrow it yourself when you want the buckets apart. As a filter, catch_all also matches catch_all_valid, so filter on catch_all_valid alone for the confirmed set (API reference, October 2026).

Step 3: Size each bucket for free

Counting spends no records. Run one count per bucket with the same audience filters. The MCP tool leadocean_count_leads does this from Claude.

text
leadocean_count_leads
  jobLevel: ["VP"]
  jobFunction: ["Sales & Business Development"]
  country: ["CA"]
  emailStatus: ["verified"]
  facets: false

Change only emailStatus for the other two runs. Over REST, send count=true as a query parameter with limit 1; meta.total is capped at 100,000.

bash
curl -s -X POST "https://api.leadocean.io/v1/people/search?count=true" \
  -H "x-api-key: $LEADOCEAN_API_KEY" -H "content-type: application/json" \
  -d '{"jobLevel":["VP"],"jobFunction":["Sales & Business Development"],
       "country":["CA"],"emailStatus":["catch_all_valid","catch_all"],"limit":1}' \
  | jq '.meta'

Step 4: Pull the buckets as separate lists

Run two real searches, one per bucket, so the status never gets blended. The first file holds the send-first bucket, the second the catch-all test batch. Filters are arrays, limit runs 1 to 100, and you page with cursor.

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 '{"jobLevel":["VP"],"jobFunction":["Sales & Business Development"],"country":["CA"],"emailStatus":["verified"],"limit":100}' \
  > verified.json

curl -s -X POST 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":["catch_all"],"limit":100}' \
  > catchall.json

For a full list, use POST /v1/exports (up to 50,000 rows a request, 500,000 a day; bulk CSV is not on Free). Request the email_1_status column so the status travels with each row.

Step 5: Check a domain yourself

You can also test a single domain by hand. Send a probe to a name that cannot exist, such as a random string at the domain, using your own mail server. If the server accepts it, the domain is catch-all. Do this sparingly and only on domains you plan to mail, because repeated probes can get your IP flagged. The status field in the data saves you this work for most rows.

text
RCPT TO:<q7x2k9wz@acme.com>   250 OK   -> catch-all
RCPT TO:<q7x2k9wz@acme.com>   550      -> normal domain, bad name rejected

Step 6: Send in a safe order

Verified first, catch-all second, in batches you can measure.

text
Day 1   bucket A, normal pace
Day 3   bucket B, 100 rows, separate sender or sequence tag
Day 6   read bounces on B
          under your own bounce limit -> send the next 500
          over it                     -> stop, keep B for another channel

Pick the bounce limit before you start. We publish no universal number, because it depends on your domain's history. LeadOcean gives no refund or credit-back for bounced emails, so read emailStatus before sending. See can I send this email: valid, risky and catch-all and the accept-all verification guide.

Bounces from the catch-all bucket should not damage the reputation you built on verified rows. Use a different mailbox or sequence for bucket B so the numbers stay readable. If a bounce spike hits, you pause one sequence, not your whole outbound.

Keep copy for bucket B plain too: no attachments, one link at most, a short first line. Gateways filter on content after they accept the message, so a heavy email is more likely to be dropped silently. Silent drops show up as low replies, not bounces, so watch both.

Step 7: Tag rows before they reach the sequencer

Add a column so the sequencer can split by bucket.

bash
jq -r '.data[] | [.profile_data.profile_full_name, .contact_data.email_status] | @csv' catchall.json

Search rows carry the status flag, never the address. Enrich a row with reveal_email to get the address itself. Anything not verified, catch_all_valid or catch_all stays out of the send list.

What you get

Counts from the free leadocean_count_leads tool, run 2026-10-21. Audience: VP, Sales & Business Development, Canada. Each count filters by emailStatus only, so it is a count by status, not a mailable total.

emailStatus filterPeopleDistinct companies
verified1,8541,392
catch_all_valid, catch_all3,7202,567
risky, unknown1,4601,147

On this audience the catch-all bucket is larger than the verified one. Drop it and you lose most of the list.

Troubleshooting

ErrorCauseFix
401Missing or bad x-api-keyCheck $LEADOCEAN_API_KEY is exported and has no stray spaces.
429Above the plan's rate limit (5 a second on Free, 200 on Agency)Honor Retry-After, slow the loop or move up a plan.
402Records spent (Free is 1,000 for life)Counts still work. Upgrade to pull more.
Empty resultsEnum value is not an exact stringList values with leadocean_list_enum_values or GET /v1/enums.
meta.total stops at 100,000Count capAdd filters until the total is under the cap.
Export refusedOver 50,000 rows a request or 500,000 a daySplit by country or title and run several exports.

FAQ

Should I send to catch-all addresses at all?

Yes, in a separate bucket and small batches. Skipping them can cut most of a list: in the counts above, the catch-all bucket is about twice the verified one. Sending them blind risks your domain.

Does a verifier "resolve" a catch-all?

Not by SMTP alone, because the server gives the same answer to every name. Any resolution comes from other signals, so read the status label and test in batches.

Is catch_all_valid safe like verified?

Close. LeadOcean confirmed the mailbox exists through the provider's identity check, so it is safe to send and ranks just below verified. A plain catch_all was never confirmed.

How many records does this guide spend?

Counts spend 0. The two 100-row test searches spend about 200 records at most.

Where can I read more?

Start with what is a catch-all email. For the send rules, see can I send this email. More guides are in the blog. Plans are on pricing.

Size your catch-all slice before you send

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

Get your free API key →