On this page
Every Taylor Swift drop, every Yeezy release, every PS5 restock turns into the same scene: thousands of items gone in 90 seconds, immediately listed on StockX or eBay at 4×. The buyers are not your fans. They're 12 GPUs in a Romanian data center renting residential proxies and antidetect browsers.
If you sell anything that's both scarce and resold for profit — concert tickets, limited sneakers, console restocks, designer drops, NFT mints, presale slots — you have a bot problem. And if your defense is "we have reCAPTCHA on the cart page," you don't have a defense.
How modern ticketing & drop bots actually work
The "drop bot" software market is professional. Tools like AIO Bot, Cybersole, Wrath, Stellar AIO, and Soleslayer cost $200–$1,200/year and ship with active Discord support. They're optimized for exactly two things: speed of checkout, and evading exactly the kind of defenses you've been told to install.
A typical drop run looks like this:
- Pre-positioned tasks — the operator queues 200–2,000 "tasks" pointing at your specific product URL. Each task is a separate session with a unique fingerprint.
- Residential proxy assignment — each task pulls a fresh US residential IP from BrightData, Smartproxy, IPRoyal, or NetNut. From your access logs, every request looks like a different home Comcast user.
- Antidetect browser session — Kameleo or GoLogin gives each task a unique canvas hash, WebGL renderer, audio fingerprint, timezone, and screen resolution. Browser-fingerprint matching gives you nothing.
- Captcha solver pre-warmed — 2Captcha and CapSolver hold a queue of solved tokens. The bot does not "solve" your captcha; it pastes one in 0.4 seconds.
- Coordinated burst at T-0 — at the second the drop opens, all 2,000 tasks attempt checkout simultaneously. From your servers' point of view, you got a flash flood of legitimate-looking US residential users.
Why traditional defenses don't work here
reCAPTCHA / hCaptcha
Cost to solve a reCAPTCHA v2 in 2026: $0.0006 in 9 seconds via 2Captcha. For a $400 ticket marked up to $1,200, an operator can spend $0.06 on captcha solving per attempt and still net $799.94. CAPTCHAs are a tax on real users at this point. (Long version: bot detection without CAPTCHA.)
IP rate-limiting
Every single request comes from a different residential IP. A blanket per-IP limit blocks zero bots and blocks plenty of real users behind shared NAT (university campuses, mobile carriers, corporate VPNs). Negative signal-to-noise.
Account-age requirements
Bot operators farm aged accounts months in advance. There's a whole subculture on the BlackHatWorld and Nulled forums dedicated to it. A drop bot's account pool is older than yours.
Browser fingerprinting (canvas / WebGL / audio)
This was the answer in 2020. In 2026, antidetect browsers rotate every fingerprint surface per session. The Kameleo "profile" you're trying to identify is gone after one purchase.
See the check on your own visit: the free live check on the homepage runs the network and browser checks on your connection and lists every reason.
Open the live checkWhat actually works in 2026
Stopping drop bots requires signals that survive residential-proxy rotation and per-session fingerprint rotation. Three categories:
1. Behavioral signature of automation
No human can fill a 6-field checkout form in 280ms. No human moves the cursor in a perfectly straight line from product card to "Add to Cart". No human's scroll velocity has zero jitter. Drop bots overwhelmingly do all three. Behavioral analysis costs nothing for real users (it's passive) and is extremely expensive for bots to fake convincingly.
2. Network reputation beyond IP
Even when residential proxies hide the data-center origin of a request, the proxy provider is identifiable. The exit IP belongs to a known BrightData range, or shows up in 47 different account signups in the last hour, or has a TLS JA3 fingerprint inconsistent with the User-Agent it's claiming. Per-IP reputation fails. Per-network-pattern reputation works.
3. Persistent visitor identity
The single most useful signal is: "is this the same browser session that already attempted checkout 14 times in the last 60 seconds, despite each attempt coming from a different IP?" A persistent visitor ID survives incognito mode, IP changes, and most fingerprint rotation. With it, you stop counting requests and start counting sessions. The bot operator's 2,000 tasks become 2,000 visitor IDs, and you can rate-limit those.
How Maskbreak handles ticketing & drops
Maskbreak is built for exactly this case. Every check returns the network flags, and the device fields whenever the browser check ran:
- Bot / automation flag — Puppeteer, Playwright, Selenium, headless Chrome.
- Antidetect browser flag — Kameleo, GoLogin, AdsPower, Multilogin, Dolphin, Octo. The "real Chrome with fake fingerprint" tier.
- Proxy flag — separate from the VPN flag, residential pools included: an exit already tied to a known commercial or peer-to-peer proxy pool returns
network.proxy: trueand a block. - Persistent visitor ID — single stable identifier across IP rotation and incognito windows.
- Device history —
device.times_seen(lifetime sightings of the visitor ID) anddevice.linked_accounts; key your own short-window attempt counter ondevice.visitor_idfor drop-day velocity.
The full evaluation is one server-side call, and each response reports its own processing time. You can call it from your edge worker before the cart endpoint even fires.
Integration: a checkout-protected drop
Add the script to the page with the Buy form, and put class="monocle-enriched" on the <form> itself. The script then adds three hidden fields to the form in the background: monocle (the network token), sentinel_fp (the browser check) and sentinel_tz (the time zone). They arrive a second or two after the page loads, so a checkout posted sooner carries only what has arrived. In watch mode the server below still sends the check, and the answer says which half was missing; in enforce mode such a checkout is held for verification.
<script async src="https://maskbreak.com/assets/sentinel.js"></script>
<form class="monocle-enriched" method="POST" action="/api/cart/checkout">
<!-- Your existing checkout fields stay here. The script adds
monocle (network), sentinel_fp (browser check) and sentinel_tz. -->
<button type="submit">Buy</button>
</form>
A cart your JavaScript submits (React, Vue, a custom drop page) sends what Sentinel.collect() returns instead, already under the API’s names. A blocked or missing script never holds the button:
const evidence = window.Sentinel ? await window.Sentinel.collect() : {};
// evidence = { token, fingerprintEventId, tz }: send it with the cart request.
On your backend, the gate runs in front of POST /api/cart/checkout. It starts in watch mode: every checkout is checked and logged, and nothing is refused. Set MASKBREAK_MODE=enforce once the log lines match what you see in the console’s Events, well before the drop rather than during it. countRecentAttempts and existingCheckoutHandler are yours:
// Server-side only. Node.js 18+ (fetch and AbortSignal.timeout).
// 'watch' (default): check every checkout, log what enforce would do, always continue.
// 'enforce': stop block; hold review, missing evidence and errors.
const MASKBREAK_MODE = process.env.MASKBREAK_MODE || 'watch';
app.use(express.json({ limit: '16kb' }));
app.use(express.urlencoded({ extended: false, limit: '16kb' }));
app.post('/api/cart/checkout', async (req, res, next) => {
const body = req.body || {};
// Form fields -> API fields: monocle -> token, sentinel_fp -> fingerprintEventId,
// sentinel_tz -> tz. Sentinel.collect() already returns the API names.
const token = body.token || body.monocle;
const fingerprintEventId = body.fingerprintEventId || body.sentinel_fp;
const tz = body.tz || body.sentinel_tz;
const missing = typeof token !== 'string' || !token ||
typeof fingerprintEventId !== 'string' || !fingerprintEventId;
let result = null, hold = null, monthUsedUp = false;
// Watch mode sends the check even with a field missing, so the dashboard
// can say which half did not arrive. Enforce mode holds it without a call.
if (!missing || MASKBREAK_MODE !== 'enforce') {
try {
const response = 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, fingerprintEventId, tz })
});
if (!response.ok) {
const refusal = await response.json().catch(() => null);
// The month's checks are used up: let the checkout through unchecked
// until the 1st (00:00 UTC) and log it, as watch mode does.
if (response.status === 429 && refusal?.code === 'monthly_quota_exceeded') monthUsedUp = true;
else throw new Error('Evaluation unavailable');
} else {
result = await response.json();
if (!result || !['allow', 'review', 'block'].includes(result.decision) ||
result.test || result.sample || result.sandbox) {
throw new Error('No production verdict');
}
if (result.decision === 'block') {
hold = [403, 'Request declined.'];
} else if (result.decision === 'review' || result.degraded || !result.device) {
hold = [409, 'Verification required.'];
}
}
} catch {
hold = [503, 'Verification unavailable. Try again later.'];
}
}
if (missing) hold = [409, 'Verification required.']; // enforce never trusts half a check
// Drop-day velocity: your own short-window counter (a Redis INCR with a
// 60 s expiry), keyed on the visitor ID, and only when the browser check
// returned one: without it, every buyer would share a single key.
const visitorId = result?.device?.visitor_id;
let attempts = 0;
if (typeof visitorId === 'string' && visitorId) {
try { attempts = await countRecentAttempts(visitorId); } catch { /* counter down: no limit */ }
}
if (!hold && attempts > 8) hold = [429, 'Too many attempts. Try again in a minute.'];
// One line per check. Never log the key, browser tokens or form data.
console.log('[maskbreak]', JSON.stringify({
mode: MASKBREAK_MODE,
decision: result?.decision ?? null,
reasons: result?.reasons ?? null,
month_used_up: monthUsedUp,
attempts,
enforce_would: hold ? 'return ' + hold[0] : 'continue'
}));
if (MASKBREAK_MODE === 'enforce' && hold) {
// Nothing is reserved for a refused or held checkout.
return res.status(hold[0]).json({ error: hold[1] });
}
return next(); // Watch, or a passed gate: your existing handler reserves the inventory.
}, existingCheckoutHandler);
Note the layered policy. The decision already blocks a proxy, automation, an emulator and a fake or tampered browser, and asks for review on a VPN alone: plenty of real fans use NordVPN, so a review sends them to your verification step, never to a refusal. A checkout that arrived without the browser check is held the same way, and that is where a bot posting straight to the cart endpoint ends up. The attempt counter is yours — key it on device.visitor_id, which stays stable across the IP rotation and incognito windows drop bots rely on. An allowed visitor past eight attempts in a minute is told to try again.
What changes after deployment
After deployment, track these outcomes against a comparable event or holdout cohort:
- Suspected automation share of inventory — compare completed purchases, challenged sessions, and later cancellations.
- Real-user complaints and challenge abandonment — verify that stricter controls do not punish legitimate fans.
- Purchase concentration — measure how many units cluster by device, payment instrument, address, and account group.
- Server load at T-0 — reject high-confidence automation before inventory reservation while preserving a safe retry path.
Get started
Free key at maskbreak.com/signup. The Free plan’s 10,000 visitor checks a month, up to 1,000 an hour, are enough to test against a real drop. Paid plans raise the hourly cap to 50,000 on Scale; bigger on-sale peaks are on Enterprise, with custom volume. The Node SDK is @sentinelsup/sdk.
Update: when the buyer is an agent
Ticketing now has to answer a question this post did not anticipate: what to do when the automation is a fan's own assistant, instructed to buy the moment a sale opens.
That traffic is automated, arrives from cloud infrastructure, and is behaviourally indistinguishable from scalping automation — but it carries a real customer's intent. The distinction cannot be drawn from "is this a bot", so it has to come from what the request is doing and how much of it one origin is doing. Per-origin purchase limits, device-level correlation across accounts, and the strictest gate on the checkout step itself all survive this shift, because they constrain volume rather than automation as such. The agent-traffic piece covers verification; the decision guide covers where to enforce.
Questions people ask
- Will Maskbreak work for sneaker drops, ticket releases, and console restocks all the same?
- Yes. The underlying signals — automation, antidetect browser, proxy (residential pools included), persistent visitor ID — are universal. The policy you apply on top is what differs (e.g. ticket releases often need a queue, sneaker drops need first-second cart-grab protection).
- Won't a strict policy block legitimate fans on VPNs?
- No. A VPN on its own returns review, not block, so in enforce mode a fan on NordVPN gets your verification step, never a refusal. A proxy, automation or a fake or tampered browser is what makes the decision block, and your own attempt counter, keyed on the visitor ID, covers one browser trying checkout again and again within a minute.
- How does Maskbreak hold up at peak traffic — 100,000 visitors hitting at T-0?
- Each check is one server-side call, and each response reports its own processing time. The frontend SDK is asynchronous and adds nothing to your page's interactive time. The Free plan allows 1,000 checks an hour and paid plans raise the hourly cap (Starter 5,000, Growth 20,000, Scale 50,000), so a drop that size is past every self-serve cap and needs an Enterprise plan, agreed with us before the event.
- Can drop-bot operators reverse-engineer Maskbreak?
- The detection logic runs server-side after the SDK collects data, so the actual scoring isn't reachable from the client. The SDK itself ships with active obfuscation that rotates frequently. Operators that try to fake a clean signal usually create new tells in the process — antidetect browsers leave their own fingerprint.
- What does it cost?
- The Free plan includes 10,000 visitor checks a month, up to 1,000 an hour, with no card. Paid plans start at €29 a month (Starter: 50,000 checks a month, up to 5,000 an hour) and go to €299 a month on Scale (1,000,000 checks, up to 50,000 an hour); bigger drops are on Enterprise, from €990 a month. There are no automatic overage charges.
Put the check where the attack enters
One call before signup, login or checkout returns decision, risk_score and the reasons behind them. The Free plan includes 10,000 visitor checks a month, no card required. Start with VPN detection and proxy detection, the network layer most attacks lean on.



