Stop Fake Signups

Stop Bot Signups, Disposable Emails & Fake Account Creation

Bot-registered accounts, throwaway inboxes and proxy-masked registrations fill your funnel with users who never existed. Maskbreak checks each registration, on the form and in the OAuth callback, with one server-side call before the user row exists. Real visitors see no challenge.

1 callServer-side decision; timing on /status
FreePlan: 10,000 visitor checks a month, no card
2Call sites: the signup form and the OAuth callback
3Answers: allow, review or block, with reasons

What you're up against

Bot-registered accounts at scale

Scripted signups run headless browsers through your registration form, pass email verification, and land in your database looking like users. Every one skews activation metrics and burns onboarding email sends.

Disposable emails that pass validation

New burner mailbox domains keep appearing, and a blocklist you maintain by hand falls behind. The addresses are syntactically valid, receive the verification mail, and click the link.

Proxy-masked registrations

Each fake signup arrives from a fresh residential IP, so per-IP rate limits and geo rules never fire. The registrations look geographically diverse when they are one operator behind a proxy pool.

Poisoned funnel metrics

Fake accounts inflate signup counts, deflate activation rate, and mislead every growth experiment you run. By the time the anomaly is obvious, weeks of A/B test data are already contaminated.

What Maskbreak does for you

  • Block headless and scripted browsers (automation_detected) and fake browsers (antidetect_browser) by default
  • Read the network behind each registration: a proxy or Tor exit blocks by default, residential proxies included; a VPN alone is flagged for review; a cloud-server address alone stays allow with datacenter_asn listed
  • Flag throwaway inbox domains with disposable_email when you send the address; it raises an allow to review and never blocks on its own
  • Send the new account's ID as accountId and device.linked_accounts counts how many of your accounts that device has been seen with
  • Get the answer before the verification email is queued, so once you enforce, a blocked bot never costs you a send or puts a mail in someone else's inbox, the trick behind email bombing

Choosing between tools? Eight of them, Maskbreak included, are compared from their own pages in fake account prevention software compared: what each checks at signup, its free plan, its price and where each beats Maskbreak.

1 device

behind many new accounts within days of a signup bonus is the tell. A worked model of a fintech launch, the signals that show it and the response plan. Illustrative scenario, not a customer result.

Read the Playbook

Where the check goes

Two call sites cover registration fraud: signup (before you write the user row or queue the verification email) and the OAuth callback (a Google identity says nothing about the device that just presented it). The client snippet rides along in your registration page; the server asks Maskbreak for a verdict before the account exists. The example starts in watch mode: it logs each verdict, lets every request through and fails open if Maskbreak is unreachable. After a few days, compare the log with the Events in your dashboard, then uncomment the enforce line; the integration guide has the full enforce checks. The example also sends the signup email so a throwaway domain is flagged; the address is checked and not stored.

// Score the signup before you create the account or send verification email
// Watch mode first: log the verdict, always continue, fail open
const body = req.body || {};  // sentinel.js adds monocle + sentinel_fp to your form
let risk = null;
try {
  const verdictRes = await fetch('https://maskbreak.com/v1/evaluate', {
    method: 'POST',
    signal: AbortSignal.timeout(5000),
    headers: {
      'Authorization': 'Bearer ' + process.env.MASKBREAK_API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      token: body.token || body.monocle,  // network evidence
      fingerprintEventId: body.fingerprintEventId || body.sentinel_fp,  // device evidence
      tz: body.tz || body.sentinel_tz,
      email: body.email  // optional: flags throwaway domains
    })
  });
  if (verdictRes.ok) risk = await verdictRes.json();
} catch {}  // unreachable or timed out: your handler still runs
console.log('[maskbreak]', JSON.stringify({
  decision: risk?.decision ?? null, reasons: risk?.reasons ?? null,
  risk_score: risk?.risk_score ?? null, degraded: risk ? !!risk.degraded : null
}));
// Enforce later: if (risk?.decision === 'block') return res.status(403).json({ error: 'Request rejected' });

What a scripted signup gets back

A headless browser behind a residential proxy, registering with a throwaway inbox. The proxy and the automation each block by default; the disposable domain adds its reason, though on its own it would only have raised an allow to review. Example response, trimmed:

{
  "decision": "block",
  "risk_score": 100,
  "reasons": ["proxy_detected", "automation_detected", "disposable_email"],
  "network": { "vpn": false, "proxy": true, "datacenter": false, "tor": false, "residential": false, "service": null },
  "device": { "automation": true, "antidetect": false, "tampering_score": 0 },
  "email": { "disposable": true }
}

The same throwaway inbox from a plain home connection and a clean browser gets review, with ["disposable_email"] and a risk_score of 15 when nothing else adds to it. A cloud-server address with nothing else flagged gets allow, with datacenter_asn listed. network.service names the proxy or VPN operator when known and is null otherwise.

See a verdict before you integrate

Run the live check on the homepage to see the network and browser checks on your own visit, no key needed. The free IP lookup tool takes any address, but a bare IP only shows Tor exits and published cloud ranges; VPN and proxy verdicts need a live visit. The disposable-email flag and multi-account linking come with the API.

The signals that matter here

Throwaway inboxes, without a list to maintain. Send the signup email as the optional email field and Maskbreak checks its domain, subdomains included, against a disposable-mail list it refreshes every day. A match adds disposable_email and raises an allow to review. It never blocks on its own: a burner inbox is a reason to look closer, not proof of a bot. If a refresh fails, the previous list stays in use. The address is checked in memory and not stored.

Automation a form can't see. Scripted registrations run headless Chrome with stealth patches, or fake (antidetect) browsers with a made-up fingerprint per profile. Maskbreak's device check returns automation_detected or antidetect_browser, and either one blocks by default. virtual_machine is listed too; on its own it asks for review, never a block: plenty of real people work inside a VM.

One person, many accounts. Throwaway inboxes and proxy rotation make each fake signup look new. Send the ID you are giving the new account as accountId: device.linked_accounts counts how many of your accounts that device has been seen with, and above one the response lists multi_account_device. It changes nothing by default, so read it in your handler (more in preventing multi-accounting). If you set a Rules-tab action for it instead, that rule decides for the shared device only: a proxy or fake browser on the same signup still blocks. Links are per customer, stored as one-way hashes, and never cross to another customer. device.times_seen is different: all sightings of the device across Maskbreak, useful as "brand-new device or not", never a count of your signups. For a fake browser that invents a new device per profile, the signal to read is antidetect_browser, not the link count.

OAuth signups are still signups. A Google or GitHub identity proves someone controls a mailbox, not that the device behind it is clean, and bulk-created OAuth accounts pass checks that only watch the password form. Run the same check in the OAuth callback so network.proxy, network.vpn and the device signals cover every registration path, not just one.

Common questions

How does Maskbreak flag disposable email addresses?
Send the signup email as the optional email field. Maskbreak checks its domain, and the parent domain, against a disposable-mail list it refreshes every day, so you do not maintain one. A match adds disposable_email and raises an allow to review; it never blocks on its own. If a refresh fails, the previous list stays in use. The address is checked in memory and not stored.
Will privacy-conscious users on VPNs get rejected?
Not by default. A VPN on its own returns review with vpn_detected, never block, and the response carries network.vpn and network.service (the operator's name when known). Your code decides what review means: let the account in and watch it, or ask for one more verification step. Proxies, Tor exits, automation, emulators and fake browsers are what block by default.
Does a signup from a cloud server get blocked?
No. A cloud-server address with nothing else flagged stays allow, with datacenter_asn in the reasons and network.datacenter true, because offices, CI runners and corporate gateways use them too. If the same signup also shows automation, a proxy or a fake browser, it is blocked because of those signals.
Does this work for 'Sign in with Google' registrations?
Yes. The browser snippet runs on your page whatever the sign-in method, and the device and network checks are the same on both paths. If Google's button posts an ID token to your server, post the two browser fields with it. If the sign-in uses a redirect, collect them with Sentinel.collect() before sending the visitor to Google and keep them in the session for the callback. A Google identity proves control of a mailbox, not that the device behind it is clean.
What happens if the Maskbreak API is unreachable?
We recommend failing open: if the call errors or passes your timeout, create the account and mark it for a second look instead of turning a real person away. A response with degraded: true was answered without part of its evidence, so treat its allow the same way. Each response reports its own processing time in evaluated_in_ms, so you can set the timeout from your own traffic.
How much does it cost to try?
Nothing on the Free plan: 10,000 visitor checks a month, every signal included, no card. Paid plans raise the allowance, from €29 a month for 50,000 checks; larger volumes are on Enterprise. If you need help reading your first week of results, contact us and a person will answer.

Keep fake accounts out of your database

Free plan: 10,000 visitor checks a month, no card. Paid plans from €29 a month. Flags proxies (residential ones included), fake browsers and scripted signups.

Fraud BriefOnce a month · no spam · unsubscribe anytime
Get the new VPN, proxy & bot patterns we see each month
Short, technical breakdowns of what fraudsters changed last month — written for engineers, not marketers.
Stop fraud before it hides — try Maskbreak free. Free plan: 10,000 visitor checks a month, no card. Paid plans from €29 a month.