Block free email domains on B2B forms: the 4,768-domain list and a free API

Block free email domains on B2B forms: the 4,768-domain list and a free API
Unif Cookbooks team
Unif Cookbooks team

What the 4,768-domain free email list HubSpot forms block contains, where blocking Gmail signups misfires, and a free API to apply the rule.

In short: HubSpot forms can reject free email addresses with one checkbox, "Block free email providers", backed by a published list of 4,768 domains. We turned that same list into a free API (GET /email/check, POST /email/check/batch, 0 credits per call), an in-browser checker, and an open-source npm package, so the rule your forms apply can also run in signup code, CRM cleanup jobs, and AI agents. The list is good at the obvious cases and wrong in predictable ways; know both before you block anyone.

B2B teams block free email domains for one reason: a demo request from jane@northwind.io tells you which company is asking, and one from jane1987@gmail.com does not. HubSpot ships this as a forms setting and documents the list behind it, with a CSV you can download.

The setting only covers HubSpot forms. Your own signup flow, the lead list a partner sent over, and the CRM export your agent is enriching never pass through it. That gap is what this post closes.

What is on the list

We loaded the CSV (snapshot of October 10, 2026) and grouped what is in it. UnifAPI is not affiliated with HubSpot; the list is theirs, the grouping is ours.

GroupExamplesWhat to know
Global webmailgmail.com, googlemail.com, yahoo.com, outlook.com, hotmail.com, icloud.com, aol.comThe cases everyone expects.
Country variants51 yahoo.*, 33 outlook.*, 24 live.*, 22 hotmail.* domainsMatching on yahoo.com alone misses yahoo.co.uk and yahoo.co.jp.
Regional providersweb.de, gmx.de, t-online.de, orange.fr, libero.it, mail.ru, yandex.ru, qq.com, 163.com, naver.comMost of the real non-US volume.
ISP mailboxescomcast.net, att.net, verizon.net, btinternet.com, shaw.ca, bigpond.comPersonal, but some small businesses still run on them.
Privacy-focusedprotonmail.com, duck.com, fastmail.com, hushmail.com, posteo.deOften used by technical buyers on purpose.
Legacy vanity domains1,264 mail2*.com domains, plus from*.com and city-of-* portalsA quarter of the list, almost no live traffic.
Some disposable inboxesmailinator.com, yopmail.com, maildrop.ccPartial coverage only.

The size of the list is mostly history. The mail2*.com vanity domains alone are 1,264 of the 4,768 entries. They cost nothing to keep, but "4,768 domains" overstates how much of today's personal email it covers: the first two rows carry most of it.

Where blocking free domains misfires

Blocking is a blunt instrument. Before you turn it on, check these five failure modes against your own funnel:

  1. Real buyers on personal addresses. Founders, consultants, and people evaluating on a weekend use Gmail. A hard block turns them away at the moment of highest intent.
  2. ISP and privacy mailboxes. A three-person agency on comcast.net and a security engineer on protonmail.com are both blocked. Neither is a consumer.
  3. Newer providers slip through. proton.me, pm.me, tuta.com, and hey.com are not on the list. Neither is guerrillamail.com, so it is not a disposable-email list either.
  4. "Business" is not "deliverable". A domain that is not on the list can still be a typo, a parked domain, or a mailbox that bounces. Nothing here checks MX records or talks to a mail server.
  5. Subdomains are not matched. The rule is exact: berlin.de is listed, senate.berlin.de is not treated as free. That is the right default for company and government subdomains, but it means mail.yahoo.com-style aliases need their own entries.

The pattern that works for most B2B teams is route, don't block: let free-domain signups through to a self-serve or nurture path, ask them for a company name, and reserve sales follow-up for business domains. Role mailboxes (info@, sales@, support@) deserve their own route too: they are business addresses, but nobody in particular reads them.

Four ways to apply the same rule

WhereUseNotes
A form or signup handlerGET /email/checkOne address, returns a verdict
A lead list or CRM exportPOST /email/check/batchUp to 1,000 addresses per call, in order
A company domain columnGET /email/domains/{domain}Accepts a domain, address, or URL
Your own code or warehouseGET /email/free-domains, or the npm packageSync the list and run it offline

All four endpoints are free: they return the standard billing block with credits_charged: 0, and a workspace with a zero balance can call them. They run without network lookups, so they answer as fast as the gateway does.

One address

curl -s "https://api.unifapi.com/email/check?email=Jane.Doe@Gmail.com" \
  -H "Authorization: Bearer $UNIFAPI_API_KEY"
{
  "request_id": "…",
  "data": {
    "input": "Jane.Doe@Gmail.com",
    "email": "jane.doe@gmail.com",
    "local_part": "jane.doe",
    "domain": "gmail.com",
    "is_valid_syntax": true,
    "is_free_provider": true,
    "is_role_account": false,
    "verdict": "free",
    "invalid_reason": null
  },
  "billing": {
    "credits_charged": 0,
    "records_charged": 0,
    "balance_remaining": 0,
    "truncated_due_to_balance": false
  }
}

verdict is the field to branch on: business, free, or invalid. When it is invalid, invalid_reason says why (missing_at_sign, invalid_local_part, invalid_domain, too_long), which is enough to show a useful form error instead of "invalid email".

A lead list

const res = await fetch("https://api.unifapi.com/email/check/batch", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.UNIFAPI_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ emails: leads.map((lead) => lead.email) }),
});
const { data } = await res.json();

const business = leads.filter((_, i) => data.results[i].verdict === "business");
console.log(data.summary); // { total, business, free, invalid, role_accounts }

Results come back in input order, duplicates included, so you can zip them with your rows without a lookup table.

Offline, in your own code

The list and the classifier are also an open-source, zero-dependency package, @unifapi/email-filter:

import { checkEmail } from "@unifapi/email-filter";

if (checkEmail(form.email).verdict === "free") {
  return "Please use your work email.";
}

It runs in Node, edge runtimes, and the browser, and ships the raw list as JSON and plain text for other languages. Pin a version and refresh it when the list changes; the snapshot date is exported as FREE_EMAIL_DOMAINS_SNAPSHOT_DATE.

Do it without code

The free email domain checker runs the same package in your browser. Paste up to 10,000 addresses or domains — a CSV column, a mail header like Jane Doe <jane@acme.io>, or a plain list — and it splits them into business, free provider, and invalid, flags role mailboxes, removes duplicates, and exports a CSV. Nothing you paste is uploaded.

Turn it into an agent prompt

With UnifAPI connected over MCP, the agent can run the batch endpoint itself:

Here is our webinar sign-up export. Classify every email with the UnifAPI email check, then return three lists: business addresses grouped by domain, free-provider addresses with the person's name so we can ask for a company, and invalid rows with the reason. Flag role mailboxes separately and do not send anything.

The check costs nothing, so the agent can run it on every list before it spends credits on enrichment. Pair it with the LinkedIn company analyzer to size up the companies behind the business domains.

Free email domain checker - paste a list and split business from personal emails, free.

Email filter API - the four free endpoints, with parameters and response schemas.

@unifapi/email-filter on GitHub - the open-source package and the raw list.