Stop Serial Trials, Quota Farming & Perpetual Evaluators
Serial trialers change emails, cookies and IPs because those cost nothing; the laptop underneath usually stays the same. Send the new account's ID with one server-side check and the response counts how many of your accounts that device has opened. When Maskbreak recognises a fresh fake-browser profile, a script or a proxy, that shows up as a reason of its own.
What you're up against
Trial resets that never end
New email, cleared cookies, fresh residential-proxy IP — and the free trial starts over. Nothing in a typical signup flow connects attempt #12 to attempt #11, so the reset loop runs for as long as the abuser cares to keep it going.
Quota farming on AI products
When the free tier includes model inference, every farmed account has a direct marginal cost. Scripted signups harvest quota across dozens of accounts, and the bill lands on your inference invoice, not the abuser's.
Competitors who evaluate forever
A rival's team can rotate trial accounts for months — benchmarking features, probing limits, demoing your product to their own prospects — without ever crossing the paywall or showing up as a single named account.
IP limits that proxies walk around
Per-IP signup caps and disposable-email blocklists are exactly the controls residential proxies and inbox aliases were built to defeat. The abuser adapts once, and the control stops working.
What Maskbreak does for you
- Count how many of your accounts each device has opened: send
accountIdand readdevice.linked_accounts. A new email or a new IP does not reset it; a link expires after 90 days without a sighting - Read the network before you provision anything: a VPN alone comes back review, a recognised proxy (residential exits included) comes back block, and a cloud-server address alone is listed as
datacenter_asnbut allowed - Flag the fake browsers (antidetect), automation and emulators that make scripted trial farming cheap, when the device check sees them; all three block by default
- Get an allow / review / block decision with reason codes, so trial policy stays in your code
- Score every signup with one server-side call: no CAPTCHA, no extra step for honest evaluators
resetting the same free trial is the tell. A worked model of a B2B SaaS whose trials never converted, and the device-linking check that exposes the loop. Illustrative scenario, not a customer result.
Read the PlaybookWhere the check goes
For trial abuse one call site matters most: the signup handler, after you create the account row and before the trial starts, so before a workspace, an API key or any quota exists. Pass that row's ID as accountId (set on your server, never read from the form) together with the email address, which is checked against known throwaway domains and not stored. If your product meters usage, run the same check wherever quota is granted or reset: that is the moment a farmed account starts costing you money. The example starts in watch mode: it logs each decision with linked_accounts, lets every signup through and fails open if Maskbreak is unreachable. After a few days, compare the log with the Events tab in your console, then turn on the enforce line and your own limit on linked_accounts; the integration guide has the full enforce checks.
// Trial signup: `user` is the account row you just created; no trial or quota yet // 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, // throwaway-domain check; the address is not stored accountId: String(user.id) // your own id, server-side: counts your accounts per device }) }); 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, linked_accounts: risk?.device?.linked_accounts ?? null, degraded: risk ? !!risk.degraded : null })); // Enforce later: if (risk?.decision === 'block') return res.status(403).json({ error: 'Signup rejected' }); // (disable the account row first). multi_account_device leaves the default decision alone, // so repeat trials need your own limit: above it, start the trial only with a card on file.
The signals that matter here
The account count is the number that matters here. Serial trialers change everything that is free to change: email address, cookies, IP. A resetter who keeps the same machine and browser usually comes back as the same device.visitor_id, and when you send accountId, device.linked_accounts climbs with every new trial, whatever the form claims. The count covers your accounts only, stored as one-way hashes, and a link expires after 90 days without a sighting. (device.times_seen is not this count: it tallies sightings across all Maskbreak traffic.) That one number is the difference between stopping trial abuse at scale and playing whack-a-mole with email domains.
Network signals mean different things at signup. A commercial VPN on a paying customer's login is usually privacy hygiene; on a brand-new trial it is a reason to ask for one more step. By default a VPN alone comes back review, with the service named in network.service when known, and a recognised proxy, residential exits included, comes back block. A cloud-server address alone (datacenter_asn) stays allow, because engineers do evaluate from cloud dev boxes. The raw network block (network.vpn, network.proxy, network.datacenter, network.residential) is there when you want a stricter trial policy than your login policy.
Automation before the quota grant. Farming a free tier only pays if account creation is cheap, which in practice means scripts, emulators or antidetect browsers, fake browsers that hand out a new fingerprint per profile. When Maskbreak's device check sees them, the signup returns automation_detected, emulator_detected or antidetect_browser, all blocked by default, so once you enforce, the farmed account never receives an API key or a token of inference quota. A brand-new fake-browser profile has no earlier accounts to link to, which is why this check and the account count work as a pair.
A score and a decision, not a black box. Every check returns a risk_score from 0 to 100, a decision of allow, review or block, and the reasons behind it. That lets you run asymmetric policy: refuse automated signups, ask a VPN or a throwaway inbox for a verified work email, ask the fourth account from one laptop for a card on file, and keep a competitor's fifth anonymous trial on the shortest leash you offer. Keep the account limit in your own code. A Multi-accounting rule on the console's Rules tab matches every check that sends an accountId from a device linked to more than one of your accounts. It decides for that signal only, so a proxy, Tor, automation, fake-browser or emulator block on the same check stays a block.
What a repeat trial looks like in the response
The sixth trial from one laptop on an AI product, over home broadband, with an ordinary email address. Nothing about the visit itself is suspicious; the account count is the finding.
// Example response, selected fields: the 6th trial from one laptop
{
"decision": "allow",
"risk_score": 0,
"reasons": ["multi_account_device"],
"network": { "vpn": false, "proxy": false, "datacenter": false, "tor": false, "residential": true },
"device": {
"antidetect": false,
"automation": false,
"returning": true,
"linked_accounts": 6,
"multi_account": true
}
}The decision stays allow because multi_account_device alone never changes the default: families, agencies and shared office machines open second accounts too. Acting on linked_accounts: 6 is your call. Where every trial is inference you pay for, treat an allow whose reasons include multi_account_device as a review in your own handler and start trial six only with a card on file. Send a throwaway inbox from the same laptop and the answer becomes review with disposable_email; add a fake browser or a proxy and it becomes block.
Common questions
End the perpetual free trial
Free plan: 10,000 visitor checks a month, no card. Paid plans from €29 a month. Counts your accounts per device and flags residential proxies, fake browsers and scripted signups when it recognises them.