What Is the Luhn Algorithm?
Luhn algorithm (mod 10) explained: the steps, a digit-by-digit check of Stripe's 4242 test card, what it catches, what it misses, and a JavaScript check.
Article summary
TL;DR
The Luhn algorithm is a mod 10 checksum that validates card numbers and other IDs. Starting from the right, you double every second digit, subtract 9 from any result above 9, and add everything up. If the total ends in 0, the number is well formed. It catches typos, not fraud.
- The last digit of a card number is the check digit. The issuer picks it so the whole number passes the mod 10 test.
- Luhn catches every single-digit typo and almost every swap of two neighboring digits. It misses 09 written as 90.
- Passing Luhn proves nothing about the card: one random number in ten passes, and card testers only use Luhn-valid numbers.
- The method is set out in ISO/IEC 7812-1, Annex B, and reused for phone IMEI numbers.
On this page
What is the Luhn algorithm?
The Luhn algorithm, also called the mod 10 or modulus 10 algorithm, is a check digit formula. The last digit of a card number is a control digit, chosen so the whole number passes a simple sum test. A typo almost always breaks the test, so the form can ask the customer to fix the number before any payment is sent.
Hans Peter Luhn, an IBM engineer, filed the patent on January 6, 1954. US Patent 2,950,048, granted on August 23, 1960, describes a hand-held "computer for verifying numbers" aimed at a common copying error: "transposing two of the digits."2US Patent 2,950,048, Computer for verifying numbers, H. P. Luhn, filed January 6, 1954, granted August 23, 1960 (read October 14, 2026)
The method is set out in Annex B of ISO/IEC 7812, the standard that numbers payment cards; the mobile standards that reuse it point to that exact annex.3ETSI TS 123 003 V17.9.0 (3GPP TS 23.003), clause 6.2.1 and Annex B (read October 14, 2026) The check digit comes after the issuer prefix and the account number: see bank identification number for the other digits.
How the Luhn algorithm works
- Start from the right. The last digit is the check digit. Keep it as it is.
- Double every second digit moving left: the 2nd, 4th, 6th digit from the right, and so on.
- Subtract 9 from any doubled value above 9. 7 doubled is 14, which becomes 5. This is the same as adding the two digits: 1 + 4 = 5.
- Add all the digits, doubled and untouched.
- Check the total. If it ends in 0 (divides by 10), the number passes. If not, it has an error.
Validating a full card number, check digit included. Remove spaces and dashes first.
Worked example: Stripe's 4242 4242 4242 4242 test card
Stripe documents 4242 4242 4242 4242 as its basic Visa test card.1Stripe Docs, Testing (read October 14, 2026) Counting from the right, the 2s sit in the odd positions (kept) and the 4s in the even positions (doubled).
| Positions from the right | Digit | Step | Value counted |
|---|---|---|---|
| 1 (check digit), 3, 5, 7, 9, 11, 13, 15 | 2 | Kept | 8 digits × 2 = 16 |
| 2, 4, 6, 8, 10, 12, 14, 16 | 4 | Doubled: 4 × 2 = 8 | 8 digits × 8 = 64 |
| All 16 digits | Added up | 16 + 64 = 80 |
Left to right, 4 2 4 2 ... 4 2 becomes 8 2 8 2 ... 8 2. Each "8 2" pair adds up to 10, and eight pairs make 80, which ends in 0: the number passes. No doubled value goes above 9, so step 3 never applies.
Now change only the last digit: 4242 4242 4242 4241. The total drops to 79, and the number fails. Stripe uses that exact number to simulate an incorrect_number error in tests.1Stripe Docs, Testing (read October 14, 2026)
Generating vs validating the check digit
The same arithmetic runs in two directions:
| Generating (issuer) | Validating (checkout) | |
|---|---|---|
| Input | The first 15 digits: 424242424242424 | All 16 digits |
| Which digits are doubled | The rightmost digit of the input, then every second one | The second digit from the right, then every second one |
| Sum | 8 × 8 + 7 × 2 = 78 | 80 |
| Result | Check digit = 80 − 78 = 2 | 80 ends in 0: valid |
The check digit brings the sum up to the next multiple of 10 (0 if it already ends in 0). Since exactly one digit in ten works, a random 16-digit number passes about one time in ten.
Inside Tagada
See every payment's route, processor by processor
Set the order your processors are tried in, per store, per country or per product.

What Luhn catches and what it misses
| Error | Example | Caught? |
|---|---|---|
| One wrong digit | 4242 ... 4241 instead of ...4242 | Always |
| Two neighbors swapped | ...4224 instead of ...4242 (sum 78) | Almost always |
| 09 swapped with 90 | ...09... instead of ...90... | Never: both pairs add up to 9 |
| Twin digits changed | 22 ↔ 55, 33 ↔ 66, 44 ↔ 77 | Never: the sums stay equal |
| A made-up number with a correct check digit | Any Luhn-valid string | Never |
Check the 09 gap by hand: 0 doubled is 0, and 9 doubled is 18, which becomes 9. Either way the pair counts for 9.
Luhn is not a security check
The formula is public, so passing it proves only that the digits are consistent. Stripe's generic decline test card, 4000 0000 0000 0002, passes Luhn and is still declined.1Stripe Docs, Testing (read October 14, 2026) Closed, expired or empty real cards pass too.
BIN attacks generate Luhn-valid numbers from a known issuer prefix, since invalid ones would die in the form. Stripe describes card testers using scripts "to test a large amount of card information at once" and recommends CAPTCHA, rate limits and velocity rules.4Stripe Docs, Protect yourself from card testing (read October 14, 2026) Luhn stops typos; fraud scoring and the issuer's authorization handle fraud. Full playbook: ecommerce fraud prevention.
Other uses: IMEI numbers
A phone's IMEI is 14 digits plus a Luhn check digit. The 3GPP specification says it "is intended to avoid manual transmission errors, e.g. when customers register stolen MEs at the operator's customer care desk," and computes it with the method of ISO/IEC 7812, Annex B.3ETSI TS 123 003 V17.9.0 (3GPP TS 23.003), clause 6.2.1 and Annex B (read October 14, 2026) Some national ID numbers use Luhn or a variant: check each scheme's official rules before reusing a card validator.
Luhn check in JavaScript
An illustrative 10-line version. In production, use the validation built into your payment provider's card field.
function luhnCheck(cardNumber) {
const digits = cardNumber.replace(/\D/g, "");
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 digits.length > 0 && sum % 10 === 0;
}
// luhnCheck("4242424242424242") === true
How Tagada helps
Fraud checks after the format check
A Luhn-valid number can still be a tested or stolen card. TagadaPay runs native 3DS2, device intelligence and a rules engine in the checkout, so each payment can be screened before authorization. Tagada follows Visa and Mastercard rules and the laws that apply to payments.
Frequently asked questions
What is the Luhn algorithm used for?
Why is it called the mod 10 algorithm?
Does a Luhn-valid card number mean the card is real?
How do I calculate the check digit?
Who invented the Luhn algorithm?
Sources
Checked October 15, 2026- Stripe Docs, Testing (read October 14, 2026)
- US Patent 2,950,048, Computer for verifying numbers, H. P. Luhn, filed January 6, 1954, granted August 23, 1960 (read October 14, 2026)
- ETSI TS 123 003 V17.9.0 (3GPP TS 23.003), clause 6.2.1 and Annex B (read October 14, 2026)
- Stripe Docs, Protect yourself from card testing (read October 14, 2026)
TagadaPay
Screen every card payment before authorization
Tell us what you sell and how you sell it. Each application is underwritten, and approval is not guaranteed.
- 01Tell us what you sell and how
- 02Underwriting reviews your business
- 03Process through TagadaPay alongside your other processors
