esponsor / dni-validator
Validators for Latin American and related national ID documents with Laravel validation rules
Requires
- php: ^8.4
- illuminate/contracts: ^10|^11|^12
Requires (Dev)
- pestphp/pest: ^3.0
This package is auto-updated.
Last update: 2026-08-11 22:27:27 UTC
README
Validators for Latin American and related national ID documents. Available as both a PHP/Laravel package and a JavaScript/TypeScript package. Both packages implement the same rules and are covered by the same shared test vectors.
Supported documents
| Country | Type | Validation | PHP class | JS import |
|---|---|---|---|---|
| π¦π· Argentina | CUIT/CUIL |
Prefix + modulo-11 check digit | CuitCuilArgentina |
/argentina |
| π§π· Brazil | CPF |
Two modulo-11 check digits | CpfBrazil |
/brazil |
| π§π· Brazil | CNPJ |
Two modulo-11 check digits | CnpjBrazil |
/brazil |
| π¨π¦ Canada | SIN |
Luhn check digit | SinCanada |
/canada |
| π¨π± Chile | RUT |
Modulo-11 check digit | RutChile |
/chile |
| π¨π΄ Colombia | CC |
Structural only β 8 or 10 digits | CcColombia |
/colombia |
| π¨π΄ Colombia | NIT |
Structural only β 10 digits, check digit not verified | NitColombia |
/colombia |
| π¨π΄ Colombia | PASS |
Length only β 2 to 12 characters | PassportColombia |
/colombia |
| πͺπ¨ Ecuador | CI |
Structural only β 10 digits, check digit not verified | CiEcuador |
/ecuador |
| πͺπ¨ Ecuador | RUT |
Structural only β 13 digits, check digit not verified | RutEcuador |
/ecuador |
| πͺπ¨ Ecuador | PASS |
Length only β 8 to 12 characters | PassportEcuador |
/ecuador |
| πͺπΈ Spain | DNI |
Modulo-23 check letter (covers DNI and NIE) | DniSpain |
/spain |
| π²π½ Mexico | CURP |
Regex + weighted checksum | CurpMexico |
/mexico |
| π΅πͺ Peru | DNI |
Structural only β 8 digits plus optional verification character | DniPeru |
/peru |
| π΅πͺ Peru | RUC |
Structural only β 11 digits with a known taxpayer prefix | RucPeru |
/peru |
| πΊπΈ United States / π΅π· Puerto Rico | SSN |
Structural only β rejects ranges the SSA never issues | SsnUnitedStates |
/united-states |
| πΊπΎ Uruguay | CI |
Weighted check digit | CiUruguay |
/uruguay |
| πΊπΎ Uruguay | RUT |
Modulo-11 check digit | RutUruguay |
/uruguay |
Rows marked Structural only or Length only verify shape or length, not a checksum: a well-formed value can still be a number that was never issued.
PHP
Install
composer require esponsor/dni-validator
Requires PHP ^8.4 and illuminate/contracts ^10|^11|^12.
Direct usage
Every validator exposes validate(). Most also expose clean() (strip formatting) and
format() (apply the country's display format); passport validators only expose validate(),
and RutEcuador has no display format.
use Esponsor\DniValidator\CpfBrazil; use Esponsor\DniValidator\RutChile; $rut = new RutChile(); $rut->validate('11.111.111-1'); // true $rut->clean('11.111.111-1'); // '111111111' $rut->format('111111111'); // '11.111.111-1' $cpf = new CpfBrazil(); $cpf->validate('111.444.777-35'); // true $cpf->format('11144477735'); // '111.444.777-35'
Laravel validation rules
Each validator has a matching rule under Esponsor\DniValidator\Rules named after the
validator class (CpfBrazil β CpfBrazilRule). Rules reject non-string values and fail with a
Spanish message.
use Esponsor\DniValidator\Rules\CpfBrazilRule; use Esponsor\DniValidator\Rules\RutChileRule; $request->validate([ 'rut' => ['required', 'string', new RutChileRule()], 'cpf' => ['required', 'string', new CpfBrazilRule()], ]);
Registry
Country and document type are matched case insensitively.
use Esponsor\DniValidator\DocumentValidatorRegistry; DocumentValidatorRegistry::validate('CL', 'RUT', '11.111.111-1'); // true DocumentValidatorRegistry::validate('ar', 'cuit/cuil', '20-12345678-6'); // true $validator = DocumentValidatorRegistry::for('UY', 'RUT'); $validator->format('211003360014'); // '21-100336-001-4' DocumentValidatorRegistry::for('CL', 'UNKNOWN'); // null
Running PHP tests
composer install vendor/bin/pest
JavaScript / TypeScript
Install
npm install @esponsor/dni-validator
Requires Node 22+. The published npm package is the repo root package.json; packages/js holds sources and tests only.
Named imports
Import from the country subpath, or from the package root for everything at once. Function
names are suffixed with the country when the same document type exists in several countries
(ciUruguayValidate, ciEcuadorValidate, dniPeruValidate, dniSpainValidate).
import { rutValidate, rutFormat } from '@esponsor/dni-validator/chile'; import { cpfValidate, cnpjValidate } from '@esponsor/dni-validator/brazil'; import { rutUruguayValidate, ciUruguayValidate } from '@esponsor/dni-validator/uruguay'; rutValidate('11.111.111-1'); // true cpfValidate('111.444.777-35'); // true
Registry
Country and document type are matched case insensitively.
import { getValidator } from '@esponsor/dni-validator'; const validator = getValidator('uy', 'rut'); validator?.validate('211003360014'); // true validator?.format?.('211003360014'); // '21-100336-001-4' getValidator('CL', 'UNKNOWN'); // null
Running JS tests
npm --prefix packages/js install
npm test
Contributing
See CONTRIBUTING.md. Security reports: SECURITY.md.
Shared specs
spec/<cc>/<type>.json is the language-independent contract for each document
(valid, invalid with reasons, optional format_cases, and metadata). Both the PHP and
JS test suites load these files through the registry, so the two runtimes cannot drift apart.
See spec/README.md for the schema.
Behaviour notes
These validators were ported from the eSponsor front-end helper. The following differences are deliberate fixes:
- CL RUT
validate()accepts only digits and conventional separators (.,-, spaces,K). The body is limited to 1β8 digits and the check digit is computed digit-by-digit (no whole-body integer conversion).clean()may still strip other characters when formatting. - BR CPF rejects repeated-digit values such as
111.111.111-11, which pass the checksum but are not issued.CNPJalready rejected them. - UY CI requires 7 or 8 digits before checking the digit. Without the length guard a 12-digit Uruguayan RUT could be accepted as a CI.
- PE DNI requires 8 digits plus an optional verification character, instead of any 8 to 9
characters drawn from
0-9andA-K. - ES DNI/NIE and PE DNI normalise their input (uppercase, punctuation stripped) before validating, like every other validator in the package.
- PE DNI
format()groups 8 digits plus the verification character (12345678-K), matching the documented placeholder.
License
MIT β Copyright (c) 2026 eSponsor