The NIT check digit is computed by multiplying each digit, right to left, by a series of primes (3, 7, 13…), summing and taking the remainder modulo 11; it catches typing errors, not whether the taxpayer exists.
1. What the check digit is#
A Colombian NIT is written as 890.903.938-8: the last number, after the hyphen, is the check digit (DV, from dígito de verificación). It is computed from the other digits with a modulo-11 method and detects typing errors when the number is captured in a form, an invoice or a database.
Validating the DV is a mathematical check. A NIT with the right DV may belong to no taxpayer, and a nonexistent one can pass the validation. To confirm that a taxpayer exists you have to consult the RUT or the DIAN's services.
Documentation: Siempre al Día: NIT check digit (Spanish) ↗
2. The algorithm step by step#
The sources consulted agree on the steps: take the NIT digits without the DV, from right to left; multiply each by its weight from the prime series 3, 7, 13, 17, 19, 23, 29, 37, 41, 43, 47, 53, 59, 67 and 71; add the products and take the remainder of dividing by 11. If the remainder is 0 or 1, that is the DV; if it is larger, the DV is 11 minus the remainder.
| Digit (right to left) | Weight | Product |
|---|---|---|
| 8 | 3 | 24 |
| 3 | 7 | 21 |
| 9 | 13 | 117 |
| 3 | 17 | 51 |
| 0 | 19 | 0 |
| 9 | 23 | 207 |
| 0 | 29 | 0 |
| 9 | 37 | 333 |
| 8 | 41 | 328 |
| Total | — | 1,081 |
With NIT 890903938 (whose published DV in the source is 8), the products add up to 1,081. Since 1,081 divided by 11 leaves a remainder of 3, the DV is 11 − 3 = 8.
One of the guides consulted applies the weights left to right; the calculation that reproduces the published example is the right-to-left one, which is the one this guide's code uses.
Documentation: Lookuptax: Colombia NIT guide (Spanish) ↗ · Actualícese: check digit calculator (Spanish) ↗
3. Code in Python and JavaScript#
Both functions accept the NIT with dots or hyphens, ignore any character that is not a digit and reject numbers longer than 15 digits, the length of the weight series. The test cases are example NITs and their DV calculated with the same method.
WEIGHTS = (3, 7, 13, 17, 19, 23, 29, 37, 41, 43, 47, 53, 59, 67, 71)
def check_digit(nit: str) -> int:
"""Check digit (modulo 11) of a NIT without its final digit."""
digits = [c for c in nit if c.isdigit()]
if not digits or len(digits) > len(WEIGHTS):
raise ValueError("the NIT must have between 1 and 15 digits")
total = sum(int(d) * p for d, p in zip(reversed(digits), WEIGHTS))
remainder = total % 11
return remainder if remainder < 2 else 11 - remainder
def is_valid(full_nit: str) -> bool:
"""Validates a NIT with its final digit: '890.903.938-8' or '8909039388'."""
only = [c for c in full_nit if c.isdigit()]
return len(only) >= 2 and check_digit("".join(only[:-1])) == int(only[-1])
for nit, dv in [("890903938", 8), ("800197268", 4), ("899999068", 1), ("900123456", 8)]:
print(nit, check_digit(nit), check_digit(nit) == dv)
print(is_valid("890.903.938-8"), is_valid("890.903.938-7"))const WEIGHTS = [3, 7, 13, 17, 19, 23, 29, 37, 41, 43, 47, 53, 59, 67, 71];
function checkDigit(nit) {
const digits = [...String(nit)].filter(c => c >= "0" && c <= "9").reverse();
if (digits.length === 0 || digits.length > WEIGHTS.length) throw new Error("the NIT must have between 1 and 15 digits");
const total = digits.reduce((acc, d, i) => acc + Number(d) * WEIGHTS[i], 0);
const remainder = total % 11;
return remainder < 2 ? remainder : 11 - remainder;
}
function isValid(nitCompleto) {
const only = [...String(nitCompleto)].filter(c => c >= "0" && c <= "9");
return only.length >= 2 && checkDigit(only.slice(0, -1).join("")) === Number(only.at(-1));
}
console.log(checkDigit("890903938"), isValid("890.903.938-8"), isValid("890.903.938-7"));Documentation: Python: str.isdigit ↗ · MDN: Array.prototype.reduce ↗
4. What the validation does not tell you#
The DV only proves that the digits are consistent with each other. Three things stay out:
- Existence: a NIT with a correct DV may not be registered in the RUT.
- Identity: it does not say who owns it or whether it is active.
- Document type: a natural person's ID number is validated with the same method when used as a NIT, but a number that is not a NIT can match by chance.
Validate the DV in the form to ask the user to fix a typing error, and confirm against the official source when the data has consequences, such as an electronic invoice.
5. Good practices when implementing it#
- Store the NIT and the DV separately, and compute the DV when displaying to detect corrupted data.
- Normalize before comparing: remove dots, spaces and hyphens to find duplicates.
- Write tests with known NITs, including those that give remainder 0 and 1, because that is where implementations with a rule error break.
- Do not use this validation as a security control or as proof of identity.
6. Keep your numbers current#
The weights and the modulo-11 rule are stable, but DIAN regulation on the NIT and the RUT changes. The sources of this guide are accounting and tax guides read on October 18, 2026; confirm with the DIAN before using the validation in regulated processes.
- Check the official source again when integrating with electronic invoicing.
- Include tests with remainders 0 and 1 in your suite.
- If you store tax IDs from other countries, do not apply this rule to them.
Sources and scope
Documentation checked on October 18, 2026. Examples and decision criteria are editorial proposals; adapt them to your application's contract and validate them in an authorized test environment.