Luhn algorithm
What is the Luhn algorithm?
Luhn algorithm is a checksum formula that verifies whether a string of digits, such as a payment card number, is structurally valid using a modulus 10 calculation. Also known as the mod 10 or modulus 10 algorithm, it was developed by IBM scientist Hans Peter Luhn and patented in 1960.
The formula relies on a single check digit, the last digit of the sequence, that forces the whole number to satisfy a fixed arithmetic rule. When a number is typed into a checkout form, the Luhn check confirms the digits add up correctly before a request ever reaches the . It validates the format of a number, not whether the account behind it exists, so it works as a first filter rather than a guarantee. Beyond payments, the same method validates IMEI device identifiers and several national and corporate ID schemes.
Key facts
- Also known as: mod 10 or modulus 10 algorithm
- Type: checksum, or check-digit, formula
- Created by: Hans Peter Luhn (IBM), patented in 1960
- Validates: the structural integrity of a digit sequence, not account validity
- Common uses: and debit card numbers, IMEI device IDs, some national ID numbers
- Standard: ISO/IEC 7812-1, the standard that defines payment card number format, specifies the Luhn formula for the card number's final check digit.
How it works
The Luhn check runs the same way whether it generates a check digit or verifies an existing number:
- Identify the check digit. The rightmost digit of the sequence is the check digit, and the calculation works back from it.
- Double every second digit. Starting from the digit immediately left of the check digit and moving left, double the value of every second digit.
- Reduce doubled values over 9. If doubling a digit produces a number greater than 9, subtract 9 from it, which is the same as adding its two digits together.
- Sum all digits. Add the adjusted doubled digits to the digits that weren't doubled.
- Check divisibility by 10. If the total is a multiple of 10, the number passes the Luhn check; if not, it's invalid.
Luhn algorithm example
Take the number 79927398713, where 3 is the check digit. Doubling every second digit from the right (1, 8, 3, 2, 9) gives 2, 16, 6, 4 and 18, which reduce to 2, 7, 6, 4 and 9. Adding these to the remaining digits gives a total of 70, a multiple of 10, so the number passes. To generate the check digit instead, the same steps run on 7992739871 give a sum of 67, and the check digit is the amount needed to reach the next multiple of 10, which is 3.
Why it matters
The Luhn algorithm catches accidental data-entry errors, like a mistyped or swapped digit, before a payment request is sent. Because it runs instantly in the browser, a checkout form can flag an invalid card number and ask for a correction rather than submitting it and waiting for a decline.
It also acts as a cheap first filter against crude card-number guessing. Randomly generated numbers rarely satisfy the checksum, so the check screens out obvious junk before it consumes an authorization attempt. The leading digits of a card, its , identify the issuer separately, while the Luhn digit confirms the sequence as a whole holds together.
Common issues
Passing the Luhn check doesn't mean a card is usable. The test confirms only that the digits are internally consistent, so a number can pass and still be declined because the account doesn't exist, the card has expired, or funds are short.
- It misses one transposition error. The algorithm detects every single-digit mistake, but swapping the adjacent digits 09 and 90 leaves the checksum unchanged, so that specific error slips through.
- It isn't fraud protection. A fraudster using a real stolen number passes the Luhn check trivially. It sits alongside checks, , and screening, which assess legitimacy rather than format.
- It misses twin errors. Replacing one pair of repeated digits with another, such as 22 with 55, 33 with 66, or 44 with 77, produces the same checksum.
- It doesn't stop generated numbers. Because the formula is public, a script can produce thousands of Luhn-valid numbers from a known BIN. These pass the format check and are only rejected at authorization.


