Type a card number into a checkout form with one digit wrong, and most sites tell you it's invalid before anything is sent to the bank. That instant check is the Luhn algorithm, a simple checksum from the 1950s that's still built into almost every payment card number.
Here's how a card number is structured, how the Luhn check works step by step, and, just as important, what it can't tell you.
What's in a card number
Payment card numbers, formally called primary account numbers (PANs), follow the international standard ISO/IEC 7812-1. They're usually 15 to 16 digits, though the range runs from 12 to 19, and have three parts:
- Issuer identification number (IIN): the leading digits, which identify the card network and the issuing bank. This is often called the BIN (bank identification number). The 2017 edition of the standard extended it from 6 to 8 digits.
- Account number: the digits the issuer assigns to the individual account.
- Check digit: the last digit, calculated from all the others with the Luhn algorithm.
The first digits alone reveal the network. Visa numbers start with 4, Mastercard with 51–55 or 2221–2720, American Express with 34 or 37, and Discover with 6011, 644–649 or 65, among other ranges. That's how a checkout form can show the right card logo as you type.
How the Luhn check works
Starting from the rightmost digit (the check digit) and moving left:
- Leave the check digit as is, and double every second digit after it.
- If doubling gives a two-digit number, subtract 9 (the same as adding its two digits: 16 becomes 1 + 6 = 7).
- Add up all the digits.
- If the total ends in 0, meaning it's divisible by 10, the number passes.
A worked example
Let's use 4242 4242 4242 4242, a well-known test number from Stripe's testing documentation that doesn't belong to any real account. Counting from the right, every second digit is a 4:
| Digit | 4 | 2 | 4 | 2 | … | 4 | 2 |
|---|---|---|---|---|---|---|---|
| Doubled? | Yes | No | Yes | No | … | Yes | No (check digit) |
| Value | 8 | 2 | 8 | 2 | … | 8 | 2 |
Eight 8s and eight 2s: 64 + 16 = 80. It ends in 0, so the number passes. Change the last digit to 3 and the total becomes 81, so 4242 4242 4242 4243 fails.
Here's a case with doubling over 9, using the example number 7992739871 and finding its check digit. From the right, the doubled digits are 1, 8, 3, 2 and 9, which become 2, 7 (16 − 9), 6, 4 and 9 (18 − 9). The undoubled digits are 7, 9, 7, 9 and 7. Their total is 28 + 39 = 67, so the check digit must be 3 to bring it to 70. The full number is 79927398713.
You can try any number in our Credit Card Validator, which runs the same check, identifies the network from the leading digits and checks that the length fits that network. It works in your browser, so nothing you type is sent anywhere.
The Luhn check in code
The whole algorithm fits in a few lines. This is the function the Credit Card Validator uses, in JavaScript:
const luhn = (digits) => {
let sum = 0;
for (let i = 0; i < digits.length; i++) {
let d = Number(digits[digits.length - 1 - i]);
if (i % 2 === 1) {
d *= 2;
if (d > 9) d -= 9;
}
sum += d;
}
return sum % 10 === 0;
};
luhn("4242424242424242"); // true
luhn("4242424242424243"); // false
It expects a string of digits only, so remove spaces and dashes first. Working from the right matters: card numbers have different lengths, and counting from the check digit keeps the doubled positions correct for all of them.
Why it catches typing mistakes
The Luhn algorithm was designed for one job: catching accidental errors when people copy or type numbers. It's good at the two most common mistakes:
- Any single wrong digit is always caught. Doubling-and-subtracting-9 maps the digits 0–9 to ten different values, so changing any one digit always changes the total's last digit.
- Almost every swap of two neighboring digits is caught. The only exception is swapping
09and90, which leaves the total unchanged. We tested every possible adjacent pair with the validator's code, and that's the only one that slips through.
It's weaker against other errors, such as two separate wrong digits that happen to cancel out, or jumbled groups of digits. For a single check digit that anyone can calculate by hand, though, it's very effective.
What a Luhn check can't tell you
A number that passes the Luhn check is only well-formed. It says nothing about whether:
- the card exists or was ever issued
- the account is open, has funds, or belongs to the person using it
- the expiration date and security code are correct
Only the card issuer can confirm those, through an authorization request from a payment processor. Roughly one in ten random 16-digit numbers passes the Luhn check by chance, because the total has to end in one specific digit out of ten. That's why Luhn validation in a checkout form is a convenience for catching typos, not a security measure.
The same idea, a check digit calculated from the other digits, appears in many other numbers. UPC and EAN barcodes use a different weighting, and our Barcode Generator calculates those check digits for you. IMEI numbers on mobile phones use the Luhn algorithm itself.
Test numbers for developers
If you're building a payment form, use your payment processor's published test numbers rather than inventing your own or, worse, using a real card. From Stripe's documentation:
| Network | Test number |
|---|---|
| Visa | 4242 4242 4242 4242 |
| Mastercard | 5555 5555 5555 4444 |
| American Express | 3782 822463 10005 |
| Discover | 6011 1111 1111 1117 |
All four pass the Luhn check. Stripe's terms prohibit testing in live mode with real card details, and other processors publish their own test numbers with similar rules.
For your own form validation, a few practical points:
- Strip spaces and dashes before checking. People paste numbers in every format.
- Validate the length for the detected network: 15 digits for American Express, 16 for most Mastercard, and 13, 16 or 19 for Visa.
- Don't reject unknown prefixes outright. New ranges are added over time, so let the processor make the final call.
- Never log or store full card numbers yourself. That's what payment processors and tokenization are for.
Card numbers and privacy
Because card numbers have so much structure, they're easier to guess than they look. With a known IIN and a Luhn check digit, only a fraction of the digits are truly unknown. This is why simply hashing card numbers doesn't anonymize them: an attacker can generate and hash every valid candidate for a given IIN. Hashing vs Encryption vs Encoding explains why encryption or tokenization is the right approach for sensitive data like this.
FAQ
Does a valid Luhn check mean the card is real?
No. It only means the digits are consistent with each other. About 10% of random numbers pass by chance.
Who invented the Luhn algorithm?
Hans Peter Luhn, a scientist at IBM. It's also called the "mod 10" algorithm because it checks whether the total is divisible by 10.
Can I use the Luhn check to find which bank issued a card?
No. The Luhn check only uses the last digit. The issuer is identified by the leading digits, the IIN, which payment processors look up in their own databases.
Is it safe to enter my card number into an online validator?
Only use a tool that runs entirely in your browser, and there's rarely a reason to check a real card at all. For testing, use published test numbers.