Domain age as a fraud signal: what a new domain tells you at sign-up

A domain registered days ago is a real risk signal at sign-up, not proof of fraud. How to check domain age with RDAP and when to review instead of block.

  • #fraud
  • #signup
  • #api
  • #policy
Two domains on a timeline: acme.io with a long green bar registered in 2009, and acme-trial.io registered 3 days ago with an amber new_domain review chip. // how old is the domain? acme.io registered 2009 17 years acme-trial.io registered 3 days ago new_domain · review no website · no SPF or DMARC 2009 2014 2019 2024 today

A domain age check asks one question: how long ago was the domain in this email address registered? A company-looking domain registered three days ago is a real risk signal at sign-up, because throwaway domains made for trial abuse and phishing are almost always new. It isn’t proof of anything, since real startups register their domain the week they launch. Use domain age to decide how closely to look at a sign-up, never as the only reason to reject one.

Why new domains show up in abuse

Once you block disposable inboxes and ask for a work email, the cheapest way around the rule is to register a domain. A few dollars buys acme-trial.io, and with a catch-all mailbox every address on it works: jane@, jane2@, ops@. Each one passes a “custom domain” check, receives your confirmation email and starts a fresh trial.

New domains turn up in three patterns:

  • Trial abuse. A domain that looks like a company, registered to farm free trials, credits or seats. It usually has no website or a placeholder, and no SPF or DMARC, because it never sends mail.
  • Phishing and impersonation. Attackers register lookalikes such as acme-billing.io shortly before a campaign, then sign up for products that send email or host pages for them (invites, shared documents, forms) to borrow those products’ reputation.
  • Burn and replace. When one domain lands on a blocklist, the next one gets registered. The domain you haven’t seen before is, by definition, not on any list yet. That’s the gap the disposable email problem describes.

In all three, the domain is days or weeks old when it reaches your form. Established companies rarely sign up from a domain registered last week.

Why it isn’t proof

Plenty of legitimate sign-ups come from new domains too:

  • A startup registers its domain, sets up Google Workspace and signs up for its tools in the same week.
  • A company renames itself, launches a product on its own domain, or spins out a new business.
  • An agency registers a domain for a client project and signs up for the tools that project needs.

The signal also misses abuse in the other direction. A domain bought on the aftermarket keeps its original registration date, so a domain registered in 2012 says nothing about who owns it today. Age describes the domain, not the person signing up.

The same number tells different stories depending on what surrounds it:

Sign-up Domain age Other signals Likely story
jane@acme-trial.io 3 days No website, no SPF or DMARC A throwaway for a free trial
billing@acme-billing.io 9 days Parked page, name borrows an existing brand Impersonation
founder@newco.ai 6 days Google Workspace, DMARC, a real homepage A startup in its first week
jane@acme.io 17 years Google Workspace, DMARC reject An established company

Only the first two deserve a closer look, and neither deserves an automatic rejection.

What RDAP is

RDAP (Registration Data Access Protocol) is the successor to WHOIS. WHOIS returns free text whose layout differs from one registry to the next, which makes it fragile to parse; RDAP answers over HTTPS with structured JSON, including standard events such as registration, expiration and last changed. For generic top-level domains such as .com, RDAP is now the official source of registration data. Many country-code registries run it too, but not all of them do, and some don’t publish a registration date. Registrant names and contacts are usually redacted, so the dates are the part you can use. A trimmed answer:

{
  "objectClassName": "domain",
  "ldhName": "acme-trial.io",
  "events": [
    { "eventAction": "registration", "eventDate": "2026-10-02T09:14:00Z" },
    { "eventAction": "expiration", "eventDate": "2027-10-02T09:14:00Z" }
  ]
}

Domain age is today’s date minus the registration event.

How isBusinessEmail gets domain age

A normal check never waits on a registry. Domain age is part of the deep check, which you request with deep=true in the body or query string of /v1/check:

  • It needs a secret key. Publishable keys never receive deep enrichment.
  • It counts as 5 checks against your daily quota, and an account can run at most 1,000 deep checks a day (rate limits). On a new account with 100 checks a day that’s 20 deep checks; at tier 1, with 1,000 a day, it’s 200.
  • It looks up the registrable domain over RDAP and fetches its homepage. Both requests carry the domain only, never the address (privacy and data).
  • Without deep=true, domain_age_days is null unless the domain was already enriched.

The fields it fills, from response fields and reason codes:

Field or reason Meaning
domain_age_days Days since registration, from RDAP; null when unknown
is_new_domain true when the domain is less than 30 days old
new_domain Reason: registered less than 30 days ago (strong negative)
young_domain Reason: registered less than 180 days ago (negative)
parked_domain Reason: the homepage is a parking or “for sale” page (strong negative)
no_website Reason: no homepage answered within the time limit (negative)
has_website Reason: a homepage answered (weak positive)

A deep check of the throwaway from the table above comes back like this (trimmed):

{
  "domain": "acme-trial.io",
  "category": "unknown",
  "recommendation": "review",
  "is_new_domain": true,
  "domain_age_days": 3,
  "reasons": ["custom_domain", "no_spf_no_dmarc", "new_domain", "no_website"]
}

These reasons adjust the confidence score of a custom domain. A three-day-old domain with no website and no SPF or DMARC falls below the threshold and comes back unknown: review under the default b2b policy, block under strict (categories and policies). A six-day-old domain on Google Workspace with DMARC and a real homepage usually stays business and allow, which is the right answer for the startup in the table. If age matters to your decision, read is_new_domain and domain_age_days yourself instead of relying on recommendation alone.

null doesn’t mean old. If the registry publishes no date or the lookup times out, domain_age_days is null and is_new_domain is false. Treat that as unknown and decide on the other signals.

When a deep check is worth it

Deep checks cost five times as much and are capped, so spend them where a bad account costs real money or time:

  • Trials with expensive resources: AI credits, compute, SMS, seats, data exports. The free trial abuse playbook shows where age fits.
  • Leads going to sales, before someone spends an hour on discovery with a domain registered on Tuesday. Lead scoring by email domain shows how to weigh it in a score.
  • Applications you approve: partner programs, marketplace sellers, anything with payouts or elevated permissions.

Skip them on newsletter forms, content downloads, waitlists and logins, where a wrong guess costs almost nothing.

Two habits keep the budget small:

  1. Check first, then go deep. A deep check on a gmail.com address still counts as 5, and a shared provider has no registration date worth paying for. Run a normal check, and repeat it with deep=true only when the category is business or unknown.
  2. Store the registration date, not the age. Save today’s date minus domain_age_days with the account. The age changes every day; the date doesn’t, so you never need to look it up twice.

Putting it into code

Deep checks wait for the registry and the homepage, so they’re slower than a normal check. Run them at trial start, or in a background job right after the account is created and before the expensive features unlock.

const API = 'https://api.isbusinessemail.com/v1/check';

async function check(email, deep = false) {
  try {
    const res = await fetch(API, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.IBE_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ email, policy: 'b2b', deep }),
      signal: AbortSignal.timeout(deep ? 6000 : 2500),
    });
    return res.ok ? await res.json() : null;
  } catch {
    return null;
  }
}

async function screenTrialSignup(email) {
  let v = await check(email);
  if (!v) return { lane: 'allow', recheck: true }; // fail open
  if (v.recommendation === 'block') return { lane: 'block' };
  if (['business', 'unknown'].includes(v.category)) v = (await check(email, true)) ?? v;

  const codes = v.reasons.map((r) => r.split(':')[0]);
  const tenant = v.workspace.google_workspace.detected || v.workspace.microsoft_365.detected;

  if (codes.includes('parked_domain')) return { lane: 'review', step: 'manual_approval' };
  if (v.is_new_domain && !tenant) return { lane: 'review', step: 'card' };
  if (v.is_new_domain) return { lane: 'allow', watch: true };
  if (v.recommendation === 'review') return { lane: 'review', step: 'confirm_email' };
  return { lane: 'allow' };
}

The same logic as a decision table:

What the check shows Lane What to do
Disposable, blocked or invalid block Age doesn’t matter; the category decides
New domain, parked or no website, no SPF or DMARC review Card on file or manual approval before trial resources
New domain with Google Workspace or Microsoft 365 and a homepage allow Watch usage for the first weeks
young_domain (30 to 180 days), otherwise normal allow A small penalty in a lead score, no extra friction
domain_age_days is null decide on the rest Don’t treat unknown age as old
Older than 180 days, normal setup allow Nothing to do

Review, don’t block

Blocking on age alone turns away founders in their first week, often the customers who would grow with you. A review lane costs a few people a little friction and keeps them:

  • Ask for a card before the expensive part of the trial, not before sign-up.
  • Hold back costly features, such as bulk exports, API credits or invites to many users, until someone approves the account or a few days of normal usage pass.
  • Approve manually on sales-led products. A two-minute look at the homepage and the domain usually settles it.
  • Ask one question, such as the company website, and compare it with the email domain.
  • Check again later. A domain that was new at sign-up is a month older a month later. Lift the limits when the account looks normal.

Impersonation needs one more step on your side. is_lookalike compares a domain with popular email providers, not with your brand, so compare new domains with your own domain and your customers’ domains yourself. Lookalike and punycode domains covers the pattern.

Next steps

  1. Pick the forms where a bad account is expensive, and send deep=true there only.
  2. Test your review lane with unknown@test.isbusinessemail.com. It returns is_new_domain: true with the new_domain and parked_domain reasons, needs no key and is never counted (test addresses).
  3. Store category, domain_age_days and the registration date on every account, and compare conversion and abuse by age after a few weeks.
  4. Read free trial abuse: the email signals that catch it for the rest of the playbook, then get a free API key.

Frequently asked questions

How do I check when a domain was registered?

Look the domain up over RDAP, the structured successor to WHOIS, and read the date of its registration event. You can query the registry yourself, use a bootstrap service such as rdap.org, or call an API: isBusinessEmail returns domain_age_days on a deep check.

Is a newly registered domain a sign of fraud?

It is a risk signal, not proof. Throwaway domains made for trial abuse and phishing are almost always new, but so are the domains of genuine startups and new projects. Use age to decide how closely to look at a sign-up, not whether to reject it.

How new is too new?

isBusinessEmail flags domains under 30 days old with new_domain and is_new_domain, and domains under 180 days old with young_domain. Many teams review the first group and only lower the score for the second, but the right cut-off depends on what a bad account costs you.

Why is domain_age_days null?

The registration date is only looked up on a deep check, or when the domain was already enriched. Even then it can be null when the registry does not publish a registration date over RDAP or the lookup times out, so treat null as unknown rather than old.

Does a deep check cost more than a normal check?

Yes. A check with deep=true counts as 5 checks against your daily quota, and an account can run at most 1,000 deep checks a day. Deep checks need a secret key and take longer, because they wait for the registry and the domain's homepage.

Should I block sign-ups from newly registered domains?

No. Blocking on age alone turns away founders in their first week. Send new domains to a review lane instead: ask for a card before the expensive part of the trial, hold back costly features, or have someone approve the account.