Check any email or domain: disposable, personal, or a real company.
pingutil is a free lookup API. Send it an address like jane@acme.io and it tells you what kind of domain that is and, for companies, who they are. Teams use it to keep throwaway accounts out of signups, separate work emails from Gmail, and route leads.
- About 9,900 disposable domains, re-synced every Monday
- Free API key, 60 requests a minute, no credit card
- Company profiles for any business domain, cached at the edge
curl https://pingutil.com/v1/lookup \
-H "Authorization: Bearer $PINGUTIL_KEY" \
-H "Content-Type: application/json" \
-d '{"input":"x7kq2m9z@mailinator.com"}'{
"domain": "mailinator.com",
"category": "disposable",
"email_signals": {
"is_randomized": true,
"is_role_based": false
},
"verdict": {
"is_spam": true,
"reason": "disposable_domain"
}
}Try a lookup
No key needed here. The demo allows 10 lookups a minute per IP. A new company domain can take a few seconds the first time while its profile is built.
What people build with it
Most integrations are a few lines around one call to /v1/lookup.
Keep throwaway accounts out of signup
Reject temporary inboxes before they eat a free trial or skew your activation numbers. Gibberish addresses on unlisted domains get caught by the email signals.
if (res.verdict.is_spam) {
return error('Please use a permanent email address.');
}Detecting disposable emails →Send work emails to sales, everyone else to self-serve
A company domain is a different lead than a Gmail address. Branch on the category instead of asking for "company name" in another form field.
const route = res.category === 'company' ? 'sales' : 'self_serve';Business vs personal email →
Fill in the company on new leads
Industry, headquarters, employee range and funding stage come back with the lookup, so your CRM record is useful before anyone opens it.
const { company } = res;
crm.update(lead.id, {
industry: company?.industry,
size: company?.employee_size_estimate,
});Enriching leads from a domain →Offer the team plan to the right people
When a second person signs up from the same company domain, that is your cue to suggest a shared workspace.
if (res.category === 'company' &&
await countUsers(res.domain) > 1) {
suggestTeamPlan(user);
}Spotting teammates →The seven categories
Every lookup returns exactly one. Lists are checked first (disposable, then free, then ISP), then TLD rules, and anything left over is treated as a company.
| Category | What it means | Examples |
|---|---|---|
| company | Anything that is not on a list or matched by a TLD rule. Gets a company profile. | stripe.com, shopify.com, figma.com |
| free | Personal webmail from providers like Google, Microsoft, Yahoo and Proton. | gmail.com, outlook.com, proton.me |
| disposable | Temporary inboxes. Matched against the community list, re-synced weekly. | mailinator.com, yopmail.com, temp-mail.org |
| isp | Addresses bundled with home internet service. Personal, not business. | comcast.net, btinternet.com, orange.fr |
| educational | Matched by TLD: .edu, .edu.<cc>, .ac.<cc>, .sch.<cc>. Subdomains count. | harvard.edu, ox.ac.uk, iitb.ac.in |
| government | Matched by TLD: .gov, .mil, .gov.<cc>, .gouv.<cc>, .gob.<cc>, .govt.<cc>. | nasa.gov, hmrc.gov.uk, economie.gouv.fr |
| unknown | Input that could not be parsed as an email or a registrable domain. | localhost, foo.invalid |
Getting started
- 1
Get a key
Sign in with your email (no password) and create a key on the dashboard. It is shown once, so store it as a secret.
- 2
Call /v1/lookup
POST an email or a domain as "input". Add skip_enrichment: true when you only need the category and spam verdict.
- 3
Branch on the result
Block on verdict.is_spam, review low_trust, and use category and company to route the user or lead.
const res = await fetch('https://pingutil.com/v1/lookup', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PINGUTIL_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ input: 'jane@stripe.com' }),
}).then((r) => r.json());
res.category; // "company"
res.company?.industry; // e.g. "Financial Technology"
res.verdict.is_spam; // falsePython, Go and curl versions are in the quickstart. Prefer clicking around? The API explorer runs requests from your browser.
Questions
What does pingutil do?
You send an email address or a domain. pingutil tells you whether it belongs to a company, a free webmail provider, a disposable (temporary) inbox service, a school, a government body or a consumer ISP. For company domains it also returns a profile: name, industry, headquarters, employee range, funding stage and links.
Is it really free?
Yes. pingutil is a community project with no paid tier. Sign in with your email to get an API key; each key allows 60 requests per minute. The demo on this page needs no key and allows 10 lookups per minute per IP.
How does it detect disposable email addresses?
It checks the domain against the open disposable-email-domains list on GitHub (about 9,900 domains), which we re-sync every Monday. It also scores the part before the @ for machine-generated patterns like "ccjxx90sze", so throwaway accounts on unlisted domains still get flagged.
Where does the company data come from?
pingutil fetches the company's own homepage and has an open AI model (gpt-oss-20b on Cloudflare Workers AI) fill a fixed schema from it. Gemini with Google Search grounding is also supported. The output is validated before it is cached, and every profile carries a confidence score. It is good for routing and segmentation; verify it before you rely on it for anything legal or financial.
How fast is a lookup?
Category checks and email signals are list and rule lookups, so they return in milliseconds. A company profile that is already cached is just as fast. The first lookup for a new company domain calls the AI model and can take several seconds; pass skip_enrichment: true when you only need the category.
Do you store the email addresses I look up?
No. Results are cached and logged per domain (for example stripe.com). The part before the @ is only used in memory to compute email signals and is not written to the database. If you do not need those signals, send just the domain.
Does pingutil check whether a mailbox exists?
No. It does not connect to mail servers (SMTP verification). With check_dns: true it tells you whether the domain exists, has mail (MX) records and has a website, which catches typos and dead domains without touching the recipient.