What the Luhn check can and cannot tell you
The Luhn formula is a checksum. It was designed in the 1950s to catch the errors people make when they read a long number off a piece of paper and type it into something else: one digit wrong, or two digits swapped. It is used on payment-card numbers, on some national identity numbers, on IMEI numbers in phones. It does that job well and it does nothing else, and the gap between those two facts is the whole point of this piece.
The arithmetic
Start at the rightmost digit and work left. Leave the rightmost digit alone, double the next one, leave the next, double the next, and so on in alternation. Whenever doubling produces a two-digit result, subtract 9 from it — so 8 doubles to 16 and counts as 7. Add every resulting number together. If the total ends in a zero, the string passes.
Here it is on 79927398713. That is an eleven-digit synthetic identifier, used because eleven digits is not a payment-card length — there is no card this could be. Reading right to left:
3stays31doubles to27stays78doubles to16, minus 9, so79stays93doubles to67stays72doubles to49stays99doubles to18, minus 9, so97stays7
The sum is 3 + 2 + 7 + 7 + 9 + 6 + 7 + 4 + 9 + 9 + 7 = 70. Seventy ends in zero, so the identifier passes. That is the entire calculation, and you can do it on the back of a receipt.
What the checksum genuinely catches
The alternate doubling is not decoration. It makes the total sensitive to position, so moving digits around changes the answer. Take the identifier above and change any single digit to any other digit — all ninety-nine possibilities were tried — and every one of them fails. Swap any two neighbouring digits that differ, and every one of those fails too. Those are precisely the two mistakes a human makes when copying a long number, which is why the formula has lasted seventy years.
It is not perfect even at that. There is one adjacent swap it cannot see: a 0 and a 9 next to each other. 2097 and 2907 both total 20, so both pass, and the checksum has no way to tell you which one you meant. Small, known, and a fair illustration of what a checksum is: a cheap filter, not a proof.
Now the part that matters
Passing Luhn does not mean a card is real. The formula reads a string of digits and reports whether those digits are internally consistent with each other. It never contacts a bank. It has no idea which numbers have been issued, which are still in date, which have been cancelled, which are frozen, or which have money behind them. A number can satisfy the checksum perfectly and correspond to no account anywhere in the world.
The reverse matters just as much. Failing the checksum is a reliable signal, because an issued number will pass it. So a failure means the digits are wrong — almost always a typo. A pass means only that you have not detected a typo.
The single authority on whether a card exists, belongs to the person presenting it, and can be charged is the issuer, reached through the payment network at the moment of the transaction. Nothing you can compute on a device answers that question. Nothing you can compute on a device ever will.
So what is it for
One thing: catching a mistyped number at the point of entry, so a form can say “check that again” instantly instead of after a slow round trip and a declined transaction. That is a genuinely useful piece of interface work and it costs a few lines of code.
It is not an access check, not a fraud control, not a verification step, and not any part of a security boundary. Treating a checksum as though it decided something is how systems end up trusting input they never checked. If a number needs to be real, ask the party that issued it.
The scope of this tool
It ignores every character that is not a digit, so spaces and hyphens make no difference — 799 273 987 13 gives the same answer as the unspaced form. Fewer than two digits returns enter digits. Otherwise you get ✓ valid (Luhn passes) or ✗ invalid checksum, and note the wording carefully: it is a statement about the checksum, not about a card.
The calculation runs in your browser and nothing is transmitted. That is worth having, and it is still not a reason to paste your own card number into a web page — the checksum on a card in your hand has already been verified by everyone who has ever charged it. The useful input here is a number from a form, a spreadsheet or a test fixture that is behaving oddly.
The Luhn Check answers exactly one narrow question. The value is knowing which question that is.