Hey everyone,
I'm building Debatly, an AI debate platform where you can create characters and let different AI models (OpenAI, Anthropic, Google) argue with each other or with you.
Recently I ran into a problem I didn't expect this early: card testing.
What happened
I had a free trial that required a card. Right after I listed Debatly in a few AI and startup directories, I got 500+ trial signups paid with stolen cards. The traffic came mostly from Russia and Belarus, hidden behind VPNs and rotating IPs. The bots were checking whether the cards were valid and burning through trial credits at the same time.
As a quick fix I removed the free trial completely and switched to paid only. It stopped the bleeding, but it also kills conversion for real users, so I don't want this to be the long term answer.
What I'd love to hear from you
Have you dealt with card testing on a small SaaS? What actually worked?
Did tools like Stripe Radar rules, 3D Secure on every payment, or a CAPTCHA (Turnstile, hCaptcha) on signup make a real difference?
Is blocking VPN / datacenter IPs worth it, or does it hurt legit users too much?
Any smarter way to offer a trial without a card (email verification, limited credits, rate limits per device) that bots can't easily farm?
Did directory listings attract this kind of traffic for you too, or was I just unlucky?
I'd really appreciate any war stories, configs or tools you'd recommend. Happy to share what I end up implementing in a follow-up post.
Thanks! 🙏
Top comments (2)
A few things that helped us with the same problem:
Velocity check per IP, not per card. Card-testers burn through many BINs from one IP fast. If you see more than ~5-8 distinct card numbers attempted from the same IP within 10 minutes, flag it. A legitimate user rarely tries more than 1-2 cards.
BIN lookup before hitting the gateway. Free BIN databases (or Stripe's
payment_method_detailsafter first charge) let you reject obviously test BINs (e.g., 400000, 424242, 555555) before you pay the gateway fee. This alone cut our noise by ~70%.Require 3DS on first payment from a new IP. Card-testers almost never complete 3DS because they're scripting. A real user will. This is the single highest-signal filter.
Cloudflare Turnstile or hCaptcha on the payment form. Not reCAPTCHA v3 (too easy to bypass), but a challenge-based one. Card-testers use headless browsers that don't handle the challenge well.
Rate-limit the payment endpoint itself, separate from your API rate limit. Something like 3 attempts per IP per 15 minutes on the charge endpoint.
The combination of 3DS + velocity + BIN filtering got us from ~40% false-positive charges to under 5%. Happy to share our exact Cloudflare rules if useful.
Adding two things the list above doesn't cover. First, the cheapest fix is often removing what they're testing against: a card-required trial with a $0 setup is a free validity check for them. A no-card trial (verified email plus a small usage allowance) gives testers nothing to test. Second, if you keep the card, cap trials per card fingerprint (Stripe gives every card one) as well as per IP, since rotating VPN IPs doesn't change the card. And a burst right after directory listings is a common pattern; those lists get scraped.