Luhn Algorithm Calculator
Enter a number to test it against the Luhn checksum and see the arithmetic digit by digit. Or enter a number without its last digit and generate the check digit that completes it. Runs entirely in your browser — nothing you type is sent anywhere.
Luhn tells you whether a number is well-formed. It cannot tell you whether a card exists. For that, run the first 6 to 11 digits through the BIN checker.
How the Luhn Algorithm Works
The algorithm treats the rightmost digit as the check digit and works leftwards:
- Starting from the second digit from the right, double every second digit.
- If doubling produces a two-digit number, subtract 9 (equivalently, add the two digits together).
- Add up all the digits, doubled and undoubled.
- If the total is divisible by 10, the number is valid.
To generate a check digit rather than test one, run the same calculation on the number with a placeholder 0 appended, then take whatever value would bring the total up to the next multiple of 10. That value is the check digit.
Worked Example: 4111 1111 1111 1111
Reading from the right, digits in even positions are doubled. Products over 9 have 9 subtracted.
| Position | Digit | Doubled? | Product | Value |
|---|---|---|---|---|
| 1 | 4 | yes | 4 × 2 = 8 | 8 |
| 2 | 1 | no | 1 | 1 |
| 3 | 1 | yes | 1 × 2 = 2 | 2 |
| 4 | 1 | no | 1 | 1 |
| 5 | 1 | yes | 1 × 2 = 2 | 2 |
| 6 | 1 | no | 1 | 1 |
| 7 | 1 | yes | 1 × 2 = 2 | 2 |
| 8 | 1 | no | 1 | 1 |
| 9 | 1 | yes | 1 × 2 = 2 | 2 |
| 10 | 1 | no | 1 | 1 |
| 11 | 1 | yes | 1 × 2 = 2 | 2 |
| 12 | 1 | no | 1 | 1 |
| 13 | 1 | yes | 1 × 2 = 2 | 2 |
| 14 | 1 | no | 1 | 1 |
| 15 | 1 | yes | 1 × 2 = 2 | 2 |
| 16 | 1 | no | 1 | 1 |
| Sum | 30 | |||
30 is divisible by 10, so 4111111111111111 passes. Change any single
digit and the sum moves off a multiple of 10, which is the whole point: the check catches
every single-digit error and almost every swap of two adjacent digits (the one exception
is 09 ↔ 90).
What Luhn Does and Doesn't Prove
This is why a checkout form needs two separate checks. Luhn runs client-side, costs nothing, and catches typos before the form submits. A BIN check on the first 6 to 11 digits then establishes what the card actually is: the network, the issuing bank, the funding type, and the country. A generated test number passes Luhn and fails the BIN check. A mistyped real card fails Luhn and may pass the BIN check. You want both signals. See what a BIN number is for how the two parts of a card number fit together.
Numbers That Use Luhn
| Number type | Length | Notes |
|---|---|---|
| Payment card numbers (PAN) | 13–19 digits | Every major network; the check digit is the last digit |
| IMEI | 15 digits | Mobile device identifiers; the 15th digit is the Luhn check |
| US National Provider Identifier | 10 digits | Computed with a constant prefix of 80840 prepended |
| Canadian Social Insurance Number | 9 digits | Standard Luhn over all nine digits |
| Various national IDs and loyalty numbers | varies | Israel, Greece, South Africa and others use Luhn or a variant |
Implementation
Two reference implementations. Both strip non-digits first, so spaces and dashes are fine.
function luhnValid(number) {
const digits = String(number).replace(/\D/g, '');
let sum = 0;
let double = false;
for (let i = digits.length - 1; i >= 0; i--) {
let d = Number(digits[i]);
if (double) {
d *= 2;
if (d > 9) d -= 9;
}
sum += d;
double = !double;
}
return digits.length > 1 && sum % 10 === 0;
}
luhnValid('4111 1111 1111 1111'); // true
luhnValid('4111 1111 1111 1112'); // false def luhn_valid(number: str) -> bool:
digits = [int(c) for c in number if c.isdigit()]
total = 0
for i, d in enumerate(reversed(digits)):
if i % 2 == 1:
d *= 2
if d > 9:
d -= 9
total += d
return len(digits) > 1 and total % 10 == 0
luhn_valid("4111 1111 1111 1111") # True
luhn_valid("4111 1111 1111 1112") # False In a payment form, run this on the client before submitting, then send only the first 6 to 11 digits to a BIN lookup. Never send the full number to a third-party lookup service; our API rejects anything over 11 digits and redacts it from logs.
FAQ
- What is the Luhn algorithm?
- A checksum formula that validates identification numbers by weighting alternate digits, summing the result, and checking that the total is divisible by 10. It was patented by Hans Peter Luhn at IBM in 1960 and is specified in ISO/IEC 7812-1. Payment card numbers, IMEIs, and US National Provider Identifiers all use it.
- What is a Luhn check digit?
- The final digit of the number. It is chosen so that the whole number passes the Luhn test. Given the other digits, exactly one check digit value makes the sum divisible by 10, and the calculator on this page generates it.
- Does passing the Luhn test mean a card number is real?
- No. Luhn only proves the digits are internally consistent, which rules out most typos and transposition errors. Any 16-digit string can be made to pass by picking the right last digit. To know whether a number belongs to a real issuer range, check the BIN.
- Which numbers use the Luhn algorithm?
- Visa, Mastercard, American Express, Discover, JCB, UnionPay and Diners Club card numbers; IMEI numbers on mobile devices; US National Provider Identifiers; Canadian Social Insurance Numbers; and many national ID and loyalty schemes.
- Is the Luhn algorithm secure?
- It is not a security control and was never meant to be one. It is an error-detection check that catches single-digit mistakes and most adjacent transpositions. It provides no protection against a deliberately constructed number.
- Why does my card number fail the Luhn check?
- Almost always a typo: one wrong digit, two adjacent digits swapped, or a digit missing. Re-read the number from the card. If it still fails, the number was not issued by a payment network.