Algoritmo de Luhn: como funciona e como implementar
O algoritmo de Luhn (também chamado mod-10) é o checksum que valida números de cartão de crédito antes de qualquer chamada ao gateway. Esse guia explica o algoritmo do zero, mostra um exemplo numérico passo a passo, traz implementação em TypeScript e Python, e tem uma calculadora interativa pra testar qualquer número.
O que é o algoritmo de Luhn
O algoritmo de Luhn é uma fórmula simples de checksum criada pelo engenheiro Hans Peter Luhn, da IBM, em 1954. Ele verifica se um número longo (cartão de crédito, IMEI, CPF/CNPJ tem variante similar) está sintaticamente correto. Não verifica fraude, não verifica se o cartão existe, não verifica saldo. Verifica se os dígitos batem com o dígito verificador que foi calculado no momento da emissão.
A ideia é simples: o último dígito do número é um dígito verificador que existe pra fazer o número inteiro passar numa soma específica. Se você muda qualquer dígito, a soma quebra. Se você inverte dois adjacentes (exceto 09 ↔ 90), a soma quebra. Isso pega ~90% dos erros de digitação antes de chegar no gateway.
Toda bandeira de cartão (Visa, Mastercard, Elo, Hipercard, Amex) usa Luhn. Padronizado pela ISO/IEC 7812. Por isso o mesmo algoritmo funciona pra qualquer cartão de 13 a 19 dígitos. Comprimento e prefixo (BIN) é que diferenciam as bandeiras — mas a validação do checksum é universal.
Passo a passo com exemplo numérico
Vou usar o número 4532 0151 1283 0366 (um Visa fictício) e mostrar cada passo:
- Comece da direita pra esquerda, ignorando o último dígito (o verificador). Os outros dígitos serão processados em pares: posição par (do fim) é multiplicada por 2, posição ímpar fica como está.
- Multiplique por 2 cada segundo dígito contando da direita. Se o resultado passar de 9, subtraia 9 (ou some os dois dígitos — dá no mesmo).
- Some todos os dígitos (modificados + inalterados + verificador).
- Se a soma for divisível por 10, o número é válido. Se sobrar 1, 2, 3..., é inválido.
Aplicando ao 4532015112830366:
Posição: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Dígito: 4 5 3 2 0 1 5 1 1 2 8 3 0 3 6 6
← último = verificador (6)
Da direita:
pos 16: 6 (verificador, soma direta no final)
pos 15: 6 → ×2 = 12 → 1+2 = 3
pos 14: 3 (soma direta)
pos 13: 0 → ×2 = 0
pos 12: 3 (soma direta)
pos 11: 8 → ×2 = 16 → 1+6 = 7
pos 10: 2 (soma direta)
pos 9: 1 → ×2 = 2
pos 8: 1 (soma direta)
pos 7: 5 → ×2 = 10 → 1+0 = 1
pos 6: 1 (soma direta)
pos 5: 0 → ×2 = 0
pos 4: 2 (soma direta)
pos 3: 3 → ×2 = 6
pos 2: 5 (soma direta)
pos 1: 4 → ×2 = 8
Soma = 6 + 3 + 3 + 0 + 3 + 7 + 2 + 2 + 1 + 1 + 1 + 0 + 0 + 2 + 6 + 5 + 8
= 50
50 mod 10 = 0 → VÁLIDO ✓Se você muda qualquer dígito (digamos, o último 6 vira 7), a soma vira 51, que não é divisível por 10, e o número é rejeitado.
Calculadora interativa
Digite qualquer número de cartão pra ver se passa no Luhn. Funciona pra Visa, Mastercard, Elo, Amex, Hipercard, Diners e qualquer cartão de 13 a 19 dígitos.
Digite com ou sem espaços/hífens. Aceita 13 a 19 dígitos.
Implementação em TypeScript
Função pura, sem dependências, ~15 linhas:
export function luhnCheck(cardNumber: string): boolean {
const digits = cardNumber.replace(/\D/g, "");
if (digits.length < 13 || digits.length > 19) return false;
let sum = 0;
let shouldDouble = false;
for (let i = digits.length - 1; i >= 0; i--) {
let d = Number(digits[i]);
if (shouldDouble) {
d *= 2;
if (d > 9) d -= 9;
}
sum += d;
shouldDouble = !shouldDouble;
}
return sum % 10 === 0;
}
// Uso:
luhnCheck("4532 0151 1283 0366"); // true
luhnCheck("4532 0151 1283 0367"); // falseNotas: o replace(/\D/g, "") remove espaços, hífens e qualquer não-dígito (o usuário pode digitar com ou sem formatação). O range 13-19 cobre Visa Electron (13), maioria das bandeiras (16), Amex (15) e cartões UnionPay (até 19).
Implementação em Python
Versão equivalente em Python, também sem dependências:
import re
def luhn_check(card_number: str) -> bool:
digits = re.sub(r"\D", "", card_number)
if not 13 <= len(digits) <= 19:
return False
total = 0
for i, ch in enumerate(reversed(digits)):
d = int(ch)
if i % 2 == 1: # cada segundo dígito (1, 3, 5...) da direita
d *= 2
if d > 9:
d -= 9
total += d
return total % 10 == 0
# Uso:
luhn_check("4532 0151 1283 0366") # True
luhn_check("4532-0151-1283-0367") # FalseO que o Luhn NÃO faz
Importante entender o escopo do checksum pra não confiar nele além do que ele resolve:
- Não verifica fraude. Você pode gerar infinitos números que passam no Luhn (esse site faz isso). Não tem nada a ver com identidade do portador ou autorização.
- Não verifica se o cartão existe. Número que passa pode pertencer a ninguém. Só quem confirma existência é o emissor (banco).
- Não verifica CVV nem data de validade. Esses campos têm validação separada (CVV não tem checksum — é só verificação contra a base do emissor).
- Não impede ataques sofisticados. Pega erro de digitação. Pra fraude real, o gateway combina autorização, AVS, fingerprint de dispositivo, behavioral signals, etc.
Use Luhn no cliente pra evitar requisições óbvias inválidas. Use no servidor também (cliente pode ser manipulado via DevTools). Mas nunca confie só nele.
BINs por bandeira
O Luhn valida o checksum. Pra detectar a bandeira do cartão, você olha o IIN/BIN (os primeiros dígitos):
| Bandeira | Prefixo | Comprimento | CVV |
|---|---|---|---|
| Visa | 4 | 13, 16, 19 | 3 |
| Mastercard | 51-55, 2221-2720 | 16 | 3 |
| Amex | 34, 37 | 15 | 4 (CID) |
| Elo | prefixos BR específicos | 16 | 3 |
| Hipercard | 606282, 3841 | 16, 19 | 3 |
| Diners | 300-305, 36, 38 | 14 | 3 |
Pra gerar números válidos por bandeira pra testes, use os geradores específicos: Visa, Mastercard, Elo, Amex ou Hipercard.
Perguntas frequentes
Por que o algoritmo se chama mod-10?+
Porque a verificação final é se a soma é divisível por 10 (soma mod 10 == 0). 'mod' = módulo, operação de resto da divisão. O nome técnico ISO é 'Luhn' em homenagem ao autor; mod-10 é o jeito informal de descrever a matemática.
O algoritmo de Luhn é o mesmo do CPF/CNPJ?+
Não. CPF e CNPJ usam mod-11 (resto da divisão por 11) com pesos diferentes pra cada dígito. Conceito de checksum é parecido, mas os pesos e o módulo são distintos. CPF e CNPJ também têm 2 dígitos verificadores, não 1.
Posso usar Luhn pra IMEI?+
Sim. IMEI usa o mesmo algoritmo de Luhn pro último dígito (o check digit). O IMEISV (16 dígitos com software version) também segue a mesma regra.
Qual a diferença entre Luhn e Luhn mod-N?+
Luhn padrão usa base 10 (dígitos 0-9). Existe variante 'Luhn mod-N' que generaliza pra qualquer base — usado em códigos alfanuméricos. Pra cartão de crédito, é sempre o Luhn padrão (base 10).
Por que cartão de teste 4111 1111 1111 1111 funciona?+
Porque ele passa no Luhn (some os dígitos seguindo as regras e dá múltiplo de 10) E está na lista de BINs reservados de teste do Visa. Gateways como Stripe, Cielo, Mercado Pago reconhecem ele como 'cartão de sandbox' e simulam respostas — sem tentar autorizar de verdade.
O algoritmo de Luhn protege contra fraude?+
Não. Ele detecta erros de digitação (~90% deles). Pra fraude real, gateway combina autorização (banco emissor confirma fundos), AVS (endereço bate?), 3DS (autenticação extra), e múltiplos sinais comportamentais. Luhn é só a pré-filtragem barata antes de tudo isso.
Próximos passos
Agora que você entende o algoritmo, pode usar os geradores pra criar números de teste válidos em qualquer bandeira: