How-to guide

    How to Stop Card Testing on Magento 2

    Bots Trying Stolen Cards at Your Checkout, and What Actually Works

    By Simon Bumford, Founder of EveryHost••12 min read

    TL;DR

    Card testing is when bots push stolen card numbers through your checkout to find out which ones still work. Even when most attempts fail, it can cost you fees, disputes and a higher decline rate on genuine orders. Most of the defence sits in two places. The first is Magento itself, where Google reCAPTCHA on checkout and, from 2.4.7, rate limiting for placing orders both cover the REST and GraphQL routes that scripts call directly. The second is your payment gateway, where card verification and velocity rules catch much of the rest. Hosting helps by spotting the pattern in the server logs and blocking abusive IP addresses, but IP blocking alone will not stop a determined attack. Turn the Magento settings on, tighten the gateway rules, and refund anything fraudulent that got through.

    What card testing is, and why failed payments still hurt

    Card testing, also called carding, is fraud aimed at your checkout rather than your stock. Someone holding a list of stolen or guessed card details uses a script to try them against a real store, usually with small payments or card checks, to find out which cards are still live. The valid ones are then used elsewhere or sold on. Your store is simply a convenient testing ground, and a Magento checkout, like any online checkout, can be driven by a script.

    The damage is not limited to the payments that succeed. Stripe's guidance on card testing lists the knock-on effects: disputes when cardholders notice the test payments that went through, a higher decline rate that can make card issuers treat all of your transactions as riskier, possible extra fees depending on your pricing plan, and extra load on your infrastructure from all the requests. Your order data suffers too, because a wave of fake guest orders looks like new customers until someone cleans it up.

    How to tell it is happening

    Most attacks are obvious once you know where to look. The signs usually show up in three places.

    • In your payment gateway: a sudden spike in failed or declined payments, often at low values, well above your normal decline rate.
    • In Magento: bursts of guest checkouts with nonsensical names or email addresses and small totals. If your payment method reports failures back to Magento, you can have a copy of each payment failure email sent to your team under Stores > Settings > Configuration > Sales > Checkout > Payment Failed Emails, which makes a sudden burst hard to miss.
    • In your server logs: the checkout's payment endpoints hit over and over, such as /rest/V1/guest-carts/{cartId}/payment-information or /graphql, sometimes from many different IP addresses. Scripts can call these endpoints directly without ever loading your checkout page, which is why the Magento protections below cover them too.

    If you are under attack right now

    1. Turn on Google reCAPTCHA for checkout (Fix 1 below). It is the quickest Magento-side brake.
    2. If you run Magento 2.4.7 or later, switch on rate limiting for placing orders (Fix 2).
    3. Tighten your payment gateway's fraud rules: card verification (CVV) and address (AVS) checks, and any velocity limits your plan offers (Fix 3).
    4. If the attempts all come through guest checkout, consider switching it off for now (Fix 4).
    5. Check with your payment provider that 3-D Secure is switched on (Fix 5), and ask whoever runs your server about a rate limit on the payment routes (Fix 6).
    6. Refund any fraudulent payments that succeeded before the cardholders dispute them. Stripe recommends this to avoid disputes.
    7. Tell your payment provider and whoever looks after your server, so they can check their side too.

    Fix 1: Google reCAPTCHA on checkout

    Magento 2.4 includes Google reCAPTCHA. Get your keys free from Google's reCAPTCHA admin console, add them under Stores > Configuration > Security > Google reCAPTCHA Storefront, then choose where to use them. For card testing, the setting that matters is Enable for Checkout/Placing Order. Adobe recommends invisible reCAPTCHA v3, which scores each interaction in the background against a minimum score threshold that defaults to 0.5.

    The important detail is that this one setting does not only protect the checkout page. According to Adobe's developer documentation, it also protects the guest REST endpoints that take payment information and the GraphQL mutations that set a payment method and place an order. Scripts that call those routes directly must then send a valid reCAPTCHA token in an X-ReCaptcha header.

    Two cautions. If you run a headless or PWA storefront, it has to send that header too, or genuine customers will fail at checkout, so test a real order on staging before you switch it on in production. And if attempts keep getting through, Stripe's advice on CAPTCHA applies here as well: adjust the score threshold, or switch from an invisible check to a visible one.

    While you are in that section, turn it on for Create New Customer Account and Customer Login too, which makes it harder to script fake accounts. If you take card payments through PayPal Payflow Pro, there is a separate Enable for PayPal PayflowPro payment form option in the same place.

    Fix 2: Rate limiting for placing orders (Magento 2.4.7 and later)

    Magento 2.4.7 added a rate limit on the payment information sent through REST and GraphQL, and Adobe's release notes say it is there to help prevent carding attacks that test many card numbers at once. It is off by default.

    Step 1: configure the backpressure logger. The rate limit has to keep count somewhere, and Adobe's rate limiting documentation makes this the first step: point Magento's backpressure logger at Redis or Valkey from the command line.

    # Example values: use your own Redis or Valkey host, port and a spare database number
    bin/magento setup:config:set \
        --backpressure-logger=redis \
        --backpressure-logger-redis-server=127.0.0.1 \
        --backpressure-logger-redis-port=6379 \
        --backpressure-logger-redis-db=3

    Use the host and port of your own Redis or Valkey server. Adobe says the database option is required if you already use Redis for both the default cache and the full-page cache, so pick a database number they do not use. Optional flags cover the timeout, persistent connections, a password, a user and a key prefix. The command writes the settings to app/etc/env.php under backpressure. If your store is managed for you, this step is one for your host.

    Step 2: switch it on in the admin. Go to Stores > Configuration > Sales > Sales > Rate Limiting. Set Enable rate limiting for placing orders to Yes, then review the two limits: Requests limit per guest (default 50) and Requests limit per authenticated customer (default 10), counted over the period you choose in Counter resets in a (minute, hour or day). Magento counts guests by their IP address and logged-in customers by their account, so several genuine shoppers behind one shared IP address, such as an office network, count as one guest. Think about how many order attempts a genuine customer of yours makes in a short period and set the guest limit with some headroom above that. A trade buyer placing lots of small orders is not a bot, so check against your own order history before tightening it. Once a limit is reached, the REST routes answer with 429 Too Many Requests and GraphQL returns a Too Many Requests error.

    If you are still on 2.4.6 or earlier, this setting does not exist. 2.4.6 is also out of support, so the rate limit is one more reason to plan the upgrade covered in our Magento 2.4.6 end of life guide.

    Fix 3: Your payment gateway does the heavy lifting

    Magento's settings slow the scripts down. Your payment gateway is where much of the card testing is actually caught, because it sees the card details and the card issuer's response. What to look at depends on your provider.

    • Stripe: its card testing protections, including automated CAPTCHA and rate limits, work best with its recommended integrations, and Stripe says their success depends on the risk data your integration sends, such as the customer's IP address, email, name and billing address. Radar can block payments that fail CVC checks, and plans that support custom rules let you add velocity rules. Keep your Stripe extension up to date and ask your developer to confirm it sends that data.
    • PayPal Braintree: the Basic Fraud Tools include AVS, CVV and risk threshold rules. Braintree says they are available at no extra cost to all merchants, need no developer work to set up and help protect against carding. Check they are switched on and set to reject payments when the CVV does not match.
    • Other gateways: look for the same things: card verification (CVV) and address (AVS) checks, velocity or rate rules, and a way to challenge suspicious payments. PayPal's own guidance on carding attacks lists AVS and CVV checks, reCAPTCHA, velocity limits and hidden honeypot fields among the main checkout defences.

    Stripe makes a point that applies to every provider: if you are not a developer or you use a plugin, most card testing fixes need code or configuration changes, so share your provider's guidance with whoever built or maintains your checkout.

    Fix 4: Make the checkout harder to reach

    The easier it is to reach your payment form, the easier it is to abuse. Stripe notes that guest checkout makes card testing easier, and that requiring a login or a validated session reduces your exposure. In Magento you can switch guest checkout off at Stores > Settings > Configuration > Sales > Checkout > Checkout Options by setting Allow Guest Checkout to No.

    That has a real cost, because some genuine customers will not create an account to buy. Treat it as an emergency brake during an attack rather than a permanent setting, and pair it with reCAPTCHA on account creation so the scripts cannot simply register their way round it.

    Fix 5: 3-D Secure and Strong Customer Authentication

    3-D Secure (3DS) adds a step in which the cardholder's bank authenticates the payment. Stripe's 3D Secure documentation says it protects businesses from liability for fraudulent card payments, and that Strong Customer Authentication rules, part of PSD2 in the EEA and similar regulations in the UK, might require 3DS for card payments anyway.

    It is worth having on, but it does not stop card testing by itself: Stripe's card testing guidance notes that testers can still collect 3DS or issuer responses to learn which cards are live. Keep the rate limits and gateway rules as well. 3DS is set up in your payment provider's account and its Magento extension rather than in core Magento, so check with your provider how it is triggered for your store.

    Fix 6: Rate limits at the web server or CDN

    Magento's own rate limit works inside Magento. You can also cap the payment routes before requests reach PHP, at the web server or at a CDN such as Cloudflare. The routes to cover are the ones Adobe's rate limiting applies to: the guest and logged-in payment-information and order routes under /rest, and /graphql. On nginx, as general advice to adapt rather than paste, it can look like this:

    # Example only. In the http { } block: give the payment routes Adobe rate limits
    # a key per client IP. Every other request gets an empty key, which limit_req ignores.
    map $uri $magento_payment_key {
        default "";
        "~^/rest/(?:[^/]+/)?V1/(?:guest-carts/[^/]+|carts/mine)/(?:payment-information|order)$" $binary_remote_addr;
    }
    map "$request_method:$uri" $magento_graphql_key {
        default "";
        "~^POST:/graphql$" $binary_remote_addr;
    }
    limit_req_zone $magento_payment_key zone=mage_payment:10m rate=6r/m;
    limit_req_zone $magento_graphql_key zone=mage_graphql:10m rate=120r/m;
    
    # In your Magento server { } block:
    limit_req zone=mage_payment burst=5 nodelay;
    limit_req zone=mage_graphql burst=60 nodelay;
    limit_req_status 429;

    Set the numbers well above what a genuine shopper does: a customer retrying a declined card a few times should never reach them. Treat /graphql with care, because on Hyva and headless (PWA) storefronts it can carry far more than payments, so give it plenty of headroom and test a full browse-to-order journey on staging. If your store sits behind Cloudflare or another proxy, set up nginx's real IP module first, or every visitor will appear to come from the proxy's addresses and share one counter.

    On Cloudflare, a rate limiting rule does the same job at the edge, counting requests per IP address. Every plan can match a rule on the URL path, which covers the REST payment routes; the Free plan allows one rule with a 10-second counting period. Matching on the request method, so that only POST requests to /graphql are counted, needs the Business plan or above.

    Where your hosting helps, and where it does not

    It is worth being clear about this. The Magento settings and your payment gateway do most of the work against card testing. Hosting helps around them in two ways.

    First, an attack leaves tracks in the web server logs: the same payment endpoints hit over and over. On EveryHost plans, Sentinel security monitoring reads those logs and can automatically block abusive IP addresses at the server firewall, and our engineers review every block, so a genuine customer caught by mistake can be let back in. Second, the people looking at those logs are Magento engineers, so when the pattern appears they can help you switch on reCAPTCHA and rate limiting, check your Magento version supports them, and point you at the gateway settings above.

    What hosting cannot do is stop card testing on its own. Stripe's guidance says plainly that filters based on a single signal such as IP address are usually not enough, because card testers use many techniques to get round them. Blocking abusive IPs raises the cost of an attack; it does not replace reCAPTCHA, rate limiting and your gateway's fraud rules. Sentinel cannot see inside your payment provider either, and it is no substitute for keeping Magento patched.

    If you want those engineers watching your logs, and a stack kept current enough to use the protections above, our managed Magento VPS hosting includes Sentinel and a UK team who work only on Magento.

    Frequently Asked Questions

    Card testing, also called carding, is when someone uses a script to try stolen or guessed card details against your checkout, usually with small payments or card checks, to find out which cards still work. Your store is the testing ground, not the real target. The valid cards are then used or sold elsewhere, while you are left with failed payments, possible disputes and a messier order history.

    Because the damage goes beyond the payments that succeed. Depending on your payment provider and pricing plan, authorisation attempts can carry fees, and any test payment that does succeed can turn into a dispute with its own fee. A large number of declines can also make card issuers treat your genuine transactions as riskier, which can raise your decline rate for real customers after the attack has stopped.

    It helps, but it is one layer rather than the whole answer. In Magento, the Enable for Checkout/Placing Order setting also protects the guest REST payment endpoints and the GraphQL payment mutations that scripts can call directly. If attempts still get through, adjust the score threshold or switch to a visible check, and combine reCAPTCHA with rate limiting and your payment gateway's fraud rules.

    Yes, from Magento 2.4.7. First configure the backpressure logger that keeps the request counts, with bin/magento setup:config:set --backpressure-logger=redis and your Redis or Valkey connection details. Then go to Stores > Configuration > Sales > Sales > Rate Limiting and set Enable rate limiting for placing orders to Yes, because it is off by default. You can then set how many purchase requests a guest and a logged-in customer can make per minute, hour or day. The defaults are 50 for guests, counted per IP address, and 10 for logged-in customers, so review them against your own trade. Adobe documents it as covering the REST and GraphQL routes that take payment information and place orders.

    It can help during an active attack, because it makes the payment form harder to reach, but it also turns away some genuine customers who will not create an account. Use it as a temporary brake: set Allow Guest Checkout to No under Stores > Settings > Configuration > Sales > Checkout > Checkout Options, turn on reCAPTCHA for account creation at the same time, and switch guest checkout back on once the attack has died down and your other protections are in place.

    Not on its own. A host can spot the pattern in the server logs and block abusive IP addresses, which raises the cost of an attack, but card testers use many techniques to get round simple IP blocks. On EveryHost plans, Sentinel reads the server logs and can automatically block abusive IPs, with our engineers reviewing every block, and those engineers can help you set up the Magento and payment gateway protections that do most of the work.

    Sources and further reading

    Seeing card testing on your store?

    Our UK Magento engineers can look at your server logs with you, help you switch on the Magento protections above and check your version supports them. Sentinel security monitoring is included on every plan.