> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tracenow.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Block fake account signups

> Stop bot-driven registrations, disposable emails, and mass account creation before they hit your database.

Fake accounts inflate your user counts, abuse free tiers, launder activity, and seed future fraud. They arrive in scripted, headless bursts, often from the same IP or device, and are cheapest to stop at the moment they try to register.

tracenow evaluates every `signup` event against email quality, IP reputation, device signals, and creation velocity. A single rule can stop a scripted wave; a small policy stops everything else.

## Which event this protects

Fake account creation maps to the `signup` event. The Cloudflare Worker fires it on every POST to your registration route before the request reaches your app. Nothing registers in your database until tracenow clears it.

## How it works

When a signup request hits your registration route, the Worker:

1. Reads the email address and submitting IP from the request.
2. Attaches the device fingerprint token (already injected by the Worker on the previous page load).
3. Calls `/trace` with `event: signup`; enrichment runs in parallel across email, IP, and device.
4. Evaluates your fake-accounts policy against the enriched signals.
5. Returns the verdict: `allow` (registration proceeds), `challenge` (add friction), or `deny` (blocked at the edge).

### Signals used

| Signal                                  | Why it matters                                                     |
| --------------------------------------- | ------------------------------------------------------------------ |
| `email.is_disposable`                   | Throwaway inboxes; no real user needs one to sign up               |
| `email.email_randomness_score`          | High scores (`gt 7`) flag generated addresses like `xk9m2@...`     |
| `email.domain_age_days`                 | Domains under 30 days old are routinely spun up for abuse          |
| `email.suspicious_tld`                  | TLDs like `.xyz`, `.click`, `.top` skew heavily toward fraud       |
| `ip.is_hosting`                         | Data-center IPs; almost no real user registers from AWS or GCP     |
| `ip.is_tor`                             | Tor exit nodes are used specifically to hide origin                |
| `ip.is_proxy` / `ip.is_vpn`             | Anonymizing proxies are a near-universal signal in account farms   |
| `velocity.ip.trace_count_1h`            | More than 10 signups from the same IP in an hour = a bot           |
| `device.is_headless`                    | Headless browsers don't have real users behind them                |
| `device.automation_detected`            | WebDriver or Puppeteer fingerprints indicate scripted registration |
| `velocity.device.distinct_user_ids_24h` | One device creating more than 3 accounts in 24 hours               |

See [Signals](/concepts/signals) for the full field reference.

<Note>
  **Fully covered at the edge.** Fake-account signals (email, IP, device, velocity) are all
  available before sign-in, so the Cloudflare Worker covers this use case with no backend code.
  The optional [server-side call](/guides/server-side) only helps if you want to seed device
  history for later account-takeover detection.
</Note>

## Set it up

<Tip>
  **Fastest setup:** enable the pre-built [Fake accounts policy templates](/guides/policy-templates)
  in Monitor mode instead of building these rules by hand. The steps below show what each
  template contains, so you can tune them afterward.
</Tip>

<Steps>
  <Step title="Connect Cloudflare (if you haven't already)">
    In the dashboard under **Integration**, paste a Cloudflare API token with **Workers Scripts: Edit**
    and **Zone → DNS: Read** scopes. tracenow validates the token and lists your zones.
  </Step>

  <Step title="Add a route rule for your registration endpoint">
    Under **Integration → Routes**, add a rule:

    * **Route pattern:** e.g. `yourdomain.com/api/auth/signup` or `yourdomain.com/register`
    * **Method:** `POST`
    * **Event:** `signup`
    * **Mode:** start with `Monitor` to observe traffic without blocking
  </Step>

  <Step title="Enable the Fake accounts policies">
    Under **Guard**, enable the pre-built [Fake accounts policy templates](/guides/policy-templates) for the `signup` event in **Monitor** mode. To customize or add your own rules, see [Rules](/guides/rules).
  </Step>

  <Step title="Switch to Enforce mode when you're confident">
    Once you've reviewed a few days of Monitor traces and confirmed the rules are catching the right traffic, go back to **Integration → Routes**, edit the signup route, and change **Mode** to `Enforce`.

    Click **Deploy** to push the updated Worker to Cloudflare.

    <Note>
      In Enforce mode, `deny` verdicts are returned at the edge as a `403` (or your custom response) and your app never sees the request. `challenge` verdicts are forwarded to origin; enforce them in your app via the [server-side](/guides/server-side) call.
    </Note>
  </Step>
</Steps>

## Rules

You don't build these by hand. The pre-built [Fake accounts policy templates](/guides/policy-templates) cover these patterns and enable in one click. See [Rules](/guides/rules) to customize them or add your own.

## What a caught attempt looks like

A typical fake-account wave produces traces like this in the event feed:

In the API response, a blocked signup looks like:

```json theme={null}
{
  "trace_id": "tr_01hx...",
  "verdict": "deny",
  "event_type": "signup",
  "status": "attempted",
  "signals": {
    "email": {
      "is_disposable": true,
      "email_randomness_score": 9.2,
      "domain_age_days": 4,
      "suspicious_tld": true
    },
    "ip": {
      "is_hosting": true,
      "is_vpn": false,
      "is_tor": false,
      "geo": { "country": "United States", "country_code": "US" },
      "as": { "asn": "AS16509", "name": "Amazon.com Inc.", "type": "hosting" }
    },
    "device": {
      "is_headless": true,
      "automation_detected": true
    },
    "velocity": {
      "ip": { "trace_count_1h": 47, "failed_count_1h": 0 }
    },
    "decision": {
      "rule_name": "Block disposable and generated emails",
      "logic": "OR",
      "matched_conditions": []
    }
  },
  "policy": {
    "name": "Fake accounts",
    "action": "deny",
    "rule_name": "Block disposable and generated emails"
  }
}
```

## Going further

The Cloudflare layer evaluates `signup` without a real user ID. It uses the submitted email as the subject, which is enough to stop the vast majority of fake-account campaigns.

If you want to tie signups back to a confirmed `subject_user_id` after your app creates the account (for linking future login and OTP events), add the [server-side](/guides/server-side) in-app call immediately after your registration handler succeeds:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const result = await fetch("https://api.tracenow.io/trace", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.TRACENOW_SECRET_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      event: "signup",
      status: "succeeded",
      ip: req.ip,
      email: user.email,
      device_token: req.headers["x-tn-device-token"],
      subject_user_id: user.id, // now you have a real ID
    }),
  });
  ```

  ```python Python theme={null}
  import httpx, os

  result = httpx.post(
    "https://api.tracenow.io/trace",
    headers={"Authorization": f"Bearer {os.environ['TRACENOW_SECRET_KEY']}"},
    json={
      "event": "signup",
      "status": "succeeded",
      "ip": request.remote_addr,
      "email": user.email,
      "device_token": request.headers.get("x-tn-device-token"),
      "subject_user_id": str(user.id),
    },
  ).json()
  ```
</CodeGroup>

This seeds the per-user history that powers the [account-takeover](/use-cases/account-takeover) signals (`is_new_for_user`, `is_new_country_for_user`, and `distinct_ips_24h`) from the very first session.
