View attachment 53318
Creating Your Own Checker Via Stripe
Checker services are in
absolute shambles right now. Their services are
dropping like flies - either going completely offline or becoming so unreliable they might as well be. The working ones? Theyre either
slow as shit or spitting out more
false declines than actual results. No wonder my inbox is flooded with the same question "How do I make my own checker?"
Well Im finally going to break it all down. Creating your own checker is a complex beast with multiple approaches but were going to tackle it step by step. This guide is the first in a series where well explore different methods starting with the most straightforward one: checking cards via
Stripes API.
Right now youre working with the bare essentials a
Stripe checker that can check a single card at a time; the next guide will amp things up with mass-checking techniques 3DS checks and explorations into other merchant integrations.
Why Stripe Though?
If youve been following my writeups you already know my stance on this: checking via
Stripe is
bad. Not because it "kills" cards - thats technically not true. The real issue is
Stripe's Radar system blacklisting (generic_decline) your cards. Every single card you run through a
Stripe checker gets
flagged as part of a "card testing" attack and good fucking luck using that card on any
Stripe-powered site afterward.
But desperate times call for desperate measures. Maybe youre hitting non-
Stripe sites anyway or you just need a quick validity check. The method still works - just understand what you're getting yourself into.
Stripe API And Binners
View attachment 53321
Those binners we roasted earlier? Turns out theyre the same ones running these "SK checker services" - mostly operated by tech-savvy
Indians whove figured out how to automate their garbage strategy. They manually generate and test bulk cards by scraping e-commerce sites for public
Stripe keys. Same monkey-typewriter approach just with fancier tools.
And its not just
Stripe they're targeting.
Braintree Square any payment processor with public keys exposed on websites gets hammered by these scripts. But we're focusing on
Stripe today because it's the most widespread and their API is actually decent to work with even if these clowns are abusing it.
Here's how Stripe checking works under the hood:
- Tokenization: Your card details get converted into a one-time token
- Payment Method Creation: That token becomes a "payment method"
- Auth Options: You can either just bind the card (no charge) or run a small auth charge ($0.50-$1) to verify funds
Building Your Own Checker
Alright lets get you set up with
Stripe in a way that doesnt leave you looking like a clueless rookie.
1. Prep Your Gear:
- Premium US proxy - Stripes fraud detection will flag cheap proxies instantly. Residential proxies are your best bet here.
- Legit identity details (SSN + DOB). Half-assed fake info is a one-way ticket to account termination.
- Business front browse Flippa.com for a small established e-commerce site. Copy their business model and details - this helps you sail through Stripe's verification process.
- Banking info any plausible routing and account numbers will work since were not actually processing payments. Just make sure the numbers follow the correct format.
2. Setting Up Your Stripe Account:
- Quality fullz (SSN DOB address etc). Bender-Search is my current go-to - their data is accurate and cheap at 50 cents per set. While other vendors exist Benders quality has been consistently solid.View attachment 53323
- Register at stripe.com using an email that you have access to.
- Personal info use the name and DOB from your fullz. The SSN needs to match perfectly.
View attachment 53325
- Business details:
- Bank details:
- When prompted for bank details select "Enter Bank Details Manually" - not doing so will prompt Plaid which we dont want
- Look up a real routing number from a bank in your fullz's city
- Generate a random 10-12 digit account number
- Use the same name as your personal info
- Once verified grab your API keys from the dashboard - youll need these for the checker
3. The Checker Setup:
Back in the day you could simply use your sk_live key and run a
Python script to bust out a token and verify a card. Nowadays,
Stripe isnt that stupid – if you try sending raw credit card numbers directly youll get hit with an error like this:
Code:
{
"charge": null,
"code": null,
"decline_code": null,
"doc_url": null,
"message": "Sending credit card numbers directly to the Stripe API is generally unsafe. To continue processing use Stripe.js, the Stripe mobile bindings, or Stripe Elements. For more information, see https://dashboard.stripe.com/account/integration/settings. If you are qualified to handle card data directly, see https://support.stripe.com/questions/enabling-access-to-raw-card-data-apis.",
"param": null,
"payment_intent": null,
"payment_method": null,
"request_log_url": "https://dashboard.stripe.com/logs/req_21941209",
"setup_intent": null,
"source": null,
"type": "invalid_request_error"
}
Instead of getting away with a direct API call you now must use
Stripes JavaScript frontend to collect and tokenize card details. There are workarounds out there – I'll dive deeper into those in a future guide – but for this surface-level approach were switching to a simple
PHP server setup.
Here's what you need to do:
- Place the following filesin one folder:
- index.html
- validate.php
- composer.json
- Run "composer install" to install the Stripe PHP module.
- Host the folder locally (using XAMPP WAMP or any plain PHP server).
- Open index.html in your browser. It will prompt you for your sk_live and pk_live keys then display a secure Stripe payment field.
- Enter your card details; once submitted the backend (validate.php) uses a Payment Intent to validate the cards legitimacy and returns a response.
Below is the complete code for this setup. (Seriously – dont modify any of this stuff.)
Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Card Validator</title>
<script src="https://js.stripe.com/v3/"></script>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
padding: 20px;
background: #f0f0f0;
}
.card-validator {
max-width: 500px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
h2 {
color: #32325d;
text-align: center;
margin-bottom: 24px;
}
.form-group {
margin-bottom: 16px;
}
label {
display: block;
margin-bottom: 8px;
color: #32325d;
}
input {
width: 100%;
padding: 8px 12px;
border: 1px solid #e4e4e4;
border-radius: 4px;
font-size: 16px;
margin-bottom: 16px;
}
.card-element {
padding: 12px;
border: 1px solid #e4e4e4;
border-radius: 4px;
margin-bottom: 16px;
}
button {
background: #5469d4;
color: white;
padding: 12px 24px;
border: none;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
width: 100%;
}
button:disabled {
background: #93a3e8;
cursor: not-allowed;
}
.status {
margin-top: 16px;
padding: 12px;
border-radius: 4px;
text-align: center;
}
.error {
background: #fee;
color: #ff0000;
}
.success {
background: #e8ffe8;
color: #008000;
}
</style>
</head>
<body>
<div class="card-validator">
<h2>Card Validator</h2>
<div id="setup-form">
<div class="form-group">
<label>Secret Key (sk_live):</label>
<input type="text" id="sk_live" required>
</div>
<div class="form-group">
<label>Public Key (pk_live):</label>
<input type="text" id="pk_live" required>
</div>
<button onclick="setupStripe()">Continue</button>
</div>
<div id="card-form" style="display: none;">
<form id="payment-form">
<div class="form-group">
<label>Card Details:</label>
<div id="card-element" class="card-element"></div>
</div>
<button type="submit" id="submit-button">Validate Card</button>
</form>
<div id="status" class="status" style="display: none;"></div>
</div>
</div>
<script>
let stripe;
let elements;
let card;
let sk_live;
function setupStripe() {
const pk_live = document.getElementById('pk_live').value;
sk_live = document.getElementById('sk_live').value;
if (!pk_live || !sk_live) {
alert('Please enter both keys');
return;
}
stripe = Stripe(pk_live);
elements = stripe.elements();
card = elements.create('card');
document.getElementById('setup-form').style.display = 'none';
document.getElementById('card-form').style.display = 'block';
card.mount('#card-element');
}
document.getElementById('payment-form').addEventListener('submit', async function(e) {
e.preventDefault();
const submitButton = document.getElementById('submit-button');
const statusDiv = document.getElementById('status');
submitButton.disabled = true;
submitButton.textContent = 'Processing...';
statusDiv.style.display = 'block';
statusDiv.textContent = 'Validating card...';
statusDiv.className = 'status';
try {
const { paymentMethod, error } = await stripe.createPaymentMethod({
type: 'card',
card: card,
});
if (error) {
throw error;
}
const response = await fetch('validate.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
payment_method_id: paymentMethod.id,
secret_key: sk_live,
}),
});
const result = await response.json();
if (result.error) {
throw new Error(result.error);
}
// Handle 3D Secure authentication if required
if (result.requires_action) {
statusDiv.textContent = 'Additional authentication required...';
const { error: confirmError } = await stripe.confirmCardSetup(
result.client_secret
);
if (confirmError) {
throw confirmError;
}
statusDiv.textContent = 'Card is Live! ✅';
statusDiv.className = 'status success';
return;
}
let message = '';
switch (result.status) {
case 'succeeded':
message = 'Card is Live! ✅';
break;
case 'processing':
message = 'Card validation is still processing...';
break;
case 'requires_action':
message = 'Card requires additional verification.';
break;
default:
message = `Card validation status: ${result.status}`;
}
statusDiv.textContent = message;
statusDiv.className = result.success ? 'status success' : 'status error';
} catch (error) {
statusDiv.textContent = `❌ Declined: ${error.message}`;
statusDiv.className = 'status error';
} finally {
submitButton.disabled = false;
submitButton.textContent = 'Validate Card';
}
});
</script>
</body>
</html>
Code:
<?php
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit();
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
exit();
}
require_once '../vendor/autoload.php';
// Ensure the input is valid JSON before decoding
$rawInput = file_get_contents('php://input');
if (!isValidJson($rawInput)) {
http_response_code(400);
echo json_encode(['error' => 'Invalid JSON input']);
exit();
}
$input = json_decode($rawInput, true);
$payment_method_id = $input['payment_method_id'] ?? null;
$secret_key = $input['secret_key'] ?? null;
if (!$payment_method_id || !$secret_key) {
http_response_code(400);
echo json_encode(['error' => 'Missing required parameters']);
exit();
}
// Helper function to validate JSON
function isValidJson($string) {
json_decode($string);
return json_last_error() === JSON_ERROR_NONE;
}
try {
\Stripe\Stripe::setApiKey($secret_key);
// Create a SetupIntent and confirm it with the payment method
$setup_intent = \Stripe\SetupIntent::create([
'payment_method' => $payment_method_id,
'confirm' => true,
'usage' => 'off_session',
'return_url' => 'https://crdpro.cc',
'automatic_payment_methods' => [
'enabled' => true,
'allow_redirects' => 'never'
]
]);
// Check the status
$status = $setup_intent->status;
$success = in_array($status, ['succeeded', 'requires_action', 'processing']);
// If 3D Secure authentication is required
if ($status === 'requires_action' || $status === 'requires_source_action') {
echo json_encode([
'success' => false,
'status' => $status,
'setup_intent' => $setup_intent->id,
'client_secret' => $setup_intent->client_secret,
'requires_action' => true
]);
exit();
}
echo json_encode([
'success' => $success,
'status' => $status,
'setup_intent' => $setup_intent->id
]);
} catch (\Exception $e) {
http_response_code(400);
echo json_encode([
'error' => $e->getMessage(),
'type' => get_class($e)
]);
}
[code]composer.json:
Code:
{
"require": {
"stripe/stripe-php": "^13.0"
}
}
*** Hidden text: cannot be quoted. ***
Once everything's setup properly:
Some Other Stuff To Remember
The whole deal with
binding versus
auth is simple. Binding merely creates a payment method which is like filing away your card details without much fanfare. Auth on the other hand actually attempts to charge a tiny amount (think $0 or a few bucks) to verify the card. It gives you better clarity on whether a card is active but it also leaves a more noticeable trace and risk of killing the card.
When it comes to account management
Stripe is
merciless. The moment you start running patterns that look sketchy theyll slam the brakes and nuke your account. Your best bet? Rotate through multiple
Stripe accounts use different IP addresses for each and keep your card-checking volume within reasonable limits. Don't be the idiot who thinks running a mountain of tests on a single account is a good idea.
Finally error handling is your lifeline. Learn how to dissect each error message—sometimes it means the card is toast; other times it's just
Stripe being a stubborn bitch. Either way understanding these messages means you can adjust your approach on the fly.
This isn't rocket science but if you ignore these pointers youll be stumbling around like a rookie. Use these strategies to stay a step ahead and remember: the devil's in the details.
More To Come
This is just the beginning of our checker creation series as such it is extremely basic and simple. We've started with the training wheels version -
Stripe API checking. In upcoming guides well dive into the real shit: building your own auth systems and mass checker working with different payment processors, creating your own Telegram CC Checker bot, etc, and creating checkers that actually give you useful data beyond "valid/invalid."
Remember: A checker is only as good as its operator. Don't be the dipshit running 10,000 cards through one
Stripe account and wondering why it got banned. Start small understand the mechanics and scale up smart.
Stay tuned for the next guide in this series. Were going to get into the specifics of building checkers that actually deserve to be called tools not toys. d0ctrine out.