Back to Case Studies
SaaS · Attack playbook
A worked playbook, not a customer result. The mechanics describe how trial resets are commonly done, the JSON is an example response in Maskbreak's documented shape, and the arithmetic is a model — swap in your own inputs.

The trial that never ends

Somewhere in your account table is a cohort that has been on your platform for a year and has never paid a cent. Each account is individually unremarkable: a new email, a new trial, fourteen days, gone. Together they are a product being used in production for free, and they are usually invisible because nothing links one to the next.

1
New identity per trial — nothing to count
0
Signup-form fields shared between one trial and the next
3
Layers a determined resetter has to rotate
1 call
Server-side verdict; measured timing on /status
Signals in this playbook
Shared device
Proxy (incl. residential)
Fake browser

This page is the attack playbook. For the implementation checklist and detection order, read How to detect and prevent free trial abuse; for a watch-mode snippet, see the trial-abuse fix.

How the attack works

Trial abuse is the cheapest fraud in this collection because it barely requires tooling. The whole technique is producing a new identity on a schedule:

  • A new email — a catch-all domain or a plus-address on a provider that ignores it, so one mailbox produces any number of addresses that all deliver.
  • A new IP — a residential proxy or just a phone hotspot, enough to break any per-address counting.
  • A cleared browser, or for the more committed, a fake-browser (antidetect) profile so the device fingerprint does not repeat either.

At the low end this is one person and a bookmark. At the high end it is an agency running a client workload permanently on somebody's free tier. The distinction matters commercially and not at all technically — the detection is identical.

Why the usual defences miss it

Email uniqueness is not identity. Catch-all domains produce infinite valid addresses; plus-addressing does the same on major providers unless you normalise it, and normalising it breaks legitimate users who genuinely rely on tagged addresses. A disposable-domain check does not help much either: a private catch-all domain is on no throwaway list.

Requiring a card works and has a price: fewer honest evaluators start a trial at all. It is a business decision disguised as a fraud control, and it should be made on your own conversion number rather than on the abuse one.

Per-IP limits catch the careless and punish the legitimate: an office, a university or a carrier NAT range shares one address between hundreds of real people.

Matching device fingerprints works right up until someone uses a fake browser, at which point every trial arrives with a new fingerprint. What does not change is the spoofing itself, which is a signal of its own.

What the verdict returns

Screening at trial signup is one server-side call to POST /v1/evaluate, with the new trial's own account id sent as accountId so the linkage is computed against your accounts only. Example response (excerpt) for the low-end resetter: a home connection, an ordinary browser with its cookies cleared, and a device already seen with eight earlier trials:

{
  "decision": "allow",
  "risk_score": 0,
  "reasons": [
    "multi_account_device"
  ],
  "network": {
    "vpn": false,
    "proxy": false,
    "datacenter": false,
    "tor": false,
    "residential": true,
    "service": null
  },
  "device": {
    "antidetect": false,
    "automation": false,
    "tampering_score": 0,
    "times_seen": 14,
    "returning": true,
    "first_seen": "2026-02-14T09:31:07.000Z",
    "linked_accounts": 9,
    "multi_account": true
  }
}

linked_accounts: 9 is the entire finding. It says this device has been seen with nine of your accounts — which no per-account check can see, because each account really was new. It is per customer and hash-only: your accounts are never linked against another customer's. times_seen and first_seen are different: they are Maskbreak-wide history for the device, not a count of your accounts.

Note the decision is allow. Nothing on the connection or in the browser is a threat, and multi_account_device does not change the decision on its own. That is the right default here: nine accounts on one device is a contractor with nine clients as often as it is one person resetting a trial, and the two deserve very different treatment. Route on the reason in your own code, or set a Multi-accounting action on the console’s Rules tab.

The committed resetter looks different. Behind a residential proxy, in a fake browser that mints a new device per trial, the example response comes back like this:

{
  "decision": "block",
  "risk_score": 93,
  "reasons": [
    "proxy_detected",
    "antidetect_browser"
  ],
  "network": {
    "vpn": false,
    "proxy": true,
    "datacenter": false,
    "tor": false,
    "residential": false,
    "service": null
  },
  "device": {
    "antidetect": true,
    "automation": false,
    "tampering_score": 0.8,
    "linked_accounts": 1,
    "multi_account": false
  }
}

The count stays at 1, and it does not matter. A residential proxy shows up as proxy_detected with network.proxy true (residential is false whenever a proxy is detected, and service names the operator when known), and the fake browser shows up as antidetect_browser. Either one is a block by default.

A Rules-tab rule changes the decision only for the signal it names. “Multi-accounting = Review” would send the low-end resetter above to review, and it never lowers a proxy, Tor, automation, fake-browser or emulator block on a linked device.

What to do about it, in order

Blocking is the worst first move here, because the population contains paying customers who have not converted yet.

  1. Start in watch mode. Log every decision for a month, let every trial through and act on nothing. The distribution will not be what you assumed, and you will find a small tail worth looking at by hand.
  2. Limit the resource, not the account. Cap what a trial can consume — seats, API calls, exports — rather than how many trials exist. A resetter loses the value; an evaluator does not notice.
  3. Ask for the upgrade. An account on its fifth trial with real usage is a customer telling you your pricing has a gap. The message that converts is an offer, not a warning.
  4. Refuse only the unambiguous tail. When you switch to enforce, the engine’s block (proxy, Tor, automation, fake browser) is that tail. High linkage alone, with no meaningful usage, is a business call you make after the watch-mode month, not a default. Keep the refused group small.

The arithmetic

A worked model. Replace the inputs with yours.

InputModel valueYours
Perpetual-trial accounts identified320—
Your entry plan, annualised€300—
Share that would convert rather than leave10%—
Infrastructure cost per trial account per year€14—

Recovered revenue is 320 × 10% × €300 = €9,600, plus €4,480 of infrastructure you stop donating. The third input is the one everybody gets wrong: the instinct is to multiply all 320 by the plan price and call it recovered ARR. Most of that population leaves rather than pays, and a model that assumes otherwise will justify enforcement that costs more than it returns.

Which is why the honest version of this number needs a holdout — a slice you deliberately leave alone. Without one you cannot distinguish revenue you recovered from churn you caused.

The adjacent problem: competitors in your trial

The same signals surface something teams are often more annoyed by than the free usage: competitors and data brokers taking trials to scrape pricing, feature availability or your customer-facing directory. The pattern is distinctive — a trial that consumes read endpoints heavily, touches nothing that writes, and never invites a second user.

That behavioural half is yours to measure; the network and device half is the same call described above, and the combination is much stronger than either.

Measure it on your own trials

Pass your account id and get device-to-account linkage back, hashed and scoped to you. Free plan: 10,000 visitor checks a month, no card. Paid plans from €29 a month.

Get Free API Key
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.