The Luhn Algorithm Explained: How Credit Card Validation Works

A step-by-step guide to the Luhn (mod-10) algorithm with a worked example for 4242 4242 4242 4242, why every card uses it, and how to implement it in code.

By FakeName Editorial TeamPublished June 25, 2026Last updated June 25, 20269 min read

The Luhn algorithm is a mod-10 checksum that detects accidental typos in number sequences like credit card numbers, and it is why a checkout form can flag a mistyped digit before any network request fires. IBM engineer Hans Peter Luhn designed it in 1954 and received US Patent 2,950,048 for it in 1960; today it sits behind nearly every payment card on earth [luhn-wiki]. This guide explains how it works, walks the math on a real test number, and gives a correct implementation.

To check a number right now, the credit card validator at /tools/credit-card-validator runs the full Luhn check in your browser and never transmits the digits anywhere. For Luhn-valid sandbox test cards, the credit card generator produces them on demand, and the full identity generator at / scopes a card to a complete fictional profile. Everything those tools emit is fictional and exists for testing, QA, and privacy work only, never for fraud or impersonation.

What does the Luhn algorithm actually do?

The Luhn algorithm computes a single check digit that makes an entire number satisfy a mod-10 arithmetic property, so any single-digit transcription error breaks the property and fails validation instantly. It is a checksum, not encryption: it carries no secret, anyone can compute it, and that is exactly the design goal. Its only job is catching the typos a human makes when copying digits.

The formula is published in Annex B of ISO/IEC 7812-1, the standard for identification card numbering, which is why it appears far beyond credit cards: in IMEI device identifiers (the 15th digit, per 3GPP TS 23.003), some social insurance numbers, and survey response IDs [iso7812]. That same standard defines the structure of a card number. Here is the anatomy of a typical 16-digit Visa or Mastercard number.

SegmentDigit positions (from left)NamePurpose
MII1Major Industry IdentifierBroad issuer category (4 = banking/finance, used by Visa)
IIN / BIN1–6 (now extended to 8)Issuer Identification NumberIdentifies the issuing institution and card network
Account7–15Individual Account IdentifierUp to 12 digits identifying the specific account
Check16Luhn check digitSingle digit that makes the whole number mod-10 valid
Anatomy of a 16-digit payment card number under ISO/IEC 7812-1

How does the Luhn algorithm work step by step?

To validate a number with Luhn, start at the rightmost digit, double every second digit moving left, subtract 9 from any doubled result above 9, sum all the digits, and confirm the total is divisible by 10. Those four steps run in linear time with no lookup beyond single-digit arithmetic. The list below states them precisely.

  1. Starting from the rightmost digit (the check digit), leave it as is and double every second digit moving left.
  2. If doubling a digit produces a number greater than 9, subtract 9 from it (equivalently, add the two digits of the result, which always lands in the range 1 to 9).
  3. Sum every digit: the untouched digits plus the transformed (doubled) digits.
  4. If the total is divisible by 10, the number passes the Luhn check. Otherwise it fails.

The subtract-9 step is where most hand calculations go wrong. Doubling 8 gives 16, and 16 minus 9 is 7, which equals 1 + 6, the sum of its digits. That shortcut keeps every contribution to a single digit. Memorize the full mapping from input digit to doubled contribution and you can run Luhn on paper in seconds.

Input digitDoubled valueAfter subtract-9 ruleNet contribution
0000
1222
2444
3666
4888
51010 − 9 = 11
61212 − 9 = 33
71414 − 9 = 55
81616 − 9 = 77
91818 − 9 = 99
Doubling lookup table: every digit's contribution when it lands in a doubled position

Worked example: why 4242 4242 4242 4242 passes

4242 4242 4242 4242 is Stripe's canonical Visa test number, used in sandbox environments worldwide [stripe-test]. It is built to pass Luhn while never mapping to a real account. The table below shows every position. Position 1 is the rightmost digit, and we double the even-numbered positions counting from the right.

Position (from right)DigitDoubled?Value after ruleNotes
12No2Check digit, untouched
24Yes84 x 2 = 8
32No2Untouched
44Yes84 x 2 = 8
52No2Untouched
64Yes84 x 2 = 8
72No2Untouched
84Yes84 x 2 = 8
92No2Untouched
104Yes84 x 2 = 8
112No2Untouched
124Yes84 x 2 = 8
132No2Untouched
144Yes84 x 2 = 8
152No2Untouched
164Yes84 x 2 = 8
Position-by-position Luhn computation for 4242 4242 4242 4242

Add the values: eight untouched 2s sum to 16, and eight doubled 8s sum to 64. The total is 16 + 64 = 80, and since 80 is divisible by 10, the number is Luhn-valid. None of the doubled values exceeded 9 here, so the subtract-9 step never fired. A number like 49927398716 does trigger it, which is why you should test implementations against varied inputs.

A check digit is a form of redundancy check used for error detection, the decimal equivalent of a binary check bit. It consists of a single digit computed from the other digits in the number.
ISO/IEC 7812-1, Identification cards — Identification of issuers

How do you compute the check digit when generating a number?

To generate a valid number, set the check digit to 0, run the same doubling-and-summing pass over the body, then pick the check digit using check digit = (10 − (sum mod 10)) mod 10. If the partial sum ends in 7, the check digit is 3; if it ends in 0, the check digit is 0. Test-data generators, including the one at /, use exactly this construction to produce numbers that survive front-end validation while staying in non-issued ranges. The faker ecosystem applies the same approach in its finance module [faker].

What does Luhn catch and what does it miss?

Luhn catches 100% of single-digit errors and most adjacent transpositions, but it misses the swap of 09 and 90, certain twin-digit substitutions like 22 to 55, and it says nothing about whether a card exists or is funded. Knowing these gaps keeps you from over-trusting a pass. The table below maps each error class to whether Luhn detects it.

Error typeExampleCaught by Luhn?
Single mistyped digit4242...4242 becomes 4252...4242Yes, always (100%)
Most adjacent transpositionsSwapping 45 to 54Yes
Transposition of 09 and 90Swapping 09 to 90No (blind spot)
Twin-digit error 22 to 5522 becomes 55No
Twin-digit error 33 to 6633 becomes 66No
Whether the card existsAny valid-format numberNo, out of scope
Whether funds are availableAny valid numberNo, out of scope
Luhn error-detection coverage by error class

The 09-to-90 swap is the most cited weakness: doubling 0 gives 0 and doubling 9 gives 9 (after subtracting 9), so swapping those two digits leaves the checksum unchanged [luhn-wiki]. The twin-digit substitutions fail for the same parity reason. Higher-assurance identifiers use the Verhoeff or Damm algorithms, which catch all single-digit and all adjacent-transposition errors. Bank accounts go further: an IBAN carries a two-digit checksum computed with ISO/IEC 7064 MOD 97-10, far stronger than Luhn but more expensive to run. Here is where Luhn sits among common schemes.

AlgorithmBase / radixAll single-digit errorsAll adjacent transpositionsTypical use
Luhn (mod 10)DecimalYesNo (misses 09→90)Credit cards, IMEI, IINs
VerhoeffDecimalYesYesIndia's Aadhaar number, high-assurance IDs
DammDecimalYesYesModern ID schemes
ISO/IEC 7064 (MOD 97-10)DecimalYesYesIBAN bank account numbers
UPC / EAN (mod 10)DecimalYesNoRetail barcodes
Check-digit algorithms compared

How do you implement a Luhn validator correctly?

A correct Luhn validator normalizes input first (strip spaces and dashes, reject non-numeric or empty strings), then reads the digits right to left, doubles alternate digits, applies the subtract-9 rule, and returns whether the sum is divisible by 10. Keep the function pure: string in, boolean out, no shared mutable state. The decision table below lists the boundary cases your tests must cover.

InputAfter normalizationExpected resultReason
4242 4242 4242 42424242424242424242ValidSum 80, divisible by 10
4242-4242-4242-42424242424242424242ValidDashes stripped, same digits
4242 4242 4242 42414242424242424241InvalidSum 79, fails mod-10
4992739871649927398716ValidExercises the subtract-9 branch
4242abc4242rejectedInvalid (error)Non-numeric characters present
(empty string)rejectedInvalid (error)No digits to validate
Input-handling decision table for a Luhn validator

Most libraries follow this shape; the faker ecosystem, for instance, generates card numbers that pass Luhn by construction [faker]. Test your version against known-valid numbers like 4242 4242 4242 4242 and 49927398716 (which forces the subtract-9 branch), plus known-invalid numbers made by changing one digit, so every code path actually runs.

Why use synthetic card numbers instead of real ones?

Synthetic card numbers are the only safe option for testing because real cardholder data falls under PCI DSS and, in the EU, under the GDPR definition of personal data in Article 4(1), which covers any information relating to an identified or identifiable person [gdpr-art4]. Using someone's real card for QA is a processing activity with no lawful basis under GDPR Article 6. Synthetic numbers look right to your validation layer but identify no one. The UK Information Commissioner's Office treats properly synthesized data as falling outside personal-data obligations precisely because no individual is identifiable from it [ico-anon].

To go further, pair the checksum with structural lookups. The BIN range and card brand live in the leading digits; the validator at /tools/credit-card-validator decodes those alongside the Luhn pass, the generator at / produces complete, internally consistent fictional records for end-to-end suites, and /countries aligns those records with regional formats. Use Luhn as your fast local first filter, and let the payment network be the source of truth for everything else.

References & sources

  1. Luhn algorithmWikipedia
  2. ISO/IEC 7812-1: Identification cards — Identification of issuers — Part 1: Numbering systemInternational Organization for Standardization
  3. Testing — Sample test cardsStripe Documentation
  4. @faker-js/faker — Finance module (creditCardNumber)faker-js
  5. NIST SP 800-122: Guide to Protecting the Confidentiality of Personally Identifiable Information (PII)National Institute of Standards and Technology
  6. GDPR Article 4 — Definitions (personal data)gdpr-info.eu
  7. Anonymisation, pseudonymisation and privacy enhancing technologies guidanceUK Information Commissioner's Office

Frequently asked questions

What is the Luhn algorithm used for?+

The Luhn algorithm is a checksum formula that validates identification numbers such as credit card numbers, IMEI device numbers, and some national IDs. It detects accidental data-entry errors like a single mistyped digit or a swapped pair of adjacent digits before a number is submitted to a backend system. It is standardized in Annex B of ISO/IEC 7812-1.

Does passing the Luhn check mean a credit card is valid?+

No. Passing Luhn only means the digits form a mathematically consistent number. It does not mean the card was issued, is active, has funds, or belongs to anyone. Real authorization requires the card network and issuing bank. Luhn is purely a front-end typo filter.

Why is 4242 4242 4242 4242 a valid card number?+

It is Stripe's well-known sandbox test number, deliberately constructed to pass the Luhn check (its digit sum is 80, which is divisible by 10) while never being issued to a real account. It lets developers test payment flows without using real card data.

Which digit does the Luhn algorithm not double?+

Working from the rightmost digit, the last digit (the check digit) is never doubled. You double every second digit moving left, so the doubling applies to positions 2, 4, 6 and so on counting from the right.

Can the Luhn algorithm catch every typo?+

No. It reliably catches every single-digit error and most adjacent transpositions, but it misses the specific transposition of 09 to 90 (and vice versa) and certain twin-digit errors like 22 to 55. It is a lightweight first line of defense, not a guarantee.

We use cookies for analytics and ads to keep this generator free. See our Privacy Policy.