Back to all articles

ID number guide

SA ID Checksum Explained: How the Luhn Digit Validates South African ID Numbers

Step-by-step explanation of the South African ID Luhn checksum: how digit 13 is calculated from the first 12 digits, common failure patterns, and why checksum validation is structural — not a Home Affairs lookup.

Published 11 June 2026Updated 11 June 2026Technical primer for developers and operations teams
Checksum = structural check only. Passing the Luhn test means the first 12 digits produce the expected 13th digit. It does not prove the number exists on Home Affairs records or belongs to the person who entered it. CheckID applies this formula in memory and does not store submitted ID numbers.

The 13th digit of a South African ID number is a Luhn checksum. When teams ask for SA ID checksum explained in plain language, they usually want to know why two numbers that look almost identical can produce different validation outcomes — and whether checksum failure always means fraud.

Checksum failure usually means a typo, transposed digit, or fabricated number that does not satisfy the published formula. It is a fast hygiene signal, not proof of identity theft and not a government database result.

The algorithm CheckID uses

Given a 13-digit string, treat positions 1–12 (zero-indexed: digits at indices 0–11) as the payload and digit 13 (index 12) as the check digit:

  1. For even positions (2nd, 4th, 6th … 12th digits), double the digit. If the result is two digits, add those digits together (for example 18 → 1 + 8 = 9).
  2. Sum all transformed even-position values.
  3. Sum all odd-position digits (1st, 3rd, 5th … 11th) without doubling.
  4. Add both sums. The check digit is (10 − (total mod 10)) mod 10.
  5. The ID is checksum-valid only when digit 13 equals that calculated value.

This matches the implementation in CheckID's validator and API — the same rules described in our ID number structure guide.

Worked example: 8001015009087

The first twelve digits are 800101500908 (positions 1–12). Splitting by position:

  • Even positions (2, 4, 6, 8, 10, 12): digits 0, 1, 1, 0, 9, 8. After doubling and digit-summing (for example 9×2=18 → 1+8=9, 8×2=16 → 1+6=7), the transformed sum is 20.
  • Odd positions (1, 3, 5, 7, 9, 11): digits 8, 0, 0, 5, 0, 0 — summed unchanged = 13.
  • Check digit: 20 + 13 = 33 → (10 − 3) mod 10 = 7, matching digit 13.

So 8001015009087 passes checksum validation (subject also to date and citizenship rules).

Change the final digit to 6 while leaving the first twelve unchanged. The birth date segment still decodes to 1980-01-01, but isValid becomes false because the checksum no longer matches. That pattern appears frequently when applicants mistype the last digit on mobile keyboards.

Common real-world failure patterns

  • Transposed adjacent digits in the birth date segment (for example 801011 vs 800101).
  • Wrong citizenship digit (using 1 when the holder is an SA citizen encoded as 0).
  • Copied test numbers from outdated examples that fail current date rules even when the checksum once looked valid in a blog post.
  • Spreadsheet scientific notation mangling leading zeros — always import ID columns as text, then run structural validation.

Checksum validation in your workflow

Manual calculation does not scale. Use the homepage validator for spot checks, the ID Validator API for live forms, or bulk SA ID validation for imports. Full request and response field names live in the developer guide; compare plan limits on pricing.

For the full digit map including gender sequence and citizenship codes, read understanding SA ID numbers.

Stop hand-calculating checksums

CheckID applies the same Luhn rules as this guide — via the web tool or REST API — with zero ID storage on our servers.

Related articles