Para validar CPF em tempo real com Java, combine a validação algorítmica local (verificação dos dígitos verificadores, instantânea) com uma chamada GET à API REST da CPFHub.io usando o HttpClient nativo ou um serviço Spring. A validação algorítmica filtra CPFs com formato inválido antes que qualquer chamada de rede seja feita; a consulta via API confirma a existência real do documento e retorna nome, data de nascimento e gênero em ~900ms.
Introdução
A validação de CPF em tempo real é um requisito comum em aplicações de cadastro, checkout e onboarding. A abordagem mais robusta combina validação algorítmica local, que é instantânea, com consulta via API REST para verificar a existência real do CPF. Em Java, essa combinação pode ser implementada de forma eficiente e thread-safe, atendendo a cenários de alta concorrência.
Validação algorítmica local
A validação algorítmica verifica os dígitos verificadores do CPF sem necessidade de chamada externa.
public class CpfValidator {
private CpfValidator() {}
public static boolean validarAlgoritmo(String cpf) {
String cpfLimpo = cpf.replaceAll("\\D", "");
if (cpfLimpo.length() != 11) {
return false;
}
// Verificar se todos os dígitos são iguais
if (cpfLimpo.chars().distinct().count() == 1) {
return false;
}
// Validar primeiro dígito verificador
int soma = 0;
for (int i = 0; i < 9; i++) {
soma += Character.getNumericValue(cpfLimpo.charAt(i))
* (10 - i);
}
int resto = (soma * 10) % 11;
if (resto == 10) resto = 0;
if (resto != Character.getNumericValue(cpfLimpo.charAt(9))) {
return false;
}
// Validar segundo dígito verificador
soma = 0;
for (int i = 0; i < 10; i++) {
soma += Character.getNumericValue(cpfLimpo.charAt(i))
* (11 - i);
}
resto = (soma * 10) % 11;
if (resto == 10) resto = 0;
return resto == Character.getNumericValue(cpfLimpo.charAt(10));
}
public static String formatar(String cpf) {
String limpo = cpf.replaceAll("\\D", "");
return String.format("%s.%s.%s-%s",
limpo.substring(0, 3),
limpo.substring(3, 6),
limpo.substring(6, 9),
limpo.substring(9, 11));
}
}
| Validação | Tempo | Cobertura |
|---|---|---|
| Formato (11 dígitos) | < 0.001ms | Erros de digitação |
| Dígitos iguais | < 0.001ms | CPFs triviais (111.111.111-11) |
| Dígitos verificadores | < 0.01ms | CPFs com números inventados |
| Consulta via API | 100-500ms | Existência real do CPF |
Serviço de validação em tempo real
O serviço combina validação local e consulta via API com cache para otimizar performance.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class CpfValidationService {
private final HttpClient httpClient;
private final String apiKey;
private final ObjectMapper mapper;
private final Map<String, ValidationResult> cache;
public CpfValidationService(String apiKey) {
this.httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build();
this.apiKey = apiKey;
this.mapper = new ObjectMapper();
this.cache = new ConcurrentHashMap<>();
}
public ValidationResult validarTempoReal(String cpf) {
String cpfLimpo = cpf.replaceAll("\\D", "");
// Etapa 1: Validação algorítmica
if (!CpfValidator.validarAlgoritmo(cpfLimpo)) {
return new ValidationResult(
false, "algoritmo", "CPF invalido", null
);
}
// Etapa 2: Verificar cache
ValidationResult cached = cache.get(cpfLimpo);
if (cached != null) {
return new ValidationResult(
cached.valido(), "cache",
cached.mensagem(), cached.dados()
);
}
// Etapa 3: Consulta via API
try {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(
"https://api.cpfhub.io/cpf/" + cpfLimpo
))
.header("x-api-key", apiKey)
.timeout(Duration.ofSeconds(5))
.GET()
.build();
HttpResponse<String> response = httpClient.send(
request,
HttpResponse.BodyHandlers.ofString()
);
JsonNode root = mapper.readTree(response.body());
if (root.get("success").asBoolean()) {
JsonNode data = root.get("data");
Map<String, String> dados = Map.of(
"nome", data.get("name").asText(),
"genero", data.get("gender").asText(),
"nascimento", data.get("birthDate").asText()
);
ValidationResult result = new ValidationResult(
true, "api", "CPF valido", dados
);
cache.put(cpfLimpo, result);
return result;
}
return new ValidationResult(
false, "api", "CPF nao encontrado", null
);
} catch (Exception e) {
// Fallback: se a API falhar, aceitar com base
// na validação algorítmica
return new ValidationResult(
true, "fallback",
"Validado localmente (API indisponivel)",
null
);
}
}
}
public record ValidationResult(
boolean valido,
String fonte,
String mensagem,
Map<String, String> dados
) {}
Endpoint REST para validação em tempo real
Exponha o serviço como endpoint REST para consumo por frontends ou outros serviços.
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/validar")
public class CpfValidationController {
private final CpfValidationService validationService;
public CpfValidationController(
CpfValidationService validationService) {
this.validationService = validationService;
}
@GetMapping("/cpf/{cpf}")
public ResponseEntity<ValidationResult> validar(
@PathVariable String cpf) {
ValidationResult resultado =
validationService.validarTempoReal(cpf);
return ResponseEntity.ok(resultado);
}
@PostMapping("/cpf/lote")
public ResponseEntity<Map<String, Object>> validarLote(
@RequestBody List<String> cpfs) {
List<ValidationResult> resultados = cpfs.stream()
.map(validationService::validarTempoReal)
.toList();
long validos = resultados.stream()
.filter(ValidationResult::valido)
.count();
return ResponseEntity.ok(Map.of(
"total", cpfs.size(),
"validos", validos,
"invalidos", cpfs.size() - validos,
"resultados", resultados
));
}
}
| Endpoint | Método | Descrição |
|---|---|---|
/api/validar/cpf/{cpf} | GET | Validação individual em tempo real |
/api/validar/cpf/lote | POST | Validação de múltiplos CPFs |
Bean Validation customizado
Crie uma anotação customizada para validar CPF em DTOs automaticamente.
// CpfValido.java
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CpfValidoValidator.class)
public @interface CpfValido {
String message() default "CPF invalido";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
// CpfValidoValidator.java
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
public class CpfValidoValidator
implements ConstraintValidator<CpfValido, String> {
@Override
public boolean isValid(String cpf,
ConstraintValidatorContext context) {
if (cpf == null || cpf.isBlank()) {
return false;
}
return CpfValidator.validarAlgoritmo(cpf);
}
}
// Uso em DTO
public class CadastroRequest {
@CpfValido(message = "CPF informado e invalido")
private String cpf;
private String nome;
// Getters e setters
public String getCpf() { return cpf; }
public void setCpf(String cpf) { this.cpf = cpf; }
public String getNome() { return nome; }
public void setNome(String nome) { this.nome = nome; }
}
Métricas de performance
Monitore a performance da validação em tempo real com Micrometer.
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
@Service
public class CpfValidationServiceMetricas {
private final Timer validacaoTimer;
private final CpfValidationService validationService;
public CpfValidationServiceMetricas(
MeterRegistry registry,
CpfValidationService validationService) {
this.validationService = validationService;
this.validacaoTimer = Timer.builder("cpf.validacao")
.description("Tempo de validacao de CPF")
.register(registry);
}
public ValidationResult validar(String cpf) {
return validacaoTimer.record(
() -> validationService.validarTempoReal(cpf)
);
}
}
Perguntas frequentes
Por que combinar validação algorítmica e consulta via API em Java?
A validação algorítmica é instantânea (sub-millisegundo) e elimina CPFs com formato inválido ou dígitos verificadores errados antes de qualquer chamada de rede. A consulta via API confirma a existência real do CPF e retorna dados como nome e data de nascimento. Juntas, as duas camadas reduzem tanto o volume de chamadas externas quanto a taxa de falsos positivos no cadastro.
Como implementar cache thread-safe para a validação de CPF em Java?
Use ConcurrentHashMap para armazenar resultados recentes. A chave é o CPF sanitizado (apenas dígitos) e o valor é o ValidationResult. Em ambientes com alta concorrência, considere adicionar TTL com Caffeine ou Guava Cache para evitar servir dados desatualizados. O cache é especialmente útil em validações em lote onde o mesmo CPF pode aparecer múltiplas vezes.
Como configurar timeout adequado para a API de CPF em Java?
Configure timeout de conexão em 5 segundos e timeout de leitura em 10 segundos. A API da CPFHub.io tem latência de ~900ms em condições normais, portanto timeouts muito curtos podem gerar falsos negativos. Com HttpClient nativo, use .timeout(Duration.ofSeconds(10)) no HttpRequest; com Spring RestTemplate, configure via RestTemplateBuilder.setReadTimeout().
O que fazer quando a API de CPF retorna erro ou fica indisponível?
Implemente um fallback que retorna o resultado da validação algorítmica com fonte = "fallback", indicando que o CPF passou apenas pela verificação local. Registre o evento para monitoramento. A API da CPFHub.io não bloqueia consultas ao atingir o limite do plano — ela cobra R$0,15 por consulta excedente e continua respondendo normalmente, então erros de disponibilidade são raros e geralmente transitórios.
Conclusão
A validação de CPF em tempo real em Java combina a velocidade da validação algorítmica local com a precisão da consulta via API REST. O uso de cache thread-safe com ConcurrentHashMap, fallback para cenários de indisponibilidade e Bean Validation customizada para DTOs cria um sistema robusto e reutilizável. As métricas com Micrometer permitem monitorar a performance e identificar gargalos em produção.
Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e integre a validação de CPF em tempo real na sua aplicação Java em menos de 30 minutos.
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
Sobre a redação
Redação CPFHub.io
Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.



