Library / SDK
brazilian-utils/python avatar
brazilian-utils/python

brutils validates and formats the Brazilian identifiers your forms keep rejecting

Biblioteca de utilitários projetada para validar, gerar e manipular dados de acordo com as particularidades do Brasil 🇧🇷

526 stars126 forksPythonMIT

At a glance

What is it?
brutils is a Python library for the Brazilian document and registry formats, offering validation, formatting, symbol stripping and generators for CPF, CNPJ, CEP, phone, PIS, voter ID, licence plate, legal process numbers and more, published on PyPI with no runtime surprises. It suits a Brazilian product team that keeps reimplementing check-digit rules, and the CEP lookup functions reach out to a network service.
Who is it for?
brutils fits a Brazilian product team that validates Brazilian identifiers in forms and imports and wants one maintained implementation of the check-digit rules instead of a copied regex per team. It does not fit a project that needs to validate against the real registry rather than the format, because the README is explicit that is_valid_cpf does not verify that a CPF exists, it only checks the digits.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the library covers, and how the functions are shaped

brutils is a library of utilities focused on solving the problems that come up daily in development of applications for Brazilian business, and the scope is large.

The catalogue covers CPF, the Brazilian individual taxpayer registry, CNPJ for companies, CEP for postal codes, phone numbers, email, dates, CNH for driver licences, vehicle licence plates, PIS for the social security registry, legal process numbers, RENAVAM for vehicle registrations, voter ID, IBGE state and municipality codes, national holidays, currency amounts, legal nature codes, and passports.

The shape of the API is consistent, and that consistency is the design. Each identifier type generally gets the same four operations: an is_valid function, a format function for display, a remove_symbols function to strip punctuation, and a generate function that produces a valid random value.

That symmetry is what makes the library pleasant to use. Once you know that CPF has is_valid_cpf, format_cpf, remove_symbols_cpf and generate_cpf, you know what every other type offers without reading its documentation, and you can write generic code over the set.

The package is published on PyPI as brutils, and the README carries badges for the version, the supported Python versions, the PyPI status and the monthly downloads. The latest release is v2.5.0 from 2026-06-30, with v2.4.0 from 2026-04-20 and v2.3.0 from 2025-10-07 before it, and the last push to the repository was on 2026-10-19.

Installing and using it

The install is a single pip command.

bash
pip install brutils

And the usage is a single import, as the README puts it: to use one of the utilities, just import the needed function.

python
>>> from brutils import is_valid_cpf
>>> is_valid_cpf('00011122233')
False

That is the whole getting-started story, and the simplicity is a deliberate choice rather than an accident of the documentation being thin.

The per-function documentation follows a fixed template, which is worth noting if you are reading the README as an API reference. Each entry states what it returns, whether it verifies existence or only format, the arguments with their types, and then a runnable example with the input and the output shown. The examples are written as doctest-style blocks with the `>>>` prompts, so they read as sessions rather than as fragments.

For example, the formatting entry for CPF shows both a valid and an invalid-looking case, and the documentation is explicit about the return type: a formatted string with visual symbols if the input is valid, and None if it is not.

python
>>> from brutils import format_cpf
>>> format_cpf('82178537464')
'821.785.374-64'
>>> format_cpf("55550207753")
'555.502.077-53'

And the generator returns a valid random string.

python
>>> from brutils import generate_cpf
>>> generate_cpf()
'17433964657'

The None-on-invalid convention is a design choice that will affect your code. A formatting function that returns None rather than raising means you have to handle the failure case at every call site, which is fine for display code but a decision you should make deliberately rather than discover.

Validation checks the format, not the registry

The most important line in the CPF documentation is the caveat, and it applies across the library.

The function returns whether the check digits of the given CPF correspond to its base number. This function does not verify the existence of the CPF, it only validates the format of the string.

That distinction is the one to internalise before you use this library anywhere near an identity check. A CPF that passes is_valid_cpf has a well-formed check digit relationship, nothing more. Whether that number belongs to a living person is not something a check-digit algorithm can tell you.

For a form that wants to catch typos, that is exactly what you want, and the library is genuinely useful. For anything resembling an identity or eligibility check, it is not sufficient, and pairing it with a registry consultation is a different project with different legal requirements.

The same shape applies to CNPJ and to the rest of the identifiers. The check-digit rules are the well-known ones, the algorithm is straightforward, and the value of the library is that it is one maintained implementation rather than a regex that someone copied from a blog post into a validation function.

The generate functions are the mirror image, and they have a different use: producing test data. A generator that produces structurally valid identifiers is what you want for fixtures, and the README's examples show outputs that differ on each call.

The CEP functions that reach out to the network

The CEP section is the one place where the library does something other than string manipulation, and it deserves its own look.

Alongside is_valid_cep, format_cep, remove_symbols_cep and generate_cep, there are two functions that look the other way: get_address_from_cep and get_cep_information_from_address.

The first takes a postal code and returns an address. The second does the reverse, taking an address and returning the CEP information for it. Both are network operations, and that changes the profile of the library from a pure utility into something with an external dependency at call time.

That matters in three ways. The first is reliability, because the calls depend on a service being up and a lookup succeeding. The second is latency, because a network call inside a form validation path is a different engineering problem from a check-digit computation. The third is privacy, because a postal code lookup sends the code, and the reverse lookup sends an address, to a service you did not choose.

So the sensible reading is that the validation, formatting, stripping and generation functions are the core of the library, and the two lookup functions are a convenience on top that you should consider carefully before putting them on a request path. The rest of the library is deterministic and offline, and those two are not.

Packaging, dependencies and the project structure

The project uses Poetry, and the pyproject.toml is short enough to describe the whole build.

The package is brutils at version 2.5.0, described as a utils library for specific Brazilian businesses, and the keywords are cpf, cnpj, cep, document, validation, brazil and brazilian.

The classifiers say Development Status 5 - Production/Stable, and the supported Python versions are 3.10 through 3.13, with Python 3 only.

The runtime dependencies are three: holidays, which is what backs the is_holiday function and is pinned to a range rather than an exact version, num2words at a pinned version, which is what converts a monetary value into text in Brazilian Portuguese for the convert_real_to_text function, and coverage, which is odd as a runtime dependency but is listed as one.

The dev tooling is ruff at a pinned version with line-length 80 and the isort rule set enabled, and the build backend is poetry-core.

The Makefile shows the developer workflow. The install target points git at a local .githooks directory, and it has a Windows-specific guard because the hooks need the execute bit, which is not a thing on Windows filesystems. The test target runs unittest discovery with PYTHONDONTWRITEBYTECODE set, again branching on whether the host is Windows. The check target runs ruff format --check and ruff check, and there is a shell target for a poetry shell.

The repository also carries the housekeeping files you would expect from a project with a code of conduct and a core team, with both Portuguese and English versions: CODE_OF_CONDUCT.md and CODE_OF_CONDUCT_EN.md, CONTRIBUTING.md and CONTRIBUTING_EN.md, CORE_TEAM.md and CORE_TEAM_EN.md, MAINTAINING.md, a CHANGELOG.md, and an old_versions_documentation/ directory. The README itself has an English counterpart at README_EN.md.

Where brutils is the wrong choice

Four cases argue against it.

The first is an identity or eligibility check. The README says is_valid_cpf does not verify that the CPF exists, only the format. If your requirement is that the number corresponds to a real person or a registered company, no amount of check-digit validation gets you there, and you need a registry consultation with its own legal and operational weight.

The second is a project outside Brazil that happens to have Brazilian users. The library is entirely Brazilian-domain, and it brings holidays and num2words as runtime dependencies. A codebase with a handful of Brazilian fields is better served by a small set of local functions than by a dependency whose only job is those fields.

The third is a server-side application that validates forms at scale and needs the CEP lookups. Those two functions call a network service, and putting them in a validation path means your availability depends on someone else's and your latency budget includes a round trip.

The alternative in the same direction is a general validation library such as the pydantic validators, or a schema library with custom types. The difference in approach is that brutils is a curated catalogue of one country's identifiers, each with the four operations you would write yourself, while a general validator gives you the composition machinery and expects you to encode the rules. For a team whose product is Brazilian by definition, the catalogue is a better fit and a smaller job. For a team with one form field in Brazil, the general library wins on dependency count.

Editorial conclusion

brutils fits a Brazilian product team that validates Brazilian identifiers in forms and imports and wants one maintained implementation of the check-digit rules instead of a copied regex per team. It does not fit a project that needs to validate against the real registry rather than the format, because the README is explicit that is_valid_cpf does not verify that a CPF exists, it only checks the digits. Install it with `pip install brutils`, import the specific function you need, and read the CEP lookup functions carefully, since they contact a network service and that is a different privacy and reliability profile from the rest of the library.

Frequently asked questions

What does brutils do?

It is a Python library for validating, formatting and generating Brazilian identifiers, covering CPF, CNPJ, CEP, phone numbers, email, dates, CNH, vehicle licence plates, PIS, legal process numbers, RENAVAM, voter ID, IBGE codes, holidays, currency, legal nature codes and passports. Most types get four functions: is_valid, format, remove_symbols and generate.

How do I install and use brutils?

Run `pip install brutils`, then import the function you need, for example `from brutils import is_valid_cpf`. The package is on PyPI as brutils and supports Python 3.10 through 3.13, with the current version being 2.5.0.

Does is_valid_cpf confirm that a CPF really exists?

No. The documentation is explicit that it returns whether the check digits correspond to the base number and does not verify the existence of the CPF, only the format of the string. The same applies to the other identifiers.

Which brutils functions make network calls?

get_address_from_cep, which returns an address for a postal code, and get_cep_information_from_address, which does the reverse. The rest of the library, validation, formatting, symbol removal and generation, works on strings alone and is deterministic.

What runtime dependencies does brutils have?

Three: holidays, pinned to a range from 0.58 to below 0.106, num2words at 0.5.14, and coverage. The package is built with poetry-core and uses ruff for formatting and linting with a line length of 80.

Official sources

  1. brazilian-utils/python on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/brazilian-utils-python.svg)](https://hysenlabs.com/projects/brazilian-utils-python)

Was this useful?