Menu

Luhn Algorithm: Why Card Numbers End in a Check Digit

The Luhn algorithm is a mod 10 checksum behind the last digit of a card number. Learn how to compute it by hand, what it catches, and what it cannot prove.

Published

  • test data
  • payments
  • Luhn

The Luhn algorithm is the reason a card number ends in a digit that looks arbitrary. It is a checksum — a small arithmetic summary of every digit that came before it — and it is the most common automated test a card number must pass before anything else happens. It was devised at IBM in the 1950s by Hans Peter Luhn and later became a convention for payment cards through the international standard that governs card numbering.

This article explains what the check digit is for, how to work it out on paper, why it catches most typing mistakes, and why passing it means far less than people assume.

What the Luhn algorithm does

Take a card number, set the last digit aside, and run the remaining digits through a fixed procedure. The result determines what the closing digit has to be. A number is accepted when the closing digit is consistent with everything in front of it.

Nothing in that procedure involves a bank, an account list or a secret. It is arithmetic published in textbooks, reproduced in nearly every programming language, and computable in a fraction of a millisecond. It answers exactly one narrow question: does this string contain an obvious transcription error?

That narrowness is easy to forget. Because the checksum is the most visible automated test in a checkout form, people start believing it says more than it does.

How do you calculate a check digit by hand?

The procedure runs from right to left over the digits that remain once the closing digit is removed.

  1. Write the digits down and number their positions from the right, starting at one.
  2. Double every digit in an even position.
  3. If a doubled value goes above nine, subtract nine from it — the same as adding the two digits of the result together.
  4. Add all the values together.
  5. Work out how much you would need to add to reach the next multiple of ten. That amount is the check digit.

A short example makes it concrete. Take the five digits 1, 2, 3, 4 and 5 as the body of a longer number and number them from the right: the 5 sits in position one, the 4 in position two, the 3 in position three, the 2 in position four and the 1 in position five. Doubling the even positions turns the 4 into 8 and the 2 into 4. The values are then 1, 4, 3, 8 and 5, which total 21. The next multiple of ten is 30, so the check digit is 9 and the finished sequence ends in 9.

Doing that by hand for a full-length card number is tedious but never ambiguous. Software does it by walking the string from its end, which is also why an implementation that starts from the wrong side will reject perfectly good numbers.

Why does doubling catch transposed digits?

The doubling rule is not arbitrary. It makes the weight of each digit depend on its position, so swapping two neighbours generally changes the total.

That matters because the two most common human errors on a numeric field are mistyping a single digit and transposing two adjacent digits. One wrong digit shifts the sum by a non-zero amount, so the checksum almost always fails. A swap between neighbours also shifts the sum, because one of the pair was doubled and the other was not.

Almost, not always. A few swaps are invisible to this check. The classic blind spot is the pair zero and nine sitting side by side: doubling nine and reducing the result by nine returns nine, so those two can trade places without changing the total. Other pairings behave the same way. The accurate description of the check, then, is that it catches every single-digit error and most but not all adjacent transpositions.

What the check digit cannot tell you

It cannot say whether a number is real. Nothing in the arithmetic refers to an issuer, so any prefix can be joined to any middle digits and a valid closing digit computed to fit.

It cannot say that an account is open, that a card has not been cancelled, or that the person typing the number is holding the card. Each of those questions needs an authorisation request to the issuer, which is exactly the operation a test environment must avoid.

It also cannot vouch for the expiry date, the cardholder name or the security code. Those fields sit beside the check digit with rules of their own, and a number that satisfies the checksum can be paired with a date that has already passed and a code that matches nothing.

This is the honest description of what the generator on this site returns: every value is structurally valid and consistent with this checksum, and every one of them is a number that was never issued to anyone.

Where else the same checksum appears

Payment cards are the best-known user of this method, not the only one. Numbering schemes that need a cheap typo guard often reach for the same public arithmetic, including several national identification numbers, assorted loyalty and gift card systems, and various internal identifiers.

That reuse has a practical consequence. A shared helper that treats a passed checksum as proof of “credit card” will misclassify anything else that happens to satisfy it. Name the routine after what it does — a modulus ten checksum — rather than after the domain where you first met it.

For developers: order of checks and common traps

Validation order matters more than people expect, and the checksum is not the right place to begin.

Check length first, because the procedure has no opinion about how many digits it is handed; a five-digit fragment can be checksum-consistent and still be useless. Check the character set next, so letters, stray whitespace and separators are refused before any arithmetic runs. Compute the checksum after that, and only then try to recognise a network from the prefix.

Three traps show up again and again:

  • Treating a leading zero as insignificant. Card numbers are strings, not integers, and a numeric parse can quietly drop a digit, producing a checksum failure that has nothing to do with the user’s typing.
  • Running the doubling pass from the left. Position is defined from the right, so direction is part of the specification rather than an implementation detail.
  • Reporting a failed checksum as a declined card. It means malformed input, and the message shown to the user should say that.

For test data, the useful pattern is to keep pairs: a number that passes and the same number with one digit altered so that it fails. That gives the suite a positive and a negative case separated by exactly one character, which makes a regression obvious at a glance. The format guide covers the length and prefix rules that should run before the checksum, and the validation walkthrough assembles the whole sequence in order.

Checking a checksum against a real string

The quickest way to build intuition is to push a few strings through the card number generator. Generate a batch, change one digit by hand and watch the check fail; generate again and notice that only the closing digit moves while everything ahead of it stays fixed. The network comparison is worth reading next, because the same arithmetic behaves differently across fifteen- and sixteen-digit schemes and the difference trips up hand-written helpers.

Next steps

Write your validation order down before you write the code, with the checksum second to last, and store one deliberately corrupted fixture for every valid number in your suite. When you want to see how lengths and prefixes interact with the closing digit, continue with the card number format guide.

Keep reading

Fake Credit Card Number Generator (Test Cards) guides