Cada número de conta bancária internacional (IBAN) carrega dois pequenos dígitos que realizam um trabalho surpreendentemente importante. Ficam logo após o código do país — nas posições três e quatro — e são o detetor de erros incorporado do IBAN. Erre um único dígito em qualquer parte do número da conta e, na maioria das vezes, esses dois dígitos verificadores deixam de bater certo. O pagamento é recusado antes de um único cêntimo se mover.
Este guia explica como esses dígitos verificadores são calculados, por que o passo do módulo 97 é tão eficaz e como calculá-los ou verificá-los de forma fiável nos seus próprios sistemas.
O que são realmente os dígitos verificadores do IBAN
Os dois dígitos que se seguem ao código do país chamam-se formalmente dígitos verificadores. Não são aleatórios nem fazem parte do seu número de conta: são derivados do resto do IBAN através de uma fórmula matemática definida na norma ISO 7064 (a mesma família de normas por detrás de muitos outros esquemas de dígitos verificadores).
O objetivo é a integridade. Quando um cliente digita um IBAN num formulário de pagamento, os dedos escorregam: um 3 torna-se um 8, dois dígitos vizinhos trocam de lugar, um carácter é omitido. Os dígitos verificadores permitem que qualquer banco — ou o seu próprio código de validação — detete esses erros de imediato, sem contactar o banco de destino.
Pense nisso como um bit de paridade a uma escala muito maior: uma impressão digital compacta da referência da conta, que viaja juntamente com os dados que protege.
Como funciona o cálculo dos dígitos verificadores
A rotina de validação é enganadoramente simples. Tome um IBAN francês como FR76 3000 6000 0112 3456 7890 189. Para o verificar:
- Mova os quatro primeiros caracteres para o fim.
FR76passa para o final, ficando30006000011234567890189FR76. - Substitua cada letra por dois dígitos. Cada letra corresponde a um número:
A=10,B=11, …Z=35. Assim,F=15eR=27, transformandoFR76em15277 6. - Leia o resultado como um único inteiro grande e calcule
inteiro mod 97. - Se o resto for exatamente 1, o IBAN é válido. Qualquer outro resto significa que o número está corrompido.
É esse todo o algoritmo. A genialidade está no passo 4: os dígitos verificadores são escolhidos, no momento em que o IBAN é criado, precisamente para que esse resto dê 1.
Calcular os dígitos verificadores do zero
Gerar um IBAN novo executa o processo ao contrário:
- Monte o BBAN (o código do banco, o balcão e o número de conta específicos de cada país).
- Acrescente o código do país seguido de
00como marcador de posição dos dígitos verificadores. - Converta as letras em números e calcule o inteiro grande.
- Calcule
98 - (inteiro mod 97). - Complete o resultado com zeros até dois dígitos — esse é o seu par de dígitos verificadores.
Por exemplo, construir um IBAN alemão a partir de um BBAN válido produz algo como DE89 3704 0044 0532 0130 00, onde 89 é o par calculado. É exatamente isto que o gerador Random IBAN faz internamente para cada país compatível: constrói um BBAN estruturalmente correto e depois deriva os dígitos verificadores para que o número final passe no MOD-97.
Porquê módulo 97 (e não algo mais simples)?
Os criadores poderiam ter usado uma soma de verificação básica, do tipo «somar todos os dígitos». Escolheram o módulo 97 de forma deliberada, e essa escolha tem consequências reais para a fiabilidade.
- 97 é primo. Usar um módulo primo distribui os erros de forma uniforme e evita os pontos cegos que afetam os esquemas com módulos não primos.
- Deteta qualquer erro num único dígito. Altere um dígito qualquer e o resto muda — garantidamente.
- Deteta quase todas as transposições. Trocar dois caracteres vizinhos (um erro de digitação clássico) é detetado na esmagadora maioria dos casos.
- A taxa de deteção ronda os 98,9 % para erros aleatórios em vários caracteres — muito acima do que uma simples soma ou um único dígito verificador conseguiriam.
A contrapartida é que precisa de aritmética de inteiros grandes, porque um IBAN de 34 caracteres expande-se até um número com dezenas de dígitos. Na prática, isto não é problema: todas as linguagens comuns lidam com isso de forma nativa ou com uma biblioteca de uma única linha, e existe um truque por blocos (mais abaixo) que evita por completo os inteiros grandes.
Calcular os dígitos verificadores em código
Raramente precisa de um tipo inteiro grande. Pela forma como funciona a aritmética modular, pode processar o IBAN em pequenos blocos mantendo um resto acumulado. Esta é a abordagem canónica em várias linguagens.
JavaScript:
function isValidIban(iban) {
const s = iban.replace(/\s+/g, '').toUpperCase();
// Move first 4 chars to the end
const rearranged = s.slice(4) + s.slice(0, 4);
// Convert letters to numbers (A=10 ... Z=35)
const numeric = rearranged.replace(/[A-Z]/g, ch =>
(ch.charCodeAt(0) - 55).toString()
);
// Piece-wise mod 97 to avoid BigInt
let remainder = 0;
for (const digit of numeric) {
remainder = (remainder * 10 + Number(digit)) % 97;
}
return remainder === 1;
}
Python:
def is_valid_iban(iban: str) -> bool:
s = "".join(iban.split()).upper()
rearranged = s[4:] + s[:4]
numeric = "".join(
str(ord(c) - 55) if c.isalpha() else c
for c in rearranged
)
return int(numeric) % 97 == 1 # Python ints are arbitrary-precision
PHP:
function isValidIban(string $iban): bool {
$s = strtoupper(preg_replace('/\s+/', '', $iban));
$rearranged = substr($s, 4) . substr($s, 0, 4);
$numeric = '';
foreach (str_split($rearranged) as $ch) {
$numeric .= ctype_alpha($ch) ? (string)(ord($ch) - 55) : $ch;
}
// bcmod handles the large integer safely
return bcmod($numeric, '97') === '1';
}
As três seguem os mesmos quatro passos. A única diferença real está em como cada linguagem lida com o número grande: o Python usa inteiros grandes nativos, o PHP apoia-se em bcmod e o JavaScript contorna o problema com o ciclo de resto acumulado.
Valide cedo, valide duas vezes
Detetar um IBAN incorreto no momento certo poupa problemas a toda a gente. Algumas práticas que compensam de forma consistente:
- Valide primeiro no lado do cliente. Execute a verificação MOD-97 no navegador enquanto o utilizador escreve ou ao perder o foco, para que corrija o erro de imediato em vez de o fazer depois de submeter.
- Revalide no servidor. Nunca confie apenas no cliente: repita a verificação no backend para se proteger contra manipulações e pedidos automatizados.
- Normalize antes de verificar. Remova os espaços, passe tudo para maiúsculas e rejeite os caracteres fora de
A–Ze0–9antes de executar o algoritmo. - Separe os erros de formato dos erros de dígitos verificadores nas suas mensagens. «Este IBAN é demasiado curto para a Alemanha» é muito mais útil para um cliente do que um genérico «IBAN inválido».
Lembre-se do limite dos dígitos verificadores: confirmam que o número é estruturalmente correto, não que a conta exista. Um IBAN perfeitamente válido pode mesmo assim apontar para uma conta encerrada ou inexistente. Para isso, precisa da verificação da conta junto do banco ou de um serviço dedicado.
Gerar IBAN de teste válidos para os seus testes
Codificar um único IBAN no seu conjunto de testes é frágil, e usar um real é um risco de conformidade. Em vez disso, gere IBAN sintéticos com dígitos verificadores válidos a pedido.
Quando cria números com o Random IBAN, cada valor é construído com o método MOD-97 da norma ISO 13616, pelo que passa na validação em qualquer biblioteca compatível. Use-os para:
- Testar unitariamente as suas funções de validação com entradas válidas e inválidas conhecidas.
- Fazer QA de importações em massa exportando centenas de IBAN para CSV ou JSON.
- Demonstrar percursos de pagamento sem nunca tocar num número de conta real.
Combine-o com o validador de IBAN para confirmar que a sua própria implementação coincide com o algoritmo de referência, e volte a verificar os seus dados de teste sempre que um país atualizar o seu formato de IBAN. Para mais contexto sobre a própria norma, consulte o nosso guia sobre o que é um número IBAN.
FAQ
Porque há sempre exatamente dois dígitos verificadores?
A norma do IBAN fixa o campo dos dígitos verificadores em dois dígitos para todos os países, independentemente do comprimento total. Dois dígitos dão 100 valores possíveis, suficientes para satisfazer o requisito do módulo 97 (os restos vão de 0 a 96) mantendo o formato compacto e uniforme em todo o mundo.
Pode um IBAN errado passar mesmo assim na verificação MOD-97?
Sim, embora seja improvável. O algoritmo deteta cerca de 98,9 % dos erros aleatórios e todos os erros num único dígito, mas uma pequena fração dos erros em vários caracteres pode, por coincidência, produzir um resto de 1. A verificação garante a estrutura, não que a conta seja real ou correta.
Qual é a diferença entre os dígitos verificadores e os dígitos verificadores nacionais?
Os dois dígitos verificadores do IBAN (posições 3 e 4) protegem todo o IBAN através do MOD-97. Alguns países — Espanha, França, Itália e outros — incorporam também os seus próprios dígitos verificadores nacionais dentro do BBAN para proteger o número de conta nacional. São mecanismos distintos que operam em camadas diferentes.
Preciso de uma biblioteca de inteiros grandes para validar um IBAN?
Não necessariamente. O método do resto por blocos mostrado acima processa o número em pequenos passos mantendo um valor acumulado abaixo de 97, pelo que basta aritmética de inteiros normal. Só precisa de inteiros grandes se calcular int(numeric) % 97 de uma só vez, como faz o exemplo em Python.
Porque é que a conversão das letras usa A=10 em vez de A=1?
Cada letra expande-se para um número de dois dígitos, de 10 a 35. Começar em 10 (em vez de 1) garante que cada letra corresponde a exatamente dois dígitos, o que mantém coerente a aritmética posicional. Se A fosse 1, as letras produziriam uma mistura de valores de um e dois dígitos e o cálculo falharia.
Como gero um IBAN com dígitos verificadores válidos para testes?
Use o gerador Random IBAN: escolha um país e ele constrói um BBAN corretamente estruturado e calcula os dígitos verificadores por si, automaticamente. Cada resultado passa na validação MOD-97, pelo que funciona como dado de teste pronto a usar, sem expor quaisquer dados bancários reais.