{"id":13405738,"url":"https://github.com/poliquin/brazilnum","last_synced_at":"2026-03-17T21:35:41.108Z","repository":{"id":22642589,"uuid":"25985491","full_name":"poliquin/brazilnum","owner":"poliquin","description":"Python functions for CNPJ, CEI, CPF, PIS/PASEP, CEP, and município numbers from Brazil.","archived":false,"fork":false,"pushed_at":"2024-07-10T20:33:45.000Z","size":86,"stargazers_count":97,"open_issues_count":3,"forks_count":10,"subscribers_count":7,"default_branch":"master","last_synced_at":"2026-01-04T03:20:50.326Z","etag":null,"topics":["brazil","cnpj","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/poliquin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-10-30T19:01:34.000Z","updated_at":"2024-05-23T14:11:25.000Z","dependencies_parsed_at":"2024-10-26T01:39:39.286Z","dependency_job_id":"189aff38-b292-40ad-bc65-ac81da37afc1","html_url":"https://github.com/poliquin/brazilnum","commit_stats":{"total_commits":67,"total_committers":1,"mean_commits":67.0,"dds":0.0,"last_synced_commit":"707cb5ecf5972b356fdb17024e3b5883e3df34b2"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/poliquin/brazilnum","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/poliquin%2Fbrazilnum","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/poliquin%2Fbrazilnum/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/poliquin%2Fbrazilnum/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/poliquin%2Fbrazilnum/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/poliquin","download_url":"https://codeload.github.com/poliquin/brazilnum/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/poliquin%2Fbrazilnum/sbom","scorecard":{"id":740106,"data":{"date":"2025-08-11","repo":{"name":"github.com/poliquin/brazilnum","commit":"707cb5ecf5972b356fdb17024e3b5883e3df34b2"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-22T17:11:43.110Z","repository_id":22642589,"created_at":"2025-08-22T17:11:43.110Z","updated_at":"2025-08-22T17:11:43.110Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30632050,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-17T17:32:55.572Z","status":"ssl_error","status_checked_at":"2026-03-17T17:32:38.732Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["brazil","cnpj","python"],"created_at":"2024-07-30T19:02:10.028Z","updated_at":"2026-03-17T21:35:41.090Z","avatar_url":"https://github.com/poliquin.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"Validate Brazilian Identification Numbers\n=========================================\n\nPython functions for working with CNPJ, CEI, CPF, PIS/PASEP, CEP, and município\nnumbers, which identify firms, people, and places in Brazil.\n\nInstallation\n------------\n\n    pip install brazilnum\n\nUsage Examples\n--------------\n\nWorks with Python 2.7 and 3.\n\n\n#### Validation Functions\nValidate a CNPJ number for a firm, in this case Telefônica Brasil:\n\n    \u003e\u003e\u003e from brazilnum.cnpj import validate_cnpj\n    \u003e\u003e\u003e validate_cnpj('02.558.157/0001-62')\n    True\n    \u003e\u003e\u003e validate_cnpj('02.558.157/0001-55')\n    False\n\nInteger input that is too short due to missing zeros is auto-corrected:\n\n    \u003e\u003e\u003e validate_cnpj(2558157000162)\n    True\n    \u003e\u003e\u003e validate_cnpj(2558157000162, autopad=False)\n    False\n\nValidate a CEI number, used for businesses that do not require a CNPJ:\n\n    \u003e\u003e\u003e from brazilnum.cei import validate_cei\n    \u003e\u003e\u003e validate_cei('11.583.00249/85')\n    True\n    \u003e\u003e\u003e validate_cei('11.583.00249/84')\n    False\n    \u003e\u003e\u003e validate_cei(115830024985)\n    True\n\nValidate CPF and PIS/PASEP numbers for individuals:\n\n    \u003e\u003e\u003e from brazilnum.pis import validate_pis\n    \u003e\u003e\u003e validate_pis('125.6124.131-0')\n    True\n    \u003e\u003e\u003e validate_pis('111.6124.131-0')\n    False\n\n    \u003e\u003e\u003e from brazilnum.cpf import validate_cpf\n    \u003e\u003e\u003e validate_cpf('968.811.342-58')\n    True\n    \u003e\u003e\u003e validate_cpf('327.861.067-97')\n    False\n\nValidation functions work with integer and unformatted input:\n\n    \u003e\u003e\u003e validate_pis(12561241310)\n    True\n    \u003e\u003e\u003e validate_cpf(96881134258)\n    True\n    \u003e\u003e\u003e validate_pis('12561241310')\n    True\n    \u003e\u003e\u003e validate_cpf('32786106797')\n    False\n\n\n#### Formatting and Padding\nUse the format function when displaying identifiers:\n\n    \u003e\u003e\u003e from brazilnum.cnpj import format_cnpj\n    \u003e\u003e\u003e format_cnpj('02558157000162')\n    '02.558.157/0001-62'\n\n    \u003e\u003e\u003e from brazilnum.cei import format_cei\n    \u003e\u003e\u003e format_cei('115830024985')\n    '11.583.00249/85'\n\n    \u003e\u003e\u003e from brazilnum.pis import format_pis\n    \u003e\u003e\u003e format_pis('12561241310')\n    '125.6124.131-0'\n\n    \u003e\u003e\u003e from brazilnum.cpf import format_cpf\n    \u003e\u003e\u003e format_cpf('96881134258')\n    '968.811.342-58'\n\nThere is a helper function to remove formatting from identifiers; it always\nreturns a string:\n\n    \u003e\u003e\u003e from brazilnum.util import clean_id\n    \u003e\u003e\u003e clean_id('02.558.157/0001-62')\n    '02558157000162'\n\n    \u003e\u003e\u003e clean_id(115830024985)\n    '115830024985'\n\nYour data source probably stores identifiers as integers, so leading\nzeros are missing. You can pad and validate these in one step:\n\n    \u003e\u003e\u003e from brazilnum.cnpj import pad_cnpj\n    \u003e\u003e\u003e pad_cnpj(2558157000162, validate=True)\n    ('02558157000162', True)\n\n    \u003e\u003e\u003e pad_cnpj(2558157000155, validate=True)\n    ('02558157000155', False)\n\n    \u003e\u003e\u003e from brazilnum.cei import pad_cei\n    \u003e\u003e\u003e pad_cei(115830024985, validate=True)\n    ('115830024985', True)\n\nYou can skip the validation step:\n\n    \u003e\u003e\u003e pad_cnpj(2558157000155, validate=False)\n    '02558157000155'\n\nPadding works the same way for PIS/PASEP and CPF numbers:\n\n    \u003e\u003e\u003e from brazilnum.pis import pad_pis\n    \u003e\u003e\u003e pad_pis(12561241310, validate=True)\n    ('12561241310', True)\n\n    \u003e\u003e\u003e pad_pis(11161241310, validate=True)\n    ('11161241310', False)\n\n    \u003e\u003e\u003e from brazilnum.cpf import pad_cpf\n    \u003e\u003e\u003e pad_cpf(4193675866, validate=True)\n    ('04193675866', True)\n\n    \u003e\u003e\u003e pad_cpf(4193675867, validate=True)\n    ('04193675867', False)\n\n\n#### CNPJ Parsing\nThe first 8 digits of CNPJs identify a firm, and the following 4 digits\nidentify a specific business establishment owned by that firm.  Headquarters is\noften establishment 0001.  The ``cnpj_from_firm_id`` function will create a\nfull CNPJ from the first 8 digits and a given establishment number:\n\n    \u003e\u003e\u003e from brazilnum.cnpj import cnpj_from_firm_id\n    \u003e\u003e\u003e cnpj_from_firm_id('02.558.157')\n    '02558157000162'\n\n    \u003e\u003e\u003e cnpj_from_firm_id('02.558.157', establishment='0002')\n    '02558157000243'\n\n    \u003e\u003e\u003e cnpj_from_firm_id('02.558.157', establishment='0002', formatted=True)\n    '02.558.157/0002-43'\n\n\nCNPJ can be parsed into firm, establishment, and check digit components:\n\n    \u003e\u003e\u003e from brazilnum.cnpj import parse_cnpj\n    \u003e\u003e\u003e parse_cnpj('02.558.157/0001-62')\n    CNPJ(cnpj='02.558.157/0001-62', firm='02.558.157', establishment='0001', check='62', valid=True)\n\n    \u003e\u003e\u003e parse_cnpj('02.558.157/0001-62', formatted=False)\n    CNPJ(cnpj=2558157000162, firm=2558157, establishment=1, check=(6, 2), valid=True)\n\n\n#### CEP Parsing\n\nCódigos de Endereçamentos Postais (zip codes) can be formatted and parsed:\n\n    \u003e\u003e\u003e from brazilnum.cep import format_cep, parse_cep\n    \u003e\u003e\u003e format_cep(13165000)\n    '13165-000'\n\n    \u003e\u003e\u003e format_cep(1002010)\n    '01002-010'\n\n    \u003e\u003e\u003e format_cep(73080)\n    '73080-000'\n\n    \u003e\u003e\u003e parse_cep('01255-080', numeric=True)\n    CEP(cep=1255080, region=0, subregion=1, sector=12, subsector=125, division=1255, suffix=80)\n\n    \u003e\u003e\u003e parse_cep('01255-080', numeric=False)\n    CEP(cep='01255-080', region='0', subregion='01', sector='012', subsector='0125', division='01255', suffix='080')\n\nCorreios has more information about the [structure of CEP](http://www.correios.com.br/para-voce/precisa-de-ajuda/o-que-e-cep-e-por-que-usa-lo/estrutura-do-cep).\n\n\n#### Municípios (Municipalities)\n\nValidation of IBGE município (municipal) identifiers is also possible:\n\n    \u003e\u003e\u003e from brazilnum.muni import validate_muni\n    \u003e\u003e\u003e validate_muni(3550308)  # São Paulo\n    True\n\n    \u003e\u003e\u003e validate_muni(4305871)  # Coronel Barros (see note below)\n    True\n\n**Note** that 9 true codes do not follow the correct verification pattern. ENCAT\nhas a [technical note](http://www.sefaz.al.gov.br/nfe/notas_tecnicas/NT2008.004.pdf)\nabout this issue. The program correctly handles special codes like Coronel\nBarros, RS (see above).\n\nIf you need a list of municípios with names and coordinates, see\n[poliquin/br-localidades](https://github.com/poliquin/br-localidades). If you\nneed historical and current codes with names, see\n[paulofreitas/dtb-ibge](https://github.com/paulofreitas/dtb-ibge).\n\n\n#### Random Identifiers\nIf you need random CNPJ for database testing, use the ``random_cnpj`` function,\nwhich can return either unformatted or formatted identifiers:\n\n    from brazilnum.cnpj import random_cnpj\n    random_cnpj()       # for a random, formatted CNPJ\n    random_cnpj(False)  # for a random, unformatted CNPJ\n\nUse ``random_cei`` for random CEI identifiers:\n\n    from brazilnum.cei import random_cei\n    random_cei()\n\nThe same thing exists for PIS/PASEP and CPF identifiers:\n\n    from brazilnum.pis import random_pis\n    random_pis()\n\n    from brazilnum.cpf import random_cpf\n    random_cpf()\n\n\n#### Check Digits\nIf you're interested in the check digits, there are functions for\ncalculating them that return integers:\n\n    \u003e\u003e\u003e from brazilnum.cnpj import cnpj_check_digits\n    \u003e\u003e\u003e cnpj_check_digits('02.558.157/0001-62')\n    (6, 2)\n\n    \u003e\u003e\u003e from brazilnum.cei import cei_check_digit\n    \u003e\u003e\u003e cei_check_digit('11.583.00249/85')\n    5\n\n    \u003e\u003e\u003e from brazilnum.cpf import cpf_check_digits\n    \u003e\u003e\u003e cpf_check_digits('041.936.758-66')\n    (6, 6)\n\n    \u003e\u003e\u003e from brazilnum.pis import pis_check_digit\n    \u003e\u003e\u003e pis_check_digit('125.6124.131-0')\n    0\n\nCNPJ check digits are calculated from the first 12 digits:\n\n    \u003e\u003e\u003e cnpj_check_digits('025581570001')\n    (6, 2)\n\nThe CEI check digit is calculated from the first 11 digits:\n\n    \u003e\u003e\u003e cei_check_digit('11583002498')\n    5\n\nCPF check digits are calculated from the first 9 digits:\n\n    \u003e\u003e\u003e cpf_check_digits('041936758')\n    (6, 6)\n\nThe PIS/PASEP check digit is calculated from the first 10 digits:\n\n    \u003e\u003e\u003e pis_check_digit('1256124131')\n    0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpoliquin%2Fbrazilnum","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpoliquin%2Fbrazilnum","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpoliquin%2Fbrazilnum/lists"}