Short answer

A card testing attack is a burst of payment attempts run against your checkout to find out which stolen card numbers still work. The attacker does not want your product. They want the answer your gateway gives back: approved or declined. On Stripe that answer comes back in seconds, and that speed is what turns a merchant's own payment form into a useful testing tool for someone else.

Why Stripe merchants get picked

Most storefronts hand out a publishable API key in the page source, and that key can create and confirm PaymentIntents. If your checkout has no CAPTCHA, no rate limit, and no 3D Secure step, a script can fire hundreds of attempts per minute and every decline is free information. Attacks tend to land on the easiest endpoint you own: a guest checkout, a donation form, a free-trial signup, or an invoice payment page.

Two things make it worse. First, most of those attempts fail, so your successful-charge volume barely moves and nothing looks wrong on a revenue dashboard. Second, the few cards that do work get charged a small amount, and the real cardholder disputes it weeks later.

Warning signs worth watching

  • A jump in authorization attempts with no matching jump in orders.
  • Many different card numbers coming from one IP address, device fingerprint, or email pattern.
  • Repeated identical amounts, often under a dollar or right at your minimum.
  • Decline reasons clustered around do_not_honor, stolen_card, or card_velocity_exceeded.
  • Traffic at hours your customers do not shop.
  • Billing countries that do not match your customer base.

What to turn on in Stripe

Stripe Radar includes a card testing protection setting you can enable, and it blocks attempts that look like automated probing. Past that toggle, the useful levers are:

  • Require CVC and a postal code check on every card payment.
  • Add a Radar rule that blocks when CVC verification fails, and another for postal code failures.
  • Apply 3D Secure to payments that Radar scores as elevated risk.
  • Set velocity rules, such as blocking more than a few attempts from one card or IP in an hour.
  • Turn on CAPTCHA or a bot check at the point where checkout starts.

If you use Checkout or Payment Links, some of this is handled for you. Custom integrations carry more of the burden, and those are the ones attackers prefer because they tend to be less defended.

How to respond in the first hour

Pull the charge attempts from the last 24 hours and group them by IP, card fingerprint, and email. You are looking for one cluster, not a hundred. Block that cluster at your edge, turn on card testing protection if it is off, and add a temporary rule requiring 3D Secure on all payments until the volume drops. Then check your API keys. A leaked secret key lets someone skip your checkout and hit the API directly, and no front-end control helps until you roll it.

Contact Stripe support and use the words "card testing." They see this pattern all the time and can tell you whether the attempts came through your API or your web page. That is the difference between a key leak and a scripted form submission, and it changes your fix.

Costs that show up later

Fraudulent charges turn into disputes, and disputes turn into monitoring programs. Visa and Mastercard both run chargeback monitoring programs with thresholds and fees attached, and a merchant that crosses them pays in more ways than one. Even a small attack can push a low-volume account over the ratio, because the math is based on a percentage, not a raw count.

Prevention habits that hold up

  • Keep your secret key server-side, always, and rotate it if you ever pasted it somewhere.
  • Log every authorization attempt with IP, device, and card fingerprint so you can investigate fast.
  • Watch decline rates weekly, not monthly.
  • Treat any unexplained spike in tiny charges as an incident, not noise.

The pattern is predictable. Attackers find the cheapest path through your payment flow, run it until it stops working, then move on. Close that path before they find it and the whole problem gets boring, which is the goal.