Card Testing Attacks: How Bots Drain Stripe Accounts in 2026

Card testing bots verify stolen cards with micro-charges before selling them. Learn how they evade Stripe Radar and how to stop them server-side.

Close-up of a payment card's metal chip, contactless symbol and embossed digits.
Photo: Credit Card Chip by kuhnmi, CC BY 2.0, cropped. Via Wikimedia Commons.
On this page
  1. What Card Testing Actually Is
  2. The Mechanics: How Card Testing Bots Operate
  3. What the Economics Look Like — For Both Sides
  4. The Signals That Betray Card Testing Bots
  5. Why Stripe Radar Alone Is Not Enough
  6. How Maskbreak Stops Card Testing Before It Reaches Stripe
  7. Building a Layered Defense
  8. Update: card testing through a clean-looking front end

One morning in Q3 2024, the fraud team at a mid-size e-commerce company opened their Stripe dashboard to find 1,847 failed payment attempts from the previous night, all between 2:00 AM and 4:30 AM. Charge amounts clustered tightly between $0.50 and $1.50. The billing addresses hit all 50 US states. No two shared an IP address. By the time their on-call engineer was awake, Stripe had already flagged the account for an elevated dispute rate — and suspended same-day payouts.

That's a card testing attack. And it's getting harder to stop, not easier.

What Card Testing Actually Is

Card testing — also called carding verification or BIN attacks — is the process of using automated scripts to verify whether stolen payment card numbers are still active. Fraudsters acquire card data in bulk: from data breaches, dark-web dumps, phishing kits, or skimmer networks. Raw stolen card data is nearly worthless on its own because a significant fraction of cards in any dump have already been cancelled, expired, or flagged by issuing banks.

The economic logic is cold and precise. A live, verified card sells for $5 to $50 on fraud marketplaces depending on card type, credit limit, and whether it has a verified billing address (AVS match). A dead card is worth $0.10 or less — barely worth the bandwidth to transmit. So before selling or using a batch of 50,000 stolen card numbers, the fraudster runs them through a checker: a bot that makes small charges against a real merchant's checkout to see which ones succeed.

The verification cost per card is typically a fraction of a cent. The upside of finding a live card is $5–$50. The economics are overwhelmingly favorable — which is why the volume is enormous.

The Mechanics: How Card Testing Bots Operate

Modern card testing operations have professionalized over the past three years. The tools are sophisticated, the infrastructure is rented, and the bots are optimized to evade exactly the defenses most merchants have in place.

Step 1 — Acquiring card databases. Operators buy BIN (Bank Identification Number) lists and full card dumps from automated dark-web shops like the now-defunct BidenCash marketplace and its successors. A typical batch purchase is 10,000–100,000 card records, priced at $0.10–$1.00 each unverified.

Step 2 — Selecting a target merchant. The ideal target has a public-facing checkout, no CAPTCHA, low order minimums, and a donation or "pay what you want" flow where small arbitrary amounts are accepted. Nonprofit donation pages are notoriously overrepresented. So are SaaS checkout flows and marketplace top-up systems.

Step 3 — Routing through residential proxies. This is the move that defeats most IP-based defenses. Services like BrightData and similar networks route each request through a different real home IP address — the kind that belongs to an actual household broadband subscriber in Des Moines or Phoenix. Stripe Radar's IP reputation signals see what looks like a normal customer. IP rate-limiting by address is useless when the address changes every request.

Step 4 — Rotating device fingerprints. Antidetect browsers (Kameleo, GoLogin, AdsPower, Multilogin) generate a fresh browser fingerprint per session: a different canvas hash, WebGL renderer string, screen resolution, timezone, installed fonts, and user-agent string. Standard device fingerprinting that would catch a bot re-using the same device profile fails when every profile looks unique.

Step 5 — Timing and volume randomization. Naive bots fire a fixed number of requests per second, making burst detection trivial. Sophisticated operators introduce jitter — randomized inter-request delays between 200ms and 8 seconds — and spread attempts across a multi-hour window. Some operations now use "low-and-slow" strategies: 3–5 card tests per hour, sustained over days, staying well below any fixed rate threshold.

Try it

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 check

What the Economics Look Like — For Both Sides

Understanding the fraud economics explains why this problem won't go away by itself.

On the attacker's side, a batch of 50,000 unverified card numbers costs roughly $5,000–$50,000 to acquire. Running them through a card checker using residential proxy bandwidth costs maybe $200–$500 in proxy fees plus verification charges. If 8% of cards come back live (a realistic figure for fresh dumps), that's 4,000 live cards. Sold at an average of $15 each, revenue is $60,000 — a comfortable margin even before using the cards directly for fraud purchases.

On the merchant's side, the costs pile up whether or not any charge succeeds:

  • Authorization fees: Stripe charges $0.05–$0.10 per authorization attempt, including declined ones. A 10,000-attempt attack costs $500–$1,000 in fees alone.
  • Dispute fees: Every successful fraudulent charge that results in a chargeback costs $15 on Stripe. If 200 charges succeed and are later disputed, that's $3,000 in dispute fees on top of the reversed revenue.
  • Account risk: Stripe's dispute threshold sits around 0.75% of transaction volume. Breaching it means enhanced monitoring, payout delays, and — in repeat cases — account termination. Losing a Stripe account mid-growth is a company-threatening event.
  • Engineering time: A fraud team reacting to a card testing incident typically spends 8–20 hours investigating, adding rules, and cleaning up. At $150/hr fully loaded, that's $1,200–$3,000 per incident.

The Signals That Betray Card Testing Bots

Despite the sophistication of modern card testing infrastructure, these operations leave a behavioral fingerprint that's detectable — if you're looking at the right signals.

Burst timing with jitter patterns. Even randomized delays cluster statistically. A human checking out makes one or two attempts over several minutes with irregular pauses. A bot producing Poisson-distributed inter-request times at high volume creates a distinct statistical signature when you look at the session-level distribution across a cohort of sessions.

IP clustering despite residential routing. Residential proxy networks have finite pools in any given city or ASN. An attack using 500 residential IPs will often show geographic clustering — 40 IPs all in the same /16 subnet of a major ISP, or temporal clustering where the same proxy IP reappears across multiple sessions within the same hour window.

Device fingerprint reuse beneath antidetect obfuscation. Antidetect browsers randomize surface fingerprints but leave lower-level traces: WebGL shader precision errors that are consistent across a vendor's browser build, AudioContext fingerprints that cluster by browser engine version, and CSS font rendering metrics that don't match the declared OS. These sub-surface signals are far harder to spoof convincingly at scale.

Velocity on persistent visitor ID. A visitor ID built to survive private windows, cleared cookies and IP changes reveals the same underlying device making attempt number 47 through IP address number 47. No legitimate customer makes 47 payment attempts in 6 hours.

Checkout behavior anomalies. Real customers read product pages, spend time on cart pages, and exhibit micro-interactions (mouse movement, scroll depth, focus events on form fields) that bots either skip entirely or emulate imperfectly. A checkout session where a payment form is submitted 0.8 seconds after page load, with no mouse movement and no field focus events, is not a human.

Why Stripe Radar Alone Is Not Enough

Stripe Radar is a card-level fraud model. It ingests card number, BIN, billing ZIP, CVV match result, and card velocity across the Stripe network. It is genuinely good at what it does — and it improves constantly as Stripe's transaction volume grows.

But Radar has a fundamental architectural constraint: it only sees signals that exist at the moment a payment_intent is created. It does not see:

  • Whether the browser session is an antidetect browser with a spoofed fingerprint
  • Whether the IP resolves to a residential proxy network's exit node
  • Whether the same underlying device has made 40 payment attempts in the past hour under different IPs
  • Whether the checkout page interaction pattern is consistent with human behavior

These are application-layer signals, not payment-layer signals. By the time Radar sees a request, it's already become a Stripe API call — meaning you've already paid the authorization fee, and the card's decline has already been logged against your merchant account's health score.

So the best card testing defense is not a better fraud model at the payment layer. It is making sure bot traffic never creates a payment intent in the first place.

How Maskbreak Stops Card Testing Before It Reaches Stripe

Maskbreak sits at the application layer, in front of your checkout, checking each payment attempt before your backend calls Stripe. The architecture is two components:

A browser script (<script async src="https://maskbreak.com/assets/sentinel.js"></script>) on your checkout page. Put class="monocle-enriched" on the checkout <form> itself, and the script adds three hidden fields to it while the customer fills it in: monocle (a network token for the customer's own connection), sentinel_fp (the browser check: automation, emulators, tampered or fake browsers) and sentinel_tz (the time zone). A checkout your JavaScript submits gets the same values from await window.Sentinel.collect().

A server-side evaluate call that your backend makes before creating any Stripe object, forwarding those three fields as token, fingerprintEventId and tz. The answer is a decision (allow, review or block), a risk score, the reasons behind it and, when the browser check ran, a visitor ID you can count payment attempts against.

Here is the integration before a Stripe charge. It starts in watch mode, where every attempt 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:

javascript
// Node.js / Express: before stripe.paymentIntents.create
const MODE = process.env.MASKBREAK_MODE || 'watch';   // 'watch' or 'enforce'

app.post('/pay', express.urlencoded({ extended: false }), express.json(), async (req, res, next) => {
  const b = req.body || {};
  let verdict = null;
  try {
    // Sent on every payment attempt, even when a field is missing.
    const r = await fetch('https://maskbreak.com/v1/evaluate', {
      method: 'POST',
      headers: {
        Authorization: 'Bearer ' + process.env.MASKBREAK_API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        token: b.monocle || b.token || '',                                     // the network token
        fingerprintEventId: b.sentinel_fp || b.fingerprintEventId || undefined, // the browser check: device.* signals
        tz: b.sentinel_tz || b.tz || undefined,
      }),
      signal: AbortSignal.timeout(3000),
    });
    if (r.ok) verdict = await r.json();
    else console.warn('[maskbreak] HTTP', r.status);
  } catch (err) {
    console.warn('[maskbreak] unavailable:', err.name);   // no verdict: the payment flow continues
  }
  console.log('[maskbreak]', JSON.stringify({
    mode: MODE,
    decision: verdict ? verdict.decision : null,
    reasons: verdict ? verdict.reasons : null,
    device_evidence: verdict ? verdict.device_evidence : null,
    degraded: verdict ? !!verdict.degraded : null,
  }));

  try {
    if (MODE === 'enforce') {
      // A proxy, automation, an emulator or a fake or tampered browser is
      // what makes the decision block; a block never reaches Stripe.
      if (verdict && verdict.decision === 'block') {
        return res.status(402).json({ error: 'payment_declined' });
      }
      // Cross-session velocity: key your own attempt counter (e.g. Redis)
      // on the visitor ID the browser check returns.
      const visitorId = verdict && verdict.device ? verdict.device.visitor_id : null;
      if (visitorId && await recentPaymentAttempts(visitorId) > 10) {
        return res.status(429).json({ error: 'too_many_attempts' });
      }
    }

    // Proceed to Stripe, with the amount from your own cart, never from the request.
    const intent = await stripe.paymentIntents.create({
      amount: await cartTotalFor(req),
      currency: 'usd',
      // ... rest of your Stripe params
    });
    res.json({ clientSecret: intent.client_secret });
  } catch (err) {
    next(err);   // Express 4 does not catch a rejected promise: an uncaught one ends the process
  }
});

The response gives you enough granularity to tune your policy. A customer on a commercial VPN with a clean browser comes back as review, not block; a proxy, automation or a fake browser is what turns the answer into block.

In enforce mode this sketch declines a block and lets a review, or a check that did not answer, go on to Stripe, where Radar and 3D Secure still apply. The stricter policy in the Stripe notes pauses a review or an unavailable check as well; choose it for payments you cannot step up.

Evaluate the control with a staged rollout. Track authorization attempts per device, issuer-decline rate, challenge rate, confirmed fraud, chargebacks, and false positives. Compare against a holdout or the same traffic segment before deployment rather than assuming a universal reduction.

Building a Layered Defense

Card testing defense works best as a layered system, with each layer doing what it's architecturally suited for:

  1. Cloudflare / WAF rules — drops unsophisticated bots using known bad ASNs and obvious attack patterns. Catches known infrastructure and obvious request patterns.
  2. Maskbreak (application layer) — flags proxies (residential ones included), VPNs, Tor, automation, emulators and tampered or fake browsers, and returns a visitor ID your own counter can measure velocity against. Adds the device and connection context that a network-only rule may miss.
  3. Stripe Radar rules — catches card-level signals: BIN velocity, billing address mismatches, issuer-level risk scores. Handles the fraud that slips through the upstream layers.
  4. 3D Secure (3DS2) — for anything Radar scores above your threshold, trigger SCA. This pushes liability to the card issuer on successful charges, eliminating your chargeback exposure even if a live card transacts.

The goal is to ensure Stripe Radar is only processing sessions that have already cleared application-layer checks. When you stop feeding Radar with junk traffic, its signal-to-noise ratio improves — and your legitimate customer conversion stays clean.

Update: card testing through a clean-looking front end

The pattern to add since publication is card testing routed through residential exits and driven by a real browser rather than a script. Every network signal reads consumer-grade, the browser environment is genuine, and the velocity is deliberately throttled to stay under per-minute thresholds.

Velocity rules alone will not see it, because the whole design is to stay beneath them. What does surface it is correlation across attempts that look unrelated at the address level: one device environment behind many card numbers, or many addresses behind one device. Pair that with protocol-layer consistency checks — a residential address running a non-browser TLS stack is a contradiction worth acting on — and the pattern becomes visible again. The residential-network guide and TLS fingerprinting cover both halves.

Questions people ask

What's the difference between card testing and carding?
Card testing (also called a BIN attack or card verification) is the process of making small charges to verify whether stolen card numbers are still active. Carding is the broader term for using verified stolen cards to make fraudulent purchases. Card testing is the first step in the carding workflow — it sorts live cards from dead ones before they're used or sold on fraud markets.
Why do fraudsters target small merchants instead of large retailers?
Large retailers have dedicated fraud teams, sophisticated ML models, velocity rules, and often 3DS2 enforcement. Small merchants frequently have none of these — just default Stripe Radar settings. They're also less likely to notice a card testing event until Stripe flags them. Donation pages, nonprofit checkouts, and small SaaS payment flows are particularly targeted because they accept arbitrary small amounts with minimal friction.
Will blocking residential proxies hurt legitimate international customers?
A detected proxy, residential or not, makes the decision block by default, because it hides the connection a payment really comes from; a commercial VPN on its own comes back as review. If some of your genuine customers do reach you through a proxy, such as a corporate gateway, set the Proxy rule to Review in the console's Rules tab and step those payments up instead of declining them. Run in watch mode first, so you can see how often that happens before anything is refused.
How quickly can a card testing attack escalate?
Fast. Once a script finds a low-friction checkout it can send attempts as quickly as your checkout answers, so a run can trip a payment provider's decline or dispute thresholds before anyone responds by hand. That is why the check belongs before the charge and runs automatically, rather than in a manual review after the fact.

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.

Get started freeRead the API docs