PHPackages                             lumensistemas/br-validation - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Validation &amp; Sanitization](/categories/validation)
4. /
5. lumensistemas/br-validation

ActiveLibrary[Validation &amp; Sanitization](/categories/validation)

lumensistemas/br-validation
===========================

Validators, generators, and formatters for Brazilian identifiers (CPF, CNPJ, PIS, Título de Eleitor, CNH, Renavam, placa de veículo, CNS, chave PIX, CEP, telefone, boleto bancário, and NF-e access key).

v1.0.0(3w ago)031↓100%1MITPHPPHP ^8.3CI passing

Since May 17Pushed 3w agoCompare

[ Source](https://github.com/lumensistemas/br-validation)[ Packagist](https://packagist.org/packages/lumensistemas/br-validation)[ RSS](/packages/lumensistemas-br-validation/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (2)Versions (2)Used By (1)

br-validation
=============

[](#br-validation)

[![Tests](https://github.com/lumensistemas/br-validation/actions/workflows/tests.yml/badge.svg)](https://github.com/lumensistemas/br-validation/actions/workflows/tests.yml)[![Latest Stable Version](https://camo.githubusercontent.com/3e5cb39c548031b5e69bf51d2975cd5b123d432f3ed2850c6eb7ccf00de73bd8/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6c756d656e73697374656d61732f62722d76616c69646174696f6e2e737667)](https://packagist.org/packages/lumensistemas/br-validation)[![Total Downloads](https://camo.githubusercontent.com/87ceecf26a445882342eab305a1310d73adb06470bdf423a0d1c7a4666f72919/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6c756d656e73697374656d61732f62722d76616c69646174696f6e2e737667)](https://packagist.org/packages/lumensistemas/br-validation)

Validators, generators, and formatters for Brazilian identifiers (CPF, CNPJ, PIS, Título de Eleitor, CNH, Renavam, placa de veículo, CNS, chave PIX, CEP, telefone, boleto bancário, and NF-e access key) in PHP. Framework-agnostic and dependency-free at runtime.

Requirements
------------

[](#requirements)

- PHP 8.3 or newer
- `ext-mbstring`

Installation
------------

[](#installation)

```
composer require lumensistemas/br-validation
```

Usage
-----

[](#usage)

### CPF

[](#cpf)

```
use LumenSistemas\BrValidation\Cpf;

Cpf::isValid('856.981.040-77');   // true
Cpf::isValid('85698104077');      // true (raw form also accepted)
Cpf::isValid('11111111111');      // false (all-equal sequence)
Cpf::isValid(85698104077);        // false (non-string input)

Cpf::format('85698104077');       // '856.981.040-77'
Cpf::normalize('856.981.040-77'); // '85698104077'

Cpf::generate(); // a valid 11-digit CPF
```

### CNPJ

[](#cnpj)

```
use LumenSistemas\BrValidation\Cnpj;

Cnpj::isValid('11.222.333/0001-81');      // true (legacy numeric)
Cnpj::isValid('12ABC34501DE35');          // true (alphanumeric, 2026 rules)
Cnpj::isValid('12abc34501de35');          // true (case-insensitive)
Cnpj::isValid('00000000000000');          // false (all-equal sequence)

Cnpj::format('11222333000181');           // '11.222.333/0001-81'
Cnpj::format('12abc34501de35');           // '12.ABC.345/01DE-35'
Cnpj::normalize(' 11.222.333/0001-81 '); // '11222333000181'

Cnpj::generateNumeric();      // a valid 14-digit numeric CNPJ
Cnpj::generateAlphanumeric(); // a valid alphanumeric CNPJ
```

### PIS / PASEP / NIS / NIT

[](#pis--pasep--nis--nit)

```
use LumenSistemas\BrValidation\Pis;

Pis::isValid('120.65328.70-5'); // true
Pis::isValid('12065328705');    // true (raw form also accepted)
Pis::isValid('00000000000');    // false (all-equal sequence)
Pis::isValid(12065328705);      // false (non-string input)

Pis::format('12065328705');     // '120.65328.70-5'
Pis::normalize('120.65328.70-5'); // '12065328705'

Pis::generate(); // a valid 11-digit PIS
```

The same 11-digit number is issued under four different government program names — PIS, PASEP, NIS, NIT — and shares a single mod-11 check digit. `Pis` validates any of them.

### Título de Eleitor

[](#título-de-eleitor)

```
use LumenSistemas\BrValidation\TituloEleitor;

TituloEleitor::isValid('1234 5678 0396'); // true (RJ)
TituloEleitor::isValid('123456780396');   // true (raw form also accepted)
TituloEleitor::isValid('123456789905');   // false (UF 99 is not a TSE code)
TituloEleitor::isValid('111111111111');   // false (all-equal sequence)

TituloEleitor::format('123456780396');    // '1234 5678 0396'
TituloEleitor::normalize('1234 5678 0396'); // '123456780396'

TituloEleitor::generate(); // a valid 12-digit título
```

The UF code in positions 9–10 is the TSE's own numbering (`01..28`), not the IBGE UF code. São Paulo (`01`) and Minas Gerais (`02`) follow a special rule: whenever a check-digit calculation yields remainder 0, the digit is bumped to 1.

### CNH

[](#cnh)

```
use LumenSistemas\BrValidation\Cnh;

Cnh::isValid('98765432109');         // true
Cnh::isValid('123.456.789-00');      // true (mask characters are stripped)
Cnh::isValid('12345678901');         // false (wrong check digits)
Cnh::isValid('11111111111');         // false (all-equal sequence)

Cnh::normalize(' 123.456.789-00 ');  // '12345678900'

Cnh::generate(); // a valid 11-digit CNH
```

The CNH número de registro has no canonical visual mask on the document, so no `format()` method is exposed — call `normalize()` for the 11-digit storage/display form.

### Renavam

[](#renavam)

```
use LumenSistemas\BrValidation\Renavam;

Renavam::isValid('01234567897');     // true
Renavam::isValid('98765432103');     // true
Renavam::isValid('00000000000');     // false (all-equal sequence)
Renavam::isValid(1234567897);        // false (non-string input)

Renavam::normalize(' 01234567897 '); // '01234567897'

Renavam::generate(); // a valid 11-digit Renavam
```

Like CNH, Renavam has no canonical visual mask on the CRLV, so no `format()` method is exposed — call `normalize()` for the 11-digit storage/display form. Pre-2007 nine-digit Renavams must be left-padded with zeros by the caller before validation.

### Placa de veículo

[](#placa-de-veículo)

```
use LumenSistemas\BrValidation\Placa;

Placa::isValid('ABC-1234'); // true (old format)
Placa::isValid('abc1234');  // true (case-insensitive)
Placa::isValid('ABC1D23');  // true (Mercosul format)
Placa::isValid('ABCD123');  // false (wrong shape)

Placa::format('ABC1234');   // 'ABC-1234'
Placa::format('abc1d23');   // 'ABC1D23'
Placa::normalize(' abc-1234 '); // 'ABC1234'

Placa::generateOld();       // a valid old-format placa
Placa::generateMercosul();  // a valid Mercosul placa
```

Old and Mercosul plates coexist on the road indefinitely (vehicles only switch to Mercosul on first registration or transfer), so this is an accept-both library, not a transitional one. Placas carry no check digit; only the shape is validated.

### CNS (Cartão Nacional de Saúde)

[](#cns-cartão-nacional-de-saúde)

```
use LumenSistemas\BrValidation\Cns;

Cns::isValid('120 6532 8705 0007'); // true (definitive)
Cns::isValid('900000000000008');    // true (provisional, starts with 9)
Cns::isValid('320653287050007');    // false (first digit must be 1, 2, 7, 8, or 9)
Cns::isValid('100000000060026');    // false (definitive with non-000/001 appendix)

Cns::format('120653287050007');     // '120 6532 8705 0007'
Cns::normalize('120 6532 8705 0007'); // '120653287050007'

Cns::generateDefinitive();   // a valid definitive CNS (first digit 1 or 2)
Cns::generateProvisional();  // a valid provisional CNS (first digit 7, 8, or 9)
```

Two structural shapes share one mod-11 check: definitive cards (first digit 1 or 2) carry the citizen's PIS in positions 1–11 and a `000`/`001` appendix in positions 12–14; provisional cards (first digit 7, 8, or 9) carry no internal structure. The validator enforces the appendix pattern for definitive cards so that arithmetically-conforming numbers the SUS would never issue are still rejected.

### Chave PIX

[](#chave-pix)

```
use LumenSistemas\BrValidation\Pix;

Pix::isValid('85698104077');                              // true (CPF key)
Pix::isValid('user@example.com');                         // true (email key)
Pix::isValid('+5511987654321');                           // true (phone key)
Pix::isValid('123e4567-e89b-42d3-a456-426614174000');     // true (EVP key)
Pix::isValid('11.222.333/0001-81');                       // true (CNPJ key)
Pix::isValid('not-a-key');                                // false

Pix::type('user@example.com');                            // 'email'
Pix::type('85698104077');                                 // 'cpf'

Pix::normalize('Test.User@Example.COM');                  // 'test.user@example.com'
Pix::normalize('856.981.040-77');                         // '85698104077'

Pix::generateEvp(); // a valid UUID v4 EVP key
```

`Pix` is a thin dispatcher over the five chave PIX shapes (CPF, CNPJ, e-mail, E.164 phone starting with `+55`, and UUID v4 EVP); CPF and CNPJ delegate to the existing validators. No `format()` method is exposed because the canonical display form depends on the type — use the type-specific `Cpf::format()` / `Cnpj::format()` when you need user-facing display.

### CEP

[](#cep)

```
use LumenSistemas\BrValidation\Cep;

Cep::isValid('01310-100');     // true
Cep::isValid('01310100');      // true (raw form also accepted)
Cep::isValid('0131010');       // false (too short)

Cep::format('01310100');       // '01310-100'
Cep::normalize('01310-100');   // '01310100'

Cep::generate(); // a shape-valid 8-digit CEP (not guaranteed to exist)
```

CEP has no check digit — this is shape validation only. Whether a given CEP corresponds to a real address requires a Correios lookup and is out of scope. All-equal sequences like `00000000` therefore pass; callers that need existence checks should integrate a lookup service separately.

### Phone

[](#phone)

```
use LumenSistemas\BrValidation\Phone;

Phone::isValid('(11) 98765-4321');  // true (mobile)
Phone::isValid('11987654321');      // true (mobile, raw)
Phone::isValid('(11) 3333-4444');   // true (landline)
Phone::isValid('+5511987654321');   // true (E.164)
Phone::isValid('11187654321');      // false (mobile must start with 9)

Phone::format('11987654321');       // '(11) 98765-4321'
Phone::format('1133334444');        // '(11) 3333-4444'
Phone::formatE164('11987654321');   // '+5511987654321'
Phone::normalize('+5511987654321'); // '11987654321'

Phone::generateMobile();    // a valid 11-digit mobile
Phone::generateLandline();  // a valid 10-digit landline
```

Enforces the post-2017 ANATEL mobile-9 mandate: 11-digit numbers must have a `9` as the first subscriber digit; 10-digit landlines must not. DDD is checked against the `11..99` range with no `0` in either position; semantic DDD allocation (which DDDs are actually issued by ANATEL) is left to callers, since the allocation list shifts over time.

### Boleto bancário

[](#boleto-bancário)

```
use LumenSistemas\BrValidation\Boleto;

Boleto::isValid('00190.12343 56789.012343 56789.012343 1 99990000010000'); // true (linha digitável)
Boleto::isValid('00190123435678901234356789012343199990000010000');       // true (raw)
Boleto::isValid('00191999900000100000123456789012345678901234');          // true (44-digit barcode)
Boleto::isValid('00191123435678901234356789012343199990000010000');       // false (wrong field-1 DV)

Boleto::format('00190123435678901234356789012343199990000010000');
// '00190.12343 56789.012343 56789.012343 1 99990000010000'

Boleto::normalize('00190.12343 56789.012343 56789.012343 1 99990000010000');
// '00190123435678901234356789012343199990000010000'

Boleto::generate(); // a valid 47-digit linha digitável
```

`Boleto::isValid` accepts either the 47-digit linha digitável or the 44-digit código de barras and dispatches by length. A linha digitável is valid iff all three of its mod-10 field DVs match AND the barcode it reconstructs to passes the mod-11 general DV check. Targets boletos bancários only; concessionária slips (48-digit utility shape) are out of scope.

### NF-e access key (chave de acesso)

[](#nf-e-access-key-chave-de-acesso)

```
use LumenSistemas\BrValidation\Nfe;

Nfe::isValid('35240111222333000181550010000000011123456788'); // true
Nfe::isValid('3524 0111 2223 3300 0181 5500 1000 0000 0111 2345 6788'); // true (masked)
Nfe::isValid('00000000000000000000000000000000000000000000');           // false (all-equal sequence)

Nfe::format('35240111222333000181550010000000011123456788');
// '3524 0111 2223 3300 0181 5500 1000 0000 0111 2345 6788'

Nfe::normalize('3524 0111 2223 3300 0181 5500 1000 0000 0111 2345 6788');
// '35240111222333000181550010000000011123456788'

Nfe::generate(); // a valid 44-digit access key
```

The same 44-digit shape and check-digit algorithm cover NF-e (modelo 55), NFC-e (modelo 65) and the broader SEFAZ document family (CT-e, MDF-e, BP-e). This validator does not constrain modelo.

Behavior
--------

[](#behavior)

- **Validation never throws.** `isValid` accepts any input type and returns `false` for non-string or malformed values. Callers can pass user input directly without `try/catch`.
- **All-equal sequences are rejected** by validators with a checksum (`11111111111`, `00000000000000`, …) even though some pass the underlying mod-11 algorithm — they are conventional placeholder values across the Brazilian validation ecosystem and never represent real identifiers. `Cep` and `Placa` are exceptions: neither carries a checksum to reject them against, so any shape-valid input is accepted and existence checks are left to the caller (Correios lookup for CEP, DETRAN for placa).
- **CNPJ is case-insensitive.** Letters in alphanumeric CNPJs are normalized to uppercase before validation and formatting; both `'12abc34501de35'` and `'12ABC34501DE35'` validate equivalently, and `format`always produces the canonical uppercase masked form.
- **Numeric CNPJs remain valid in perpetuity** alongside the 2026 alphanumeric format. This is an accept-both library, not a transitional one.
- **`format()` is tolerant.** When the input shape doesn't match the canonical form, `format()` returns the input unchanged rather than raising. It does not validate check digits — that is `isValid()`'s job.

Laravel integration
-------------------

[](#laravel-integration)

A companion package `lumensistemas/laravel-br-validation`is planned, providing `Rule` classes and a service provider. It will be linked here once published.

Development
-----------

[](#development)

```
composer install
composer test
```

License
-------

[](#license)

MIT. See [`LICENSE`](LICENSE).

###  Health Score

42

—

FairBetter than 88% of packages

Maintenance95

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

24d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/dfdf6591a8b2d844569545878fba113e9c8de3d9b9d48f5b25637c6f0353ffbd?d=identicon)[lucasvscn](/maintainers/lucasvscn)

---

Top Contributors

[![lucasvscn](https://avatars.githubusercontent.com/u/3482569?v=4)](https://github.com/lucasvscn "lucasvscn (33 commits)")

---

Tags

validatorvalidationphoneboletocorreioscepbrnfeDanfepixcpfcnpjbraziliansusplacacnhNISCNSbacenpistelefonefebrabandetranpasepnittitulo-eleitortserenavammercosulanatel

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/lumensistemas-br-validation/health.svg)

```
[![Health](https://phpackages.com/badges/lumensistemas-br-validation/health.svg)](https://phpackages.com/packages/lumensistemas-br-validation)
```

###  Alternatives

[respect/validation

The most awesome validation engine ever created for PHP

6.1k39.0M405](/packages/respect-validation)[propaganistas/laravel-phone

Adds phone number functionality to Laravel based on Google's libphonenumber API.

3.0k38.3M138](/packages/propaganistas-laravel-phone)[opis/json-schema

Json Schema Validator for PHP

64841.2M257](/packages/opis-json-schema)[robersonfaria/validation

Pacote Laravel para validações comuns ao Brasil(pt-BR) tipo: CNPJ,CPF,CEP,CNS

107.6k](/packages/robersonfaria-validation)[yiibr/yii2-br-validator

Provide validations and features for brazilian localization

14105.8k4](/packages/yiibr-yii2-br-validator)[stuyam/laravel-phone-validator

A phone validator for Laravel using the free Twilio phone lookup service.

2861.7k](/packages/stuyam-laravel-phone-validator)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
