Voter ID
The Brazilian voter registration number.
Validate
- JavaScript library
- Python library18 cases fail
- Go library18 cases fail
- Ruby library18 cases fail
- Rust library18 cases fail
- .NET library18 cases fail
- Erlang library18 cases fail
Validates a voter ID: an 8-digit sequential number, a 2-digit UF code (01 to 28) and 2 modulus 11 check digits, at most 12 digits (Resolução TSE nº 23.659/2021, art. 36).
- A 13-digit value is rejected. 2.4.0 accepted a 13-digit SP/MG form with a 9-digit sequential number.
- The TSE drops the leading zeros of the sequential number when it issues the ID. A shorter value is left-padded with zeros to 12 digits before the check:
123450159is checked as000123450159. At least one sequential digit is required, so the shortest accepted value has 5 digits. 2.4.0 rejected these shorter values. - No official source gives the weights of the check digits or the SP/MG rule that turns a remainder of 0 into 1. They follow community references.
- Mask characters: whitespace,
.,-and/, alone or in a run, around and between the0000 0000 00 00groups (the same onescpf.isValidreads). Any other character, a letter in particular, makes the value invalid. A separator inside a group is rejected, except between the digits of a sequential number written without its leading zeros, grouped from the right (123 4567 01 91). - Only a string is read. Any other type returns
false.
Pending decision
The reference (JS) accepts whitespace, dots, hyphens and slashes around and between the groups, with a shortened sequential number grouped from the right (123 4567 01 91). Until 2.4.0 it accepted whitespace and dots only. Other libraries accept digits only. See the open decision in docs/findings.md.
| Parameter | Type | Required |
|---|---|---|
value | string | yes |
| returns | boolean |
Check if a voter ID number is valid. A voter ID has at most 12 digits, so a 13-digit value is rejected.
- A voter ID is an 8-digit sequential number, a 2-digit federative union code (
01to28) and 2 check digits. - The TSE drops the leading zeros of the sequential number when it issues the ID, so a shorter value is read as the ID without them and left padded with zeros to 12 digits before it is checked (
123450159is checked as000123450159). At least one sequential digit is required: the shortest accepted value has 5 digits. - Whitespace, dots, hyphens and slashes are accepted around and between the groups. Any other character makes the value invalid.
- Resolução TSE nº 23.659/2021, art. 36, which revoked Resolução TSE nº 21.538/2003 (art. 140), fixes the layout, the federative union table and two check digits "determinados com base no 'Módulo 11'". It gives no weights and no rule per state: the weights, and the rule that turns a remainder of 0 into 1 for São Paulo (
01) and Minas Gerais (02), have no official source and follow the community references below.
import { generateVoterId, isValidVoterId } from '@brazilian-utils/brazilian-utils';
const voterId = generateVoterId('SP');
isValidVoterId(voterId); // true
isValidVoterId('102385010671'); // true (12 digits)
isValidVoterId('123450159'); // true (000123450159 issued without its leading zeros)
isValidVoterId('1234567880191'); // false (13 digits, more than the 12 the TSE allows)
isValidVoterId('123456780124'); // false (invalid check digits)Source: Resolução TSE nº 23.659/2021, art. 36 ("composto por até 12 algarismos", "os oito primeiros algarismos serão sequenciados, desprezando-se, na emissão, os zeros à esquerda"), brutils and siga0984.
Code: brazilian-utils/javascriptTry it with JavaScript isValidVoterId
Shared test cases (52) and the result in each library voterId.isValid
Format
- JavaScript library
- Python library24 cases fail
- Go library20 cases fail
- Ruby library26 cases fail
- Rust library21 cases fail
- .NET library23 cases fail
- Erlang library26 cases fail
Formats a voter ID with the grouping 0000 0000 00 00.
- A voter ID has at most 12 digits (Resolução TSE nº 23.659/2021, art. 36), so the function drops the digits after the 12th and has no 13-digit grouping. 2.4.0 grouped a 13-digit SP/MG value as
0000 0000 0 00 00. - The TSE drops the leading zeros of the sequential number when it issues the ID. By default a shorter value is formatted from the left, as a partial value.
options.padfirst left-pads it with zeros to 12 digits:123450159gives0001 2345 01 59. options.obfuscate(defaultfalse) hides the first 3 digits and the 2 check digits with*:***4 5678 01 **. The UF code stays visible.- No authority publishes a masking rule for the voter ID. The rule is an analogy with the one the Leis de Diretrizes Orçamentárias set for publishing a CPF ("ocultar os três primeiros dígitos e os dois dígitos verificadores", Lei nº 12.309/2010, art. 87, § 5º, repeated up to the LDO 2026, Lei nº 15.321/2025, art. 163), not a published norm.
- The mask hides by position. A voter ID given as a number has lost its leading zeros, so pass
padtogether withobfuscatefor it. - A number is read only when it is a safe non-negative integer. A negative, fractional, non-finite or unsafe number gives an empty string (2.4.0 read the digits of any number).
- A value with no digits (empty, or only letters and symbols) returns an empty string, even with
pad. options.obfuscateis applied afterpad, and is read for truthiness likepad: a non-boolean such as1hides the digits too, and0does not. The two can be combined (123450159gives***1 2345 01 **).
Pending decision
The reference (JS) formats only the characters an incomplete value has and returns an empty string for empty or invalid input. Other libraries return null. See the open decision in docs/findings.md.
| Parameter | Type | Required |
|---|---|---|
value | string | number | yes |
options | FormatVoterIdOptions | no |
options.pad | boolean | no |
options.obfuscate | boolean | no |
| returns | string |
Format a voter ID number with the 12-digit grouping 0000 0000 00 00.
- Options (
FormatVoterIdOptions):padleft pads the value with zeros up to 12 digits, restoring the leading zeros of a voter ID issued without them;obfuscatehides the first 3 digits and the 2 check digits, leaving the federative union code visible. The mask hides by position, so passpadwithobfuscatefor a voter ID given as a number, which has lost its leading zeros: without it the mask shifts onto the check digits. An empty value, or one without digits, gives''even withpad. - Without
pad, a shorter value is formatted from the left, as a partially typed ID. - Digits past the 12th are dropped.
- No authority publishes a masking rule for the voter ID, so
obfuscateapplies the one the Leis de Diretrizes Orçamentárias set for publishing a CPF ("ocultar os três primeiros dígitos e os dois dígitos verificadores", Lei nº 14.194/2021, art. 149, first set by Lei nº 12.309/2010, art. 87, § 5º), a number with the same structure.
import { formatVoterId } from '@brazilian-utils/brazilian-utils';
formatVoterId('123456780175'); // '1234 5678 01 75'
formatVoterId('123456780175', { obfuscate: true }); // '***4 5678 01 **'
formatVoterId('123450159', { pad: true }); // '0001 2345 01 59'
formatVoterId('123450159'); // '1234 5015 9' (read as a partially typed ID)Try it with JavaScript formatVoterId
Shared test cases (45) and the result in each library voterId.format
Parse
- JavaScript library
- Python library
- Go library3 cases fail
- Ruby library4 cases fail
- Rust library3 cases fail
- .NET library3 cases fail
- Erlang library
Removes voter ID formatting and keeps only digits, capped at 12 digits for every UF.
- A voter ID has at most 12 digits (Resolução TSE nº 23.659/2021, art. 36). 2.4.0 kept 13 digits when the UF digits were SP or MG.
- A shorter value is returned as it is, not padded.
voterId.isValidaccepts that form, andvoterId.formatwithpadrestores the zeros. - A number is read only when it is a safe non-negative integer. A negative, fractional, non-finite or unsafe number gives an empty string (2.4.0 read the digits of any number).
| Parameter | Type | Required |
|---|---|---|
value | string | number | yes |
| returns | string |
Remove voter ID formatting, keep only digits, and cap the result to 12 digits. A shorter value is kept as it is, without adding leading zeros.
import { parseVoterId } from '@brazilian-utils/brazilian-utils';
parseVoterId('1234 5678 01 75'); // '123456780175'
parseVoterId('12345 01 59'); // '123450159'Try it with JavaScript parseVoterId
Shared test cases (13) and the result in each library voterId.parse
Generate
Generates a valid random voter ID: 12 digits, unformatted, with the leading zeros of the sequential number kept.
state(a state code, orZZfor a voter ID issued abroad) sets the UF code. Letter case and surrounding whitespace are ignored (" sp "isSP); 2.4.0 read a lowercase code as unknown. An unknown value falls back toZZ(UF28).- The result always has 12 digits. The same ID without the leading zeros of its sequential number is valid too (
voterId.isValidreads it). - A value that is not a string also falls back to
ZZ; the function never throws forstate.
| Parameter | Type | Required |
|---|---|---|
state | StateCode | "ZZ" | no |
| returns | string |
Generate a valid random voter ID number. The optional state argument (StateCode, or "ZZ" for a voter ID issued abroad) sets the federative union code.
stateignores letter case and surrounding whitespace ('sp'is'SP'). An unknown state, or a value that is not a string, falls back to"ZZ"(UF28).- The result always has 12 digits, the leading zeros of the sequential number included; the same ID without them is valid too.
import { generateVoterId } from '@brazilian-utils/brazilian-utils';
generateVoterId(); // valid random voter ID (abroad, "ZZ")
generateVoterId('SP'); // valid random voter ID for Sao Paulo
generateVoterId('XX'); // falls back to "ZZ" instead of throwingSource: Lei nº 14.194/2021, art. 149, the CPF masking rule obfuscate borrows, first set by Lei nº 12.309/2010, art. 87, § 5º and repeated by the later LDOs (Lei nº 15.321/2025, art. 163, the one for 2026, repeats it).
Try it with JavaScript generateVoterId
Shared test cases (1) and the result in each library voterId.generate
Decode
Reads the fields of a voter ID: the sequential number, the federative union of the registration and the check digits.
- Returns
nullexactly whenvoterId.isValidreturnsfalse; the input rules are the same. - The result has
sequentialNumber(8 digits),federativeUnion(the code01to28),stateCode(the state code, ornullfor28, the voters abroad) andcheckDigits(2 digits). Codes are strings that keep their leading zeros. - A voter ID issued without the leading zeros of its sequential number is read as
voterId.isValidreads it, left-padded with zeros to 12 digits:123450159gives thesequentialNumber00012345. stateCodeis the federative union of the registration, not necessarily where the voter lives today.- Each call returns a new object.
| Parameter | Type | Required |
|---|---|---|
value | string | yes |
| returns | VoterIdInfo | null |
Read the fields of a voter ID, as a VoterIdInfo, or null when isValidVoterId would return false.
- Fields:
sequentialNumber(8 digits),federativeUnion(the code'01'to'28'),stateCode(aStateCode, ornullfor'28', the voters abroad) andcheckDigits(2 digits). Codes are strings that keep their leading zeros. - A voter ID issued without the leading zeros of its sequential number is read as
isValidVoterIdreads it, left padded with zeros to 12 digits:'123450159'gives thesequentialNumber'00012345'. - The
stateCodeis the federative union of the registration, not necessarily where the voter lives today.
import { getVoterIdInfo } from '@brazilian-utils/brazilian-utils';
getVoterIdInfo('1023 8501 06 71');
// {
// sequentialNumber: '10238501',
// federativeUnion: '06',
// stateCode: 'PR',
// checkDigits: '71',
// }
getVoterIdInfo('000000002801'); // { sequentialNumber: '00000000', federativeUnion: '28', stateCode: null, checkDigits: '01' }
getVoterIdInfo('123456780124'); // null (invalid check digits)Source: Resolução TSE nº 23.659/2021, art. 36.
Code: brazilian-utils/javascriptTry it with JavaScript getVoterIdInfo
Shared test cases (26) and the result in each library voterId.getInfo
Official sources
Last updated on
