What is bonus abuse?
Bonus abuse is the repeated claiming of a per-customer promotion — a signup bonus, a deposit-match, or free credit — through duplicate accounts that pretend to be new players. It is common in iGaming and rewards programs, where the bonus has direct cash value and one person can profitably farm dozens of accounts.How ShieldLabs surfaces it
ShieldLabs resolves each claim to a set of identifiers: the per-claim RequestID, the cookie-scoped VisitorID, your hashed UserHID for the account, and the durable, server-derived DeviceID that survives a cookie clear, incognito, and IP rotation. A hunter clears cookies, opens a private window, and rotates VPN IPs between accounts precisely so each claim looks new, so counting cookies or public IPs lets the farm right through. The DeviceID holds steady underneath and lets your code see how many “new” players actually share one machine. ShieldLabs also returns a per-request Risk Score (0–100). When a hunter masks the connection, the anonymity signals fire, and the real network IP (local_ip.ip) can reveal the network behind the public public_ip.ip they rotate. When their countries disagree, detection_flags.ip_mismatch is set to true (informational only, surfaced for your code; it does not change the score, and can be benign on mobile networks). The durable tell is the constant local_ip itself, the Local IP the patterns correlate on, so a farm rotating VPN exits still collapses to one local_ip.
The dashboard grades the relationship over time with the Many Accounts on One Device and Many Accounts on One Local IP patterns; your claim code enforces your per-customer policy.
Stop bonus abuse
The rule your code applies, wired up in## Build it below: read the claim session’s score and its signals breakdown for masking, and read the durable DeviceID plus the real network IP (local_ip.ip) to count how many distinct UserHID accounts have already claimed off that one machine or local network. Then:
- Credit the bonus when the score is low and the device is fresh.
- Hold it for verification when the claim is masked, when the Many Accounts on One Device or Many Accounts on One Local IP pattern flags the entity, or when the live account count crosses your per-customer cap.
local_ip, so the bonus pauses for review instead of paying out, while a genuine new player goes through.
Build it
Create a ShieldLabs account and get your keys
Sign up for free and get 5,000 identifications, or log in if you already have an account. Register the domain you want to identify visitors on, then open the Keys page. Use the Public Key to initialize the snippet in the browser, and keep your server-side credentials on your backend: the Private API Key authenticates the History API, and each webhook endpoint has its own
whsec_… signing secret. See Keys.Identify the claim session
Add the snippet to the page where the bonus is claimed — the “claim bonus” button, the deposit form with a bonus code, the welcome-offer screen. Re-identify on the action so you score the session that is actually claiming, not a stale page load. Pass the account’s hashed id, never a raw email. Use
forceCheckAuthenticatedUser here (not checkAuthenticatedUser): a bonus claim is a sensitive, value-bearing action, so resetting the visit session first gives you a fresh score keyed to a requestID you can act on, per the snippet methods.claim-bonus.html
Read the scored result on your server
The score arrives on the webhook. Verify the
X-Shield-Signature HMAC, then cache it by request_id. Your claim endpoint reads it back with the shared waitForScore helper from the Use Case Tutorials, or falls back to a History API read by request_id. The fields that matter are device_id, user_hid, score, signals, detection_flags, and the two IPs — public_ip (public, VPN-fakeable) and local_ip (the live equivalent of the Local IP behind the Many Accounts on One Local IP pattern):the webhook your handler caches
Count the accounts behind the device and decide
This is where your code owns the verdict. Link the related accounts on the durable A determined hunter using several genuinely separate browsers shows up as several devices, since the DeviceID is browser-bound. The Many Accounts on One Local IP pattern closes that gap: ten accounts claiming through one local IP is a strong shape even when each reports a different device. Use the pre-computed pattern export as a fast denylist; reserve live
device_id: read the History API by device_id and count the distinct user_hid values it has touched — that count is the number of accounts behind the machine. Combine it with the session score, then decide grant, verify, or deny.api/claim-bonus.js
shieldHistory is the shared History API read from the Use Case Tutorials, here keyed by device_id. The underlying call:Read a device's claim history
device_id reads for the borderline, high-value claims.Decide and tune
Verify, do not hard-deny on the score alone — a real new player on a corporate VPN, a privacy browser, or a shared household network can score high or share a device with a relative. Holding a suspicious claim for a quick verification step keeps the genuine player in while still stopping the farm. Start in logging-only mode, watch how real claims distribute, then tune against your own traffic before you tighten thresholds.
Test it
You do not need a real farm to see this hold. Claim the bonus once in your normal browser and note thedevice_id on the webhook. Then play the hunter: clear cookies, open a private/incognito window, or switch to a second browser profile, and claim again as a different account. The cookie_id and visitor_id change on each run, but the same device_id returns, and the distinct-user_hid count off that device climbs with each claim — which is exactly the count your handler gates on. Toggling a VPN or switching networks should also light up the anonymity signals on the claiming session without changing the durable DeviceID.
Recommended starting policy
A guide, not a rule. Layer the score with the account count and tune against your own traffic.| Signal at the bonus claim | Suggested action |
|---|---|
| Clean / Low score, no repeat device | Grant the bonus |
| Medium score, no pattern flag | Grant, but log and watch the device |
| High score | Hold for verification before crediting |
| Device or local IP flagged Suspicious | Require verification, regardless of the session score |
| Device or local IP flagged Dangerous | Deny the bonus and route to review |
| All-zero DeviceID (blocked or JS-disabled, score 90+) | Hold for verification on the score alone |
Next
Promo Abuse
The sibling reward gate: coupons, referral credit, and trial resets claimed once per customer, counted off the same durable DeviceID.
New Account Fraud
Thin the farm at registration before it ever reaches the bonus, by joining each new account to its DeviceID.