The Luhn Algorithm Explained: How Card Number Validation Works
Type a card number into almost any checkout and, before it even talks to a bank, the form can already tell you if you fat-fingered a digit. That instant check is the Luhn algorithm — a tiny piece of 1950s maths that still guards card numbers, IMEIs and many ID numbers today.
You can watch it work on real input with our Luhn Checker and Card Validator.
What the Luhn algorithm is for
Luhn is a checksum. Its only job is to catch accidental mistakes — a mistyped or transposed digit — not to prove a card is real or funded. The final digit of a card number is a check digit chosen so that the whole number passes the Luhn check.
The steps
Starting from the rightmost digit and moving left:
- Double every second digit. If doubling gives a two-digit result, subtract 9 (or add the two digits together).
- Sum all the digits — the doubled ones and the untouched ones.
- Check mod 10. If the total is divisible by 10, the number passes.
A worked example
Take the sample number 4539 1488 0343 6467. Double every second digit from the right, reduce anything over 9, add it all up, and the total comes to a multiple of 10 — so it passes Luhn. Change any single digit and the sum almost always breaks, which is exactly how the check catches typos.
What Luhn catches — and what it misses
- Catches: single-digit typos and most transpositions (swapping two adjacent digits).
- Misses: whether the card exists, whether it has funds, whether the BIN is assigned, and some rare double-transpositions.
In other words, passing Luhn means “this is a well-formed number,” nothing more. To learn what the opening digits mean, read BIN Numbers Explained.
Where you will find it
Luhn is everywhere: credit and debit cards, IMEI numbers on phones, some national ID and provider numbers, and loyalty cards. It is popular because it is trivial to implement and needs no lookup table.
Luhn in a few lines of code
function luhnValid(string $num): bool {
$sum = 0; $alt = false;
for ($i = strlen($num) - 1; $i >= 0; $i--) {
$d = (int) $num[$i];
if ($alt) { $d *= 2; if ($d > 9) $d -= 9; }
$sum += $d; $alt = !$alt;
}
return $sum % 10 === 0;
}
Need valid-looking numbers for QA a checkout? Generate synthetic, Luhn-passing sandbox cards with our Card Generator — they are for development only and can never be charged.
The bottom line
The Luhn algorithm is a fast, elegant typo-catcher, not a validity check. Use it to fail obvious mistakes early in a form, then let the payment network decide whether a card is genuinely usable. Try it live in the Luhn Checker.