PrivCaptcha.com

Card testing and carding prevention at checkout

Stolen card numbers validated in bulk against a live checkout: the checkout is not the target, it is the oracle.

How card testing works at a checkout

The cheap version replays the checkout POST from a cloud host, card number swapped. The funded version drives a real browser through residential proxies.

What card testing looks like in your logs
Authorisation attempts far outnumbering completed orders.
The same basket total repeated with a different card each time.
Long runs of cards sharing the first six digits.

How PrivCaptcha stops card testing

Four steps, with the numbers the server uses. Nothing here is configured by you.

The raw POST is what to close first

Card testers skip the page, so the handler must refuse submissions without a privcaptcha-response. Each token: one card, one verdict.

The driver is scored, per request

Bare client: 20, +40 bot user-agent, +15 no Accept-Language, +10 no Accept = 85, level 5: 19 bits. Driven browser: 20, level 2.

Solving buys the tester slack

Each wrong answer adds 8, capped at +40: five failures take 20 to 60, level 4. Solving subtracts 5, capped at -25.

Per-card cost

One proof-of-work per challenge, bits rising with the score. A nonce covers 3 attempts. Non-visual is a flat 22 bits, 4.2 million hashes.

What a card testing run costs now: Each card needs its own challenge and proof-of-work. At level 4: the target among 10 shapes, the slider within 6 pixels, on every card. The 10-per-second issuance limit is keyed per address. A proxy pool spreads past it.

Add PrivCaptcha to your checkout form in two lines of code

Script tag, container in front of the submit button, and your existing verify call. Already on reCAPTCHA or hCaptcha? That backend code stays exactly as it is.

reCAPTCHA siteverify hCaptcha siteverify
Server SDKs
<!-- checkout form -->
<script src="https://privcaptcha.com/1/api.js" async defer></script>
<div class="privcaptcha" data-sitekey="your-site-key"></div>
<!-- server side, unchanged -->
POST https://privcaptcha.com/api/v1/siteverify
Where it goes

In the checkout form with the card fields, above the pay button.

What the backend does

Read privcaptcha-response from the POST and verify it at /api/v1/siteverify before you call the processor.

The usual mistake

Tokens are single-use: a declined customer needs a fresh widget.

What this does not solve about card testing

PrivCaptcha prices the attempt, it does not judge it: no card number, BIN or decline. Processor-side controls stay necessary.

Common questions about card testing

How PrivCaptcha prices card testing, and what it does not do about it.

A genuine buyer solves one puzzle in a couple of seconds before the submit. The cost lands on volume: an attacker running thousands of authorisations pays the proof-of-work on every single one.
No. The widget sits in front of the submit and the token is verified server-side before you charge. Your existing payment logic is untouched.
Every request is challenged - there is no invisible pass to aim a script at, and no allowlist that skips the check. What changes is the form the challenge takes and what it costs. The server scores each request and picks one of five difficulty levels, so an ordinary visitor gets a couple of seconds and a client that looks automated gets tight tolerances and a heavier proof-of-work. On the non-visual path, taken by screen-reader and keyboard visitors, there is no puzzle to solve at all: the proof-of-work is the whole challenge, at a fixed 22 bits.
No. An address is used for the length of one request and never written anywhere. What we keep is an HMAC of it under a salt that is random, lives only in Redis and rotates every day, so yesterday's hashes cannot be linked to today's. The counters under that hash expire after 24 hours.

Put PrivCaptcha in front of your checkout form

10,000 verifications a month are free, and the integration is the one you already have.