# Como validar número de cartão de crédito (algoritmo de Luhn)

> O último dígito de um cartão de crédito é um dígito verificador, calculado pelo algoritmo de Luhn. Ele pega erros de digitação, como um número trocado, antes de o pagamento chegar ao banco. Este guia explica o cálculo, mostra a validação em JavaScript, Python e PHP e lista o que o Luhn não garante e os cuidados com dados de cartão.

- Endereço oficial: https://pradev.com.br/guias/como-validar-cartao-de-credito-luhn
- Tipo: Guia
- Publicado em: 2026-10-01
- Atualizado em: 2026-10-01
- Autor: Leonardo Gaertner (https://pradev.com.br/sobre)
- Ferramentas: [Validador de Cartão de Crédito](https://pradev.com.br/validador-de-cartao-de-credito), [Gerador de Cartão de Crédito](https://pradev.com.br/gerador-de-cartao-de-credito)

## Como o algoritmo funciona

- Comece pelo último dígito e vá para a esquerda.
- Dobre um dígito sim, outro não, a partir do segundo da direita. Se o dobro passar de 9, subtraia 9 (14 vira 5).
- Some tudo. O número é válido se a soma terminar em 0, ou seja, se for múltiplo de 10.

O Luhn pega todos os erros de um único dígito e quase todas as trocas de dois dígitos vizinhos (a exceção é 09 com 90). É a mesma ideia dos dígitos verificadores do CPF, com outra conta: veja o [guia de validação de CPF](https://pradev.com.br/guias/como-validar-cpf-em-javascript). Para conferir um número na hora, use o [validador de cartão de crédito](https://pradev.com.br/validador-de-cartao-de-credito).

## Em JavaScript

A conta do Luhn fica separada da regra do cartão (de 12 a 19 dígitos), porque ela também vale para números de outros tamanhos, como o IMEI dos celulares. A função `digitoLuhn` calcula o dígito final, útil para montar números de teste.

```javascript
// Algoritmo de Luhn: da direita para a esquerda, dobra um dígito sim, outro não
function luhnConfere(digitos) {
  let soma = 0;
  for (let i = 0; i < digitos.length; i++) {
    let n = Number(digitos[digitos.length - 1 - i]);
    if (i % 2 === 1) {
      n *= 2;
      if (n > 9) n -= 9; // 7 × 2 = 14, e 1 + 4 = 5 (o mesmo que 14 - 9)
    }
    soma += n;
  }
  return soma % 10 === 0;
}

// Cartão: de 12 a 19 dígitos e o Luhn conferindo
function cartaoValido(numero) {
  const d = numero.replace(/\D/g, '');
  return d.length >= 12 && d.length <= 19 && luhnConfere(d);
}

// Dígito que completa um número para passar no Luhn (útil para gerar dados de teste)
function digitoLuhn(base) {
  for (let dv = 0; dv <= 9; dv++) {
    if (luhnConfere(`${base}${dv}`)) return dv;
  }
}
```

_JavaScript_

## Em Python e PHP

```python
import re


def luhn_confere(digitos: str) -> bool:
    soma = 0
    for i, c in enumerate(reversed(digitos)):
        n = int(c)
        if i % 2 == 1:
            n = n * 2 - 9 if n * 2 > 9 else n * 2
        soma += n
    return soma % 10 == 0


def cartao_valido(numero: str) -> bool:
    d = re.sub(r"\D", "", numero)
    return 12 <= len(d) <= 19 and luhn_confere(d)
```

_Python_

```php
<?php
function luhnConfere(string $digitos): bool
{
    $soma = 0;
    foreach (str_split(strrev($digitos)) as $i => $c) {
        $n = (int) $c;
        if ($i % 2 === 1) {
            $n = $n * 2 > 9 ? $n * 2 - 9 : $n * 2;
        }
        $soma += $n;
    }
    return $soma % 10 === 0;
}

function cartaoValido(string $numero): bool
{
    $d = preg_replace('/\D/', '', $numero);
    return strlen($d) >= 12 && strlen($d) <= 19 && luhnConfere($d);
}
```

_PHP_

## O que o Luhn não garante

- Que o cartão existe, está ativo ou tem limite: isso só a operadora responde, na autorização do pagamento.
- A bandeira: os primeiros dígitos (o BIN) indicam o emissor. Visa começa com 4, Mastercard com 51 a 55 ou 2221 a 2720, American Express com 34 ou 37. As faixas de Elo e Hipercard são muitas e mudam; deixe a identificação com o gateway de pagamento.
- Para testar, use os números de teste publicados pelo seu gateway, como `4111 1111 1111 1111`, que passam no Luhn e não cobram nada, ou crie números fictícios com o [gerador de cartão de crédito](https://pradev.com.br/gerador-de-cartao-de-credito).

## Cuidados com dados de cartão

- Não guarde o número completo nem o código de segurança. Quem guarda dados de cartão precisa seguir o padrão PCI DSS, que é exigente. Use a tokenização do gateway: o número vai direto para ele, e você guarda só um token.
- Nunca registre o número do cartão em logs, nem em mensagens de erro.
- A validação no navegador só ajuda quem digita. O pagamento é decidido pelo gateway.
- Para mostrar o cartão salvo, use só os 4 últimos dígitos.

## Perguntas frequentes

### Como validar um número de cartão de crédito?

Confira o tamanho (de 12 a 19 dígitos) e aplique o algoritmo de Luhn: dobre um dígito sim, outro não, a partir do segundo da direita, subtraia 9 dos dobros acima de 9 e veja se a soma é múltipla de 10.

### Passar no Luhn quer dizer que o cartão é verdadeiro?

Não. O Luhn só mostra que o número foi digitado sem erro. Se o cartão existe e tem limite, só a operadora responde, quando o pagamento é autorizado.

### Quais números de cartão usar em testes?

Os números de teste publicados pelo seu gateway de pagamento, como 4111 1111 1111 1111 para Visa. Eles passam na validação e funcionam no ambiente de testes, sem cobrar nada.

### Onde mais o algoritmo de Luhn é usado?

No IMEI dos celulares e em vários números de identificação pelo mundo. A conta é sempre a mesma; muda só o tamanho do número.

## Fontes

- [Wikipédia (em inglês): algoritmo de Luhn](https://en.wikipedia.org/wiki/Luhn_algorithm)

## Guias relacionados

- [Como validar CPF em JavaScript, Python e PHP](https://pradev.com.br/guias/como-validar-cpf-em-javascript): Aprenda a calcular os dígitos verificadores do CPF e veja funções prontas e testadas para validar CPF em JavaScript, Python e PHP.
- [Como gerar CPF e CNPJ válidos para testes em código](https://pradev.com.br/guias/como-gerar-cpf-e-cnpj-para-testes): Como gerar CPF e CNPJ matematicamente válidos para testes em JavaScript, Python e PHP, o cálculo dos dígitos e os cuidados para não usar dados de pessoas reais.
