Boleto

Boleto de cobrança bancária and boleto de arrecadação: linha digitável and barcode validation, formatting, parsing and decoding.

  • Parity matrix

Validate

Validates a boleto: the 47-digit cobrança bancária linha digitável or its 44-digit barcode, or a boleto de arrecadação as its 48-digit linha digitável or 44-digit barcode.

  • The function verifies every check digit of the chosen layout (per Carta-Circular BCB 2.926/2000 and the FEBRABAN arrecadação layout).
  • The código de moeda (position 4 of the barcode and of the linha digitável) must be 9 (real), the only code Carta-Circular BCB 2.926/2000 assigns. 2.4.0 accepted any digit there.
  • The one exception is the FEBRABAN Convenção da Cobrança "Situação 2" slip of an institution identified only by its ISPB: bank code 988, código de moeda 0, fator de vencimento 0000, and the ISPB padded with zeros to 10 digits in barcode positions 10 to 19, where the amount would be. Bank 988 with código de moeda 9 is an ordinary slip.
  • The cobrança bancária barcode has 44 digits: bank code, código de moeda 9, the módulo 11 check digit in position 5, fator de vencimento, amount and free field. It is checked by the same rules as the linha digitável. Until 2.4.0 this barcode was rejected.
  • A 44-digit value that starts with 8 is only ever an arrecadação barcode (the 8 is its product identifier). A cobrança bancária barcode of a bank code 8xx is not accepted, because the two layouts could not be told apart.
  • The mask characters (whitespace, ., - and /) are accepted between digits, a run of them included, and whitespace around the value. Any other character makes the value invalid: letters, punctuation or a mask character leading or trailing the digits. So a linha digitável wrapped in letters is rejected. Until 2.4.0 every non-digit was dropped.
  • A value that is not a string is invalid.
ParameterTypeRequired
valuestringyes
returnsboolean

Check if a boleto (brazilian payment method) is valid.

  • Accepts the 47 digit "cobrança bancária" linha digitável, its 44 digit barcode (bank code, código de moeda 9, the módulo 11 check digit in position 5, fator de vencimento, amount and free field) and, for the "boleto de arrecadação", either its 48 digit linha digitável or its 44 digit barcode. A 44 digit value starting with 8 is only ever an arrecadação barcode (the 8 is the FEBRABAN product identifier of the arrecadação), so a cobrança bancária barcode of a bank code from 800 to 899 (only 804 exists) is not accepted in barcode form, as the two could not be told apart; its 47 digit linha digitável is accepted. Up to 2.4.0 the cobrança bancária barcode was rejected.
  • The usual mask characters (whitespace, ., - and /) are accepted between digits; any other character makes the value invalid, so abc + a linha digitável + zzz is rejected, not read as its digits (up to 2.4.0 every non-digit was dropped).
  • The código de moeda (position 4 of the cobrança bancária barcode and linha digitável) must be 9 (real), the only code Carta-Circular BCB nº 2.926/2000 assigns. The one exception is the "Situação 2" slip of the FEBRABAN Convenção da Cobrança, issued by an institution identified only by its ISPB: bank code 988, código de moeda 0, fator de vencimento 0000 and the ISPB, padded with zeros, where the amount would be. Any other digit is rejected.
import { isValidBoleto } from '@brazilian-utils/brazilian-utils';

isValidBoleto('00190000090114971860168524522114675860000102656'); // true
isValidBoleto('00196758600001026560000001149718606852452211'); // true (cobrança bancária barcode)
isValidBoleto('846100000005246100291102005460339004695895061080'); // true (boleto de arrecadação)
isValidBoleto('00170000010114971860168524522114275860000102656'); // false (código de moeda 7)
isValidBoleto('abc00190000090114971860168524522114675860000102656zzz'); // false (letters around the digits)
isValidBoleto('98800000060114971860168524522114100000018236120'); // true (Situação 2: bank 988, moeda 0, ISPB)

Source: Carta-Circular BCB nº 2.926/2000, FEBRABAN, Layout Padrão de Arrecadação, Versão 08 (in force from 01/06/2026), FEBRABAN, Convenção da Cobrança.

Code: brazilian-utils/javascript
Try it with JavaScript isValidBoleto
The inputs start with the first shared case. Change one to see the new result.

Runs @brazilian-utils/brazilian-utils 2.5.0 in your browser.

Shared test cases (65) and the result in each library boleto.isValid

Format

Formats a boleto linha digitável with its printed mask.

  • The function groups the 47-digit cobrança bancária linha digitável as 00000.00000 00000.000000 00000.000000 0 00000000000000.
  • A 48-digit linha digitável starting with 8 (boleto de arrecadação) gets four blocks of 11 digits, each followed by its check digit. The 44-digit arrecadação barcode keeps the cobrança bancária mask, and a 44-digit value starting with 8 is always read as an arrecadação barcode.
  • Every character that is not a digit is removed first, so a masked value is accepted. Digits beyond the length of the pattern are dropped.
  • Without options.pad a short value is masked only as far as its digits go (104914 gives 10491.4).
  • A value with no digits (an empty string, abc, null) gives an empty string, even with options.pad. Until 2.4.0 pad: true returned the full zero mask for an empty string or one without digits.
  • options.pad left-pads the value with zeros to the length of the pattern before masking.
  • 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).
ParameterTypeRequired
valuestring | numberyes
optionsFormatBoletoOptionsno
options.padbooleanno
returnsstring

Format a boleto number.

  • Options (FormatBoletoOptions): pad left-pads the value with zeros to the length of the pattern before masking (default false). An empty value, or one without digits, gives '' even with pad.
  • A 48 digit linha digitável starting with 8 gets the arrecadação mask: four blocks of 11 digits, each followed by its check digit. The 44 digit arrecadação barcode keeps the "cobrança bancária" mask.
import { formatBoleto } from '@brazilian-utils/brazilian-utils';

formatBoleto('00190000090114971860168524522114675860000102656'); // 00190.00009 01149.718601 68524.522114 6 75860000102656
formatBoleto('1900000901149', { pad: true }); // 00000.00000 00000.000000 00000.000000 0 01900000901149
formatBoleto('846100000005246100291102005460339004695895061080'); // 84610000000-5 24610029110-2 00546033900-4 69589506108-0 (48 digit arrecadação linha digitável)
formatBoleto('84610000000246100291100054603390069589506108'); // 84610.00000 02461.002911 00054.603390 0 69589506108 (44 digit arrecadação barcode keeps the bancária mask)

Source: FEBRABAN, Layout Padrão de Arrecadação, Versão 08 (in force from 01/06/2026).

Code: brazilian-utils/javascript
Try it with JavaScript formatBoleto
The inputs start with the first shared case. Change one to see the new result.

Runs @brazilian-utils/brazilian-utils 2.5.0 in your browser.

Shared test cases (71) and the result in each library boleto.format

Parse

Removes every character that is not a digit from a boleto (mask, spaces, letters) and returns the digits, without checking that the boleto is valid.

  • The result is cut to 47 digits, or to 48 when the digits start with 8 (boleto de arrecadação). Digits beyond that are dropped.
  • 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).
ParameterTypeRequired
valuestring | numberyes
returnsstring

Remove boleto formatting, keep only digits, and cap the result to 47 digits (48 for boleto de arrecadação).

import { parseBoleto } from '@brazilian-utils/brazilian-utils';

parseBoleto('00190.00009 01149.718601 68524.522114 6 75860000102656'); // 00190000090114971860168524522114675860000102656

Source: Carta-Circular BCB nº 2.926/2000, FEBRABAN, Layout Padrão de Arrecadação, Versão 08 (in force from 01/06/2026).

Code: brazilian-utils/javascript
Try it with JavaScript parseBoleto
The inputs start with the first shared case. Change one to see the new result.

Runs @brazilian-utils/brazilian-utils 2.5.0 in your browser.

Shared test cases (10) and the result in each library boleto.parse

Generate

Generates a valid random boleto number.

  • By default, the function generates a 47-digit cobrança bancária linha digitável. With params.type set to arrecadação, it generates a 48-digit boleto de arrecadação instead.
  • A cobrança bancária slip gets a random 3-digit bank code, the código de moeda 9 (real) and a fator de vencimento of 0000 (no due date) or 1000 to 9999. Factors 0001 to 0999 denote no date and are never drawn.
  • A boleto de arrecadação draws its segment from 1 to 7 (segment 9 is the banks' own) and its value identifier from all four values (6 and 8 for an effective amount, 7 and 9 for a reference quantity), so hasEffectiveValue can be true or false.
  • boleto.isValid accepts the result.
  • It draws with Math.random(), so it is not cryptographically secure. Do not use it for security purposes.
ParameterTypeRequired
paramsGenerateBoletoParamsno
params.type"bancario" | "arrecadacao"no
returnsstring

Generate a valid random boleto.

  • Pass { type: 'arrecadacao' } (GenerateBoletoParams) for a 48 digit boleto de arrecadação instead of the default 'bancario' (cobrança bancária, 47 digits).
  • A cobrança bancária slip carries the código de moeda 9 and a fator de vencimento of 0000 (no due date) or 1000 to 9999; 0001 to 0999 denote no date.
import { generateBoleto } from '@brazilian-utils/brazilian-utils';

generateBoleto(); // "00190000090114971860168524522114675860000102656"
generateBoleto({ type: 'arrecadacao' }); // "846100000005246100291102005460339004695895061080"

Source: Carta-Circular BCB nº 2.926/2000, FEBRABAN, Layout Padrão de Arrecadação, Versão 08 (in force from 01/06/2026).

Code: brazilian-utils/javascript
Try it with JavaScript generateBoleto
The inputs start with the first shared case. Change one to see the new result.

Runs @brazilian-utils/brazilian-utils 2.5.0 in your browser.

Shared test cases (3) and the result in each library boleto.generate

Decode

Extracts the amount, due date and bank code from a boleto: the 47-digit linha digitável or the 44-digit barcode of a cobrança bancária slip, or a boleto de arrecadação. Returns null when the value is not a valid boleto.

  • The result has amount (in cents), expirationDate and bankCode (the 3-digit COMPE code).
  • The due date is null when the boleto carries no fator de vencimento (a factor below 1000).
  • The fator de vencimento cycle reset on 2025-02-22, so a factor maps to two dates 9000 days apart. No FEBRABAN or Banco Central publication tells the cycles apart; the rule comes from bank manuals. options.referenceDate resolves the cycle as of that date instead of today. Pass it whenever the answer has to stay stable, since the same slip can resolve to the other date as time passes.
  • The window around referenceDate is 3000 days back and 5500 days ahead, and the nearer candidate wins when neither falls inside it. A slip due up to 3499 days (about 9.5 years) before referenceDate keeps its date. One due 3500 days (about 9.6 years) or more before it is read as the next cycle (a date in the future). To read an old slip, pass a referenceDate near its issue date. The search never goes below the first cycle, so an older referenceDate still resolves a factor to the oldest date it can denote, never one before the 1997-10-07 base date.
  • A referenceDate that is not a valid Date (an invalid Date, a string, a number, null) is ignored and today is used. The call never throws. Until 2.4.0 an invalid Date gave the 1997 base date and a string or a number threw.
  • The 44-digit barcode is read for the same fields as the linha digitável: the amount from positions 10 to 19 and the fator de vencimento from positions 6 to 9. Until 2.4.0 a cobrança bancária barcode gave null. A value that is not a string gives null.
  • A 44-digit value that starts with 8 is always read as an arrecadação barcode, never as a cobrança bancária one: it gives the arrecadação result when it is a valid arrecadação barcode and null otherwise, even when it would be a valid barcode of a bank 8xx.
  • A boleto de arrecadação has no bank code and no due date: bankCode is "" and expirationDate is null. It also has type ("arrecadacao"), segment (1 to 7, or 9 for the banks' own use), value (the amount in reais, amount divided by 100) and hasEffectiveValue (whether the amount is an effective value or a reference quantity).
  • A FEBRABAN "Situação 2" slip (bank 988, código de moeda 0, see boleto.isValid) carries the issuer's 8-digit ISPB where the amount would be. The result has ispb set to that ISPB, amount set to 0 and expirationDate null. ispb is new in 2.5.0 and is absent on every other slip.
  • It returns null exactly when boleto.isValid returns false, so a slip with a código de moeda other than 9 gives null (2.4.0 decoded it).
ParameterTypeRequired
valuestringyes
optionsGetBoletoInfoOptionsno
options.referenceDateDateno
returnsBoletoInfo | null

Extract information from a boleto (amount, expiration date, bank code). Returns null when the value is not a valid boleto.

  • Options (GetBoletoInfoOptions): referenceDate resolves the "fator de vencimento" cycle as of that date instead of now.
  • Reads the 47 digit linha digitável and the 44 digit barcode of a cobrança bancária slip, and the arrecadação forms, the same way as isValidBoleto accepts them.
  • Returns a BoletoInfo: amount in cents, expirationDate and the three digit bankCode. expirationDate is null when the slip carries no fator de vencimento (a factor below 1000).
  • The fator de vencimento cycle reset on 22/02/2025, so a factor can mean either of two dates 9000 days apart. No FEBRABAN communiqué on the reset is published; the rule is in bank manuals, such as Bradesco's (Versão 17). referenceDate picks between them; pass it whenever the answer has to stay stable.
  • The windows are 3000 days back and 5500 days ahead of referenceDate: a slip due up to 3499 days (about 9.5 years) before it keeps its date, and one due 3500 days (about 9.6 years) or more before it is read as the next cycle (a date in the future), so to read an old slip pass a referenceDate near its issue date. A referenceDate that is not a valid Date is ignored and now is used.
  • A boleto de arrecadação has bankCode: '' and expirationDate: null, plus type: 'arrecadacao', segment, value (the amount in reais) and hasEffectiveValue.
  • A FEBRABAN Convenção da Cobrança "Situação 2" slip (bank code 988, código de moeda 0) carries the issuer's ISPB where the amount would be: it comes back as ispb, with amount: 0.
import { getBoletoInfo } from '@brazilian-utils/brazilian-utils';

getBoletoInfo('00190000090114971860168524522114675860000102656');
// { amount: 102656, expirationDate: Date, bankCode: '001' }

getBoletoInfo('00196758600001026560000001149718606852452211');
// same slip read from its 44 digit barcode

getBoletoInfo('00190000090114971860168524522114675860000102656', {
  referenceDate: new Date(2018, 6, 1)
});
// Resolves the fator de vencimento cycle as of 2018-07-01

getBoletoInfo('98800000060114971860168524522114100000018236120');
// { amount: 0, expirationDate: null, bankCode: '988', ispb: '18236120' }

getBoletoInfo('846100000005246100291102005460339004695895061080');
// { amount: 2461, expirationDate: null, bankCode: '', type: 'arrecadacao', segment: 4, value: 24.61, hasEffectiveValue: true }

getBoletoInfo('invalid'); // null

Source: Carta-Circular BCB nº 2.926/2000, FEBRABAN, Layout Padrão de Arrecadação, Versão 08 (in force from 01/06/2026), FEBRABAN, Convenção da Cobrança.

Code: brazilian-utils/javascript
Try it with JavaScript getBoletoInfo
The inputs start with the first shared case. Change one to see the new result.

Runs @brazilian-utils/brazilian-utils 2.5.0 in your browser.

Shared test cases (16) and the result in each library boleto.getInfo

Official sources

See also Banks

Last updated on

On this page