Luhn (mod-10) checksums: how card/IMEI check digits work

Published: 2026-09-05

How the Luhn mod-10 algorithm builds and verifies check digits for PAN-style and IMEI numbers, what errors it catches, and why a valid checksum is not proof of a real account.

The Luhn algorithm (also called the mod-10 or modulus 10 check) is a simple checksum used on many digit-only identifiers: payment card primary account numbers (PANs), some national IDs, and the 15-digit IMEI on mobile devices. The last digit is usually a check digit computed from the rest so that mistyped or transposed numbers fail a quick local test before they hit a payment network or device database.

This guide walks through the arithmetic, what “valid” actually means, and how to practice safely in the browser. Prefer synthetic test numbers—a passing Luhn check is not proof that a card or IMEI exists.

What problem Luhn solves

Humans and OCR systems make predictable mistakes: swap two adjacent digits, mistype one digit, drop a digit. Luhn is cheap to compute by hand or in firmware and catches many of those errors without a network round-trip.

It does not:

  • Authenticate a payment or prove funds
  • Identify card brand (Visa, Mastercard, etc.)
  • Encrypt or hide the number
  • Catch every possible corruption (especially some double errors)

Think of it as a spelling check for digit strings, not a security control. For privacy when experimenting, keep numbers on-device—see why local-only matters.

The algorithm (right to left)

Given a full digit string (payload + check digit):

  1. Starting from the rightmost digit, move left.
  2. Double every second digit (positions 2, 4, 6… counting from the right).
  3. If a doubled value is greater than 9, subtract 9 (same as summing its digits: 16 → 1+6 = 7).
  4. Sum all contributions.
  5. The number is Luhn-valid if the sum is divisible by 10 (sum % 10 === 0).

Worked example

Classic teaching string: 79927398713 (often grouped as 7992-7398-713). Digits from the right, doubling every second:

Digit (right → left) Doubled? Contribution
3 no 3
1 yes 2
7 no 7
8 yes 7 (16−9)
9 no 9
3 yes 6
7 no 7
2 yes 4
9 no 9
9 yes 9 (18−9)
7 no 7

Sum = 70, and 70 % 10 === 0valid. Flip any single digit and the sum usually stops ending in 0.

Check-digit formula: take the payload (all digits except the last), append a temporary 0, run the same sum, then

checkDigit = (10 - (sum % 10)) % 10

For payload 7992739871, that yields check digit 3, matching the example. The Luhn checker shows payload, expected check digit, and an optional doubling walk for short inputs.

Cards, IMEIs, and other Luhn users

Identifier Typical length Role of last digit
Payment PAN Often 13–19 digits Check digit (issuer also encodes BIN/IIN in the prefix)
IMEI 15 digits Check digit over the first 14
Some loyalty / account IDs Varies Same mod-10 rule if the scheme adopted Luhn

Test PANs such as 4111 1111 1111 1111 are published for sandboxes; they pass Luhn so gateways accept the format while declining real charges. Do not paste live customer PANs into random websites—use local tools or issuer test data.

IMEI check digits follow the same Luhn rule over the 14-digit body. A wrong check digit is a strong signal of a typo; a correct one still does not prove the device is registered or legitimate.

Retail EAN/UPC barcodes also use a mod-10 style check digit, but the weighting is different (alternating ×3 and ×1 from the right). Do not mix Luhn and GS1 formulas—see Generating Code128, EAN, UPC, and QR barcodes offline.

IBAN validation uses a different checksum (MOD-97 over a rearranged alphanumeric string), not Luhn. When you move from card-style digits to bank account numbers, switch algorithms—try the IBAN validator for length and MOD-97 checks.

What “valid” and “invalid” mean

Result Means Does not mean
Valid checksum Digits satisfy Luhn Real card, funded account, or issued IMEI
Invalid checksum Transcription or generation error (or wrong algorithm) Fraud by itself
Expected check digit ≠ last digit Last digit is wrong for that payload Which earlier digit was mistyped

Luhn catches most single-digit errors and many adjacent transpositions. It can miss some multi-digit corruptions. Production systems still need issuer authorization, device registries, and proper auth—not checksum alone.

Computing vs verifying

Two everyday workflows:

  1. Verify: paste a full number → strip spaces/hyphens → run Luhn → valid or invalid (and show expected last digit if it failed).
  2. Complete: paste a payload without a check digit → compute the digit that makes the number valid (useful for generating synthetic test IDs).

Bulk lists (one number per line) are handy for fixture files and QA dumps. Blank lines and # comments are usually skipped so you can annotate samples.

Safe practice tips

  • Prefer documented test numbers and random synthetic payloads over anything from production logs.
  • Treat Luhn output as format hygiene, never as authorization.
  • Keep checksum experiments local when numbers might be sensitive: the Luhn checker runs entirely in your browser and does not upload or store input.
  • Grouping with spaces or hyphens (4111-1111-…) is fine for humans; strip them before math.

Try it locally

On the Luhn checker:

  • Paste a digit string (spaces and hyphens OK) or load an educational example.
  • Read valid/invalid, Luhn sum, last digit, and expected check digit.
  • Expand the doubling walk on short inputs to see each contribution.
  • Switch to bulk list mode for one-per-line checks and a TSV-style summary.
  • Use complete with check digit when you only have the payload.

Nothing leaves your device—the same privacy model as the rest of LocalTools.

Related reading

All learn articles