[{"data":1,"prerenderedAt":2593},["ShallowReactive",2],{"pt-BR-tools-category-articles":3},[4,884,2265],{"id":5,"title":6,"articleCover":7,"articleCoverEmbed":8,"articleCoverEmbedUploadDate":8,"articleCoverHeight":9,"articleCoverWidth":10,"authorId":11,"body":12,"categoriesIds":868,"description":870,"enAlternateSlug":871,"extension":872,"meta":873,"navigation":247,"path":874,"ptBrAlternateSlug":875,"publishedAt":876,"seo":877,"sitemap":878,"stem":880,"updatedAt":881,"wordCount":882,"__hash__":883},"blog\u002Fblog\u002Fcomo-validar-cartao-de-credito-com-javascript.md","Como validar um cartão de crédito com JavaScript (algoritmo de Luhn)","\u002Fimages\u002Fblog\u002Fjavascript\u002Fcomo-validar-cartao-de-credito-com-javascript.webp",null,720,1280,"thiago-nunes-batista",{"type":13,"value":14,"toc":845},"minimark",[15,19,22,27,35,38,41,45,57,60,94,99,116,143,149,152,156,159,650,669,673,684,701,707,710,714,717,721,728,732,745,749,752,756,763,772,776,780,791,795,798,802,805,809,812,816,819,823,826,830,833,841],[16,17,18],"p",{},"Você está construindo um formulário de checkout e precisa validar o campo de cartão antes de enviar os dados pro gateway de pagamento. A solução mais comum e recomendada é usar o algoritmo de Luhn para checar se o número tem o formato matemático correto.",[16,20,21],{},"Neste artigo, você vai entender exatamente como o algoritmo funciona, ver um exemplo numérico passo a passo e implementar uma função JavaScript pronta pra usar no seu projeto.",[23,24,26],"h2",{"id":25},"o-que-é-o-algoritmo-de-luhn","O que é o algoritmo de Luhn",[16,28,29,30,34],{},"O algoritmo de Luhn, também chamado de \"fórmula do módulo 10\" ou \"mod-10\", foi criado por Hans Peter Luhn em 1954 e virou padrão da indústria para validar números de cartão de crédito. Ele calcula um ",[31,32,33],"strong",{},"dígito verificador"," (o último dígito do número) que permite detectar erros de digitação, como trocar dois dígitos de lugar ou digitar um número errado.",[16,36,37],{},"A ideia é simples: o emissor do cartão (banco ou bandeira) gera o número de forma que, quando você aplica a fórmula do Luhn, o resultado seja divisível por 10. Se não for, o número tem erro de formatação.",[16,39,40],{},"Isso é feito no lado do cliente (no navegador) antes de mandar os dados pro servidor. Assim você evita enviar requisições inválidas pro gateway de pagamento e melhora a experiência do usuário com feedback imediato.",[23,42,44],{"id":43},"passo-a-passo-do-algoritmo-com-exemplo-numérico","Passo a passo do algoritmo com exemplo numérico",[16,46,47,48,51,52,56],{},"Vamos validar o número de teste da Visa que várias plataformas de pagamento usam em sandbox: ",[31,49,50],{},"4242 4242 4242 4242",". Primeiro, removemos espaços e traços, ficando com ",[53,54,55],"code",{},"4242424242424242",".",[16,58,59],{},"Agora aplicamos o algoritmo de Luhn:",[61,62,63,70,76,82,88],"ol",{},[64,65,66,69],"li",{},[31,67,68],{},"Comece pelo dígito mais à direita"," (o último 2) e vá para a esquerda. Esse primeiro dígito nunca é dobrado.",[64,71,72,75],{},[31,73,74],{},"Dobre o valor de cada segundo dígito"," a partir daí, ou seja, pule um, dobre o próximo, pule um, dobre o próximo, e assim por diante.",[64,77,78,81],{},[31,79,80],{},"Se o dobro resultar em dois dígitos",", some os dois algarismos entre si (ou subtraia 9, é equivalente).",[64,83,84,87],{},[31,85,86],{},"Some todos os dígitos"," (os dobrados\u002Fajustados e os que não foram alterados).",[64,89,90,93],{},[31,91,92],{},"Se o total for divisível por 10",", o número é válido pelo algoritmo de Luhn.",[95,96,98],"h3",{"id":97},"exemplo-prático-com-4242424242424242","Exemplo prático com 4242424242424242",[16,100,101,102,105,106,109,110,112,113,115],{},"O número tem 16 dígitos, alternando ",[53,103,104],{},"4"," e ",[53,107,108],{},"2",". Começando pelo dígito mais à direita (que não é dobrado) e indo para a esquerda, os dígitos que caem na posição \"dobrar\" são sempre os ",[53,111,104],{},", e os que caem na posição \"não dobrar\" são sempre os ",[53,114,108],{},". Isso acontece porque o número inteiro segue esse padrão alternado.",[117,118,119,128],"ul",{},[64,120,121,124,125,127],{},[31,122,123],{},"Dígitos que não são dobrados"," (8 dígitos, todos ",[53,126,108],{},"): 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 = 16",[64,129,130,124,133,135,136,138,139,142],{},[31,131,132],{},"Dígitos dobrados",[53,134,104],{},"): cada ",[53,137,104],{}," dobrado vira ",[53,140,141],{},"8"," (4 × 2 = 8, não passa de 9, não precisa ajustar). 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 = 64",[16,144,145,146,56],{},"Somando os dois grupos: 16 + 64 = ",[31,147,148],{},"80",[16,150,151],{},"Como 80 é divisível por 10 (resto 0), esse número passa na validação do algoritmo de Luhn.",[23,153,155],{"id":154},"implementação-em-javascript-puro","Implementação em JavaScript puro",[16,157,158],{},"Abaixo está uma função completa que remove espaços, traços e outros caracteres não numéricos, depois aplica o algoritmo de Luhn:",[160,161,166],"pre",{"className":162,"code":163,"language":164,"meta":165,"style":165},"language-javascript shiki shiki-themes dracula","function validarCartaoCredito(numero) {\n  \u002F\u002F Remove tudo que não for dígito\n  const digitos = numero.replace(\u002F\\D\u002Fg, \"\");\n\n  \u002F\u002F Cartões têm entre 13 e 19 dígitos (a maioria 16)\n  if (digitos.length \u003C 13 || digitos.length > 19) {\n    return false;\n  }\n\n  let soma = 0;\n  let deveDobrar = false; \u002F\u002F começa pelo último dígito (não dobra)\n\n  \u002F\u002F Percorre da direita para a esquerda\n  for (let i = digitos.length - 1; i >= 0; i--) {\n    let d = parseInt(digitos[i], 10);\n\n    if (deveDobrar) {\n      d *= 2;\n      \u002F\u002F Se resultou em dois dígitos, soma os algarismos (ou subtrai 9)\n      if (d > 9) {\n        d -= 9;\n      }\n    }\n\n    soma += d;\n    deveDobrar = !deveDobrar; \u002F\u002F alterna para o próximo dígito\n  }\n\n  return soma % 10 === 0;\n}\n\n\u002F\u002F Testando com o número de teste da Visa\nconsole.log(validarCartaoCredito(\"4242 4242 4242 4242\")); \u002F\u002F true\nconsole.log(validarCartaoCredito(\"4242424242424242\")); \u002F\u002F true\nconsole.log(validarCartaoCredito(\"1234 5678 1234 5678\")); \u002F\u002F false\n","javascript","",[53,167,168,192,199,242,249,255,284,296,302,307,323,341,346,352,393,415,420,429,443,449,465,478,484,490,495,507,524,529,534,555,561,566,572,602,625],{"__ignoreMap":165},[169,170,173,177,181,185,189],"span",{"class":171,"line":172},"line",1,[169,174,176],{"class":175},"s0Tla","function",[169,178,180],{"class":179},"sAOxA"," validarCartaoCredito",[169,182,184],{"class":183},"sCdxs","(",[169,186,188],{"class":187},"sGEwX","numero",[169,190,191],{"class":183},") {\n",[169,193,195],{"class":171,"line":194},2,[169,196,198],{"class":197},"shSDL","  \u002F\u002F Remove tudo que não for dígito\n",[169,200,202,205,208,211,214,217,219,223,227,229,232,235,239],{"class":171,"line":201},3,[169,203,204],{"class":175},"  const",[169,206,207],{"class":183}," digitos ",[169,209,210],{"class":175},"=",[169,212,213],{"class":183}," numero.",[169,215,216],{"class":179},"replace",[169,218,184],{"class":183},[169,220,222],{"class":221},"s-doY","\u002F",[169,224,226],{"class":225},"sIQBb","\\D",[169,228,222],{"class":221},[169,230,231],{"class":175},"g",[169,233,234],{"class":183},", ",[169,236,238],{"class":237},"seVfx","\"\"",[169,240,241],{"class":183},");\n",[169,243,245],{"class":171,"line":244},4,[169,246,248],{"emptyLinePlaceholder":247},true,"\n",[169,250,252],{"class":171,"line":251},5,[169,253,254],{"class":197},"  \u002F\u002F Cartões têm entre 13 e 19 dígitos (a maioria 16)\n",[169,256,258,261,264,267,270,273,276,279,282],{"class":171,"line":257},6,[169,259,260],{"class":175},"  if",[169,262,263],{"class":183}," (digitos.length ",[169,265,266],{"class":175},"\u003C",[169,268,269],{"class":225}," 13",[169,271,272],{"class":175}," ||",[169,274,275],{"class":183}," digitos.length ",[169,277,278],{"class":175},">",[169,280,281],{"class":225}," 19",[169,283,191],{"class":183},[169,285,287,290,293],{"class":171,"line":286},7,[169,288,289],{"class":175},"    return",[169,291,292],{"class":225}," false",[169,294,295],{"class":183},";\n",[169,297,299],{"class":171,"line":298},8,[169,300,301],{"class":183},"  }\n",[169,303,305],{"class":171,"line":304},9,[169,306,248],{"emptyLinePlaceholder":247},[169,308,310,313,316,318,321],{"class":171,"line":309},10,[169,311,312],{"class":175},"  let",[169,314,315],{"class":183}," soma ",[169,317,210],{"class":175},[169,319,320],{"class":225}," 0",[169,322,295],{"class":183},[169,324,326,328,331,333,335,338],{"class":171,"line":325},11,[169,327,312],{"class":175},[169,329,330],{"class":183}," deveDobrar ",[169,332,210],{"class":175},[169,334,292],{"class":225},[169,336,337],{"class":183},"; ",[169,339,340],{"class":197},"\u002F\u002F começa pelo último dígito (não dobra)\n",[169,342,344],{"class":171,"line":343},12,[169,345,248],{"emptyLinePlaceholder":247},[169,347,349],{"class":171,"line":348},13,[169,350,351],{"class":197},"  \u002F\u002F Percorre da direita para a esquerda\n",[169,353,355,358,361,364,367,369,371,374,377,380,383,385,388,391],{"class":171,"line":354},14,[169,356,357],{"class":175},"  for",[169,359,360],{"class":183}," (",[169,362,363],{"class":175},"let",[169,365,366],{"class":183}," i ",[169,368,210],{"class":175},[169,370,275],{"class":183},[169,372,373],{"class":175},"-",[169,375,376],{"class":225}," 1",[169,378,379],{"class":183},"; i ",[169,381,382],{"class":175},">=",[169,384,320],{"class":225},[169,386,387],{"class":183},"; i",[169,389,390],{"class":175},"--",[169,392,191],{"class":183},[169,394,396,399,402,404,407,410,413],{"class":171,"line":395},15,[169,397,398],{"class":175},"    let",[169,400,401],{"class":183}," d ",[169,403,210],{"class":175},[169,405,406],{"class":179}," parseInt",[169,408,409],{"class":183},"(digitos[i], ",[169,411,412],{"class":225},"10",[169,414,241],{"class":183},[169,416,418],{"class":171,"line":417},16,[169,419,248],{"emptyLinePlaceholder":247},[169,421,423,426],{"class":171,"line":422},17,[169,424,425],{"class":175},"    if",[169,427,428],{"class":183}," (deveDobrar) {\n",[169,430,432,435,438,441],{"class":171,"line":431},18,[169,433,434],{"class":183},"      d ",[169,436,437],{"class":175},"*=",[169,439,440],{"class":225}," 2",[169,442,295],{"class":183},[169,444,446],{"class":171,"line":445},19,[169,447,448],{"class":197},"      \u002F\u002F Se resultou em dois dígitos, soma os algarismos (ou subtrai 9)\n",[169,450,452,455,458,460,463],{"class":171,"line":451},20,[169,453,454],{"class":175},"      if",[169,456,457],{"class":183}," (d ",[169,459,278],{"class":175},[169,461,462],{"class":225}," 9",[169,464,191],{"class":183},[169,466,468,471,474,476],{"class":171,"line":467},21,[169,469,470],{"class":183},"        d ",[169,472,473],{"class":175},"-=",[169,475,462],{"class":225},[169,477,295],{"class":183},[169,479,481],{"class":171,"line":480},22,[169,482,483],{"class":183},"      }\n",[169,485,487],{"class":171,"line":486},23,[169,488,489],{"class":183},"    }\n",[169,491,493],{"class":171,"line":492},24,[169,494,248],{"emptyLinePlaceholder":247},[169,496,498,501,504],{"class":171,"line":497},25,[169,499,500],{"class":183},"    soma ",[169,502,503],{"class":175},"+=",[169,505,506],{"class":183}," d;\n",[169,508,510,513,515,518,521],{"class":171,"line":509},26,[169,511,512],{"class":183},"    deveDobrar ",[169,514,210],{"class":175},[169,516,517],{"class":175}," !",[169,519,520],{"class":183},"deveDobrar; ",[169,522,523],{"class":197},"\u002F\u002F alterna para o próximo dígito\n",[169,525,527],{"class":171,"line":526},27,[169,528,301],{"class":183},[169,530,532],{"class":171,"line":531},28,[169,533,248],{"emptyLinePlaceholder":247},[169,535,537,540,542,545,548,551,553],{"class":171,"line":536},29,[169,538,539],{"class":175},"  return",[169,541,315],{"class":183},[169,543,544],{"class":175},"%",[169,546,547],{"class":225}," 10",[169,549,550],{"class":175}," ===",[169,552,320],{"class":225},[169,554,295],{"class":183},[169,556,558],{"class":171,"line":557},30,[169,559,560],{"class":183},"}\n",[169,562,564],{"class":171,"line":563},31,[169,565,248],{"emptyLinePlaceholder":247},[169,567,569],{"class":171,"line":568},32,[169,570,571],{"class":197},"\u002F\u002F Testando com o número de teste da Visa\n",[169,573,575,578,581,583,586,588,591,594,596,599],{"class":171,"line":574},33,[169,576,577],{"class":183},"console.",[169,579,580],{"class":179},"log",[169,582,184],{"class":183},[169,584,585],{"class":179},"validarCartaoCredito",[169,587,184],{"class":183},[169,589,590],{"class":237},"\"",[169,592,50],{"class":593},"s-mGx",[169,595,590],{"class":237},[169,597,598],{"class":183},")); ",[169,600,601],{"class":197},"\u002F\u002F true\n",[169,603,605,607,609,611,613,615,617,619,621,623],{"class":171,"line":604},34,[169,606,577],{"class":183},[169,608,580],{"class":179},[169,610,184],{"class":183},[169,612,585],{"class":179},[169,614,184],{"class":183},[169,616,590],{"class":237},[169,618,55],{"class":593},[169,620,590],{"class":237},[169,622,598],{"class":183},[169,624,601],{"class":197},[169,626,628,630,632,634,636,638,640,643,645,647],{"class":171,"line":627},35,[169,629,577],{"class":183},[169,631,580],{"class":179},[169,633,184],{"class":183},[169,635,585],{"class":179},[169,637,184],{"class":183},[169,639,590],{"class":237},[169,641,642],{"class":593},"1234 5678 1234 5678",[169,644,590],{"class":237},[169,646,598],{"class":183},[169,648,649],{"class":197},"\u002F\u002F false\n",[16,651,652,653,656,657,660,661,668],{},"Essa função é o que você usa no ",[53,654,655],{},"onblur"," ou ",[53,658,659],{},"onsubmit"," do seu formulário. Se quiser testar online antes de integrar, temos um ",[662,663,667],"a",{"href":664,"rel":665},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas\u002Fvalidador-de-cartao-de-credito",[666],"nofollow","validador de cartão de crédito online, gratuito"," que aplica exatamente essa lógica.",[23,670,672],{"id":671},"o-que-esse-algoritmo-não-garante","O que esse algoritmo NÃO garante",[16,674,675,676,679,680,683],{},"Aqui vai o disclaimer que muita gente pula (e depois se arrepende): ",[31,677,678],{},"o algoritmo de Luhn valida apenas o FORMATO\u002Festrutura matemática do número",". Ele ",[31,681,682],{},"NÃO"," verifica:",[117,685,686,689,692,695,698],{},[64,687,688],{},"Se o cartão existe de verdade",[64,690,691],{},"Se está ativo ou bloqueado",[64,693,694],{},"Se tem limite disponível",[64,696,697],{},"Se pertence à pessoa que está preenchendo o formulário",[64,699,700],{},"Se não é um cartão reportado como roubado\u002Ffraudado",[16,702,703,704,706],{},"Isso só o emissor do cartão (banco ou bandeira) consegue checar, via gateway de pagamento real (Stripe, Pagar.me, Mercado Pago, etc.). O Luhn é só um \"filtro de digitação\". Ele evita que você mande ",[53,705,642],{}," pro gateway e receba um erro bobo que poderia ter sido pego antes.",[16,708,709],{},"Não escreva no seu código nada que sugira que validar com Luhn significa \"cartão válido pra cobrar\", porque não é verdade.",[23,711,713],{"id":712},"erros-comuns","Erros comuns",[16,715,716],{},"Se você já implementou validação de cartão, provavelmente já viu (ou cometeu) algum desses:",[95,718,720],{"id":719},"validar-só-pela-quantidade-de-dígitos","Validar só pela quantidade de dígitos",[16,722,723,724,727],{},"Muitos formulários só checam se o número tem 16 dígitos. Isso deixa passar ",[53,725,726],{},"1111111111111111",", que tem 16 dígitos mas falha no Luhn. O inverso também acontece: American Express tem 15 dígitos, então validar só por \"tem que ter 16\" quebra o fluxo pra quem usa Amex.",[95,729,731],{"id":730},"não-remover-espaçostraços-antes-de-validar","Não remover espaços\u002Ftraços antes de validar",[16,733,734,735,656,738,740,741,744],{},"O usuário digita ",[53,736,737],{},"4242-4242-4242-4242",[53,739,50],{},". Se você não limpar isso antes de aplicar o Luhn, a validação falha mesmo com o número correto. A linha ",[53,742,743],{},"numero.replace(\u002F\\D\u002Fg, '')"," resolve isso.",[95,746,748],{"id":747},"tratar-luhn-como-verificação-antifraude","Tratar Luhn como verificação antifraude",[16,750,751],{},"Isso é clássico: o time de produto pede \"valida se o cartão é válido\" e o dev implementa Luhn achando que tá fazendo verificação de fraude. Não tá. Fraude requer análise de risco, tokenização, 3D Secure, regras do gateway. Nada disso o Luhn faz.",[95,753,755],{"id":754},"usar-números-de-teste-como-se-fossem-reais","Usar números de teste como se fossem reais",[16,757,758,759,762],{},"Os números de teste que gateways como Stripe e PayPal disponibilizam são válidos pelo Luhn, mas ",[31,760,761],{},"não são cartões reais",". Eles só funcionam em ambiente de sandbox. Nunca use em produção e nunca tente \"testar se funciona\" em gateway real. Isso é violação dos termos e pode gerar bloqueio.",[16,764,765,766,771],{},"Se precisar de dados de teste válidos pelo Luhn pra testar formulários, nosso ",[662,767,770],{"href":768,"rel":769},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas\u002Fgerador-de-cartao-de-credito",[666],"gerador de cartão de crédito para testes"," cria números estruturalmente corretos (mas não reais) pra você usar no QA.",[23,773,775],{"id":774},"perguntas-frequentes","Perguntas frequentes",[95,777,779],{"id":778},"como-saber-se-um-número-de-cartão-é-válido","Como saber se um número de cartão é válido?",[16,781,782,783,786,787,790],{},"Depende do que você quer dizer com \"válido\". Se for ",[31,784,785],{},"formato correto",", use o algoritmo de Luhn, que é o que a maioria dos gateways espera no front-end. Se for ",[31,788,789],{},"cartão que realmente funciona",", só o gateway de pagamento (via emissor) consegue responder, depois que você tenta cobrar.",[95,792,794],{"id":793},"dá-pra-testar-um-formulário-de-pagamento-sem-usar-cartão-real","Dá pra testar um formulário de pagamento sem usar cartão real?",[16,796,797],{},"Sim. Use os números de teste que cada gateway fornece (Stripe, Pagar.me, Mercado Pago, etc.). Eles são válidos pelo Luhn e simulam cenários como \"pagamento aprovado\", \"saldo insuficiente\", \"3D Secure\", etc. Nunca use cartões reais de terceiros. Use só os de sandbox.",[95,799,801],{"id":800},"validar-cartão-de-crédito-é-a-mesma-coisa-que-verificar-se-ele-está-ativo","Validar cartão de crédito é a mesma coisa que verificar se ele está ativo?",[16,803,804],{},"Não. Validar (com Luhn) checa se o número tem a estrutura matemática correta. Verificar se está ativo, tem limite ou não tá bloqueado é papel do banco, feito via gateway, quando você tenta processar o pagamento.",[95,806,808],{"id":807},"o-que-é-o-algoritmo-de-luhn-1","O que é o algoritmo de Luhn?",[16,810,811],{},"É uma fórmula matemática (módulo 10) que calcula um dígito verificador pra detectar erros de digitação em números como cartões de crédito, IMEI de celular, etc. Foi criado em 1954 por Hans Peter Luhn e virou padrão da indústria.",[95,813,815],{"id":814},"posso-usar-o-luhn-pra-evitar-fraude","Posso usar o Luhn pra evitar fraude?",[16,817,818],{},"Não. O Luhn só pega erro de digitação. Fraude requer análise comportamental, verificação de endereço, 3D Secure, regras de risco do gateway. Nada disso o Luhn faz.",[95,820,822],{"id":821},"qual-a-diferença-entre-número-válido-pelo-luhn-e-cartão-válido-pra-cobrar","Qual a diferença entre \"número válido pelo Luhn\" e \"cartão válido pra cobrar\"?",[16,824,825],{},"\"Número válido pelo Luhn\" significa formato matemático correto. \"Cartão válido pra cobrar\" significa que o emissor confirmou que o cartão existe, tá ativo, tem limite e não tá bloqueado. Só o gateway junto com o emissor respondem a segunda pergunta.",[23,827,829],{"id":828},"fechamento","Fechamento",[16,831,832],{},"Se você tá implementando validação de cartão num formulário de checkout, o algoritmo de Luhn é o primeiro passo, e o mais importante, pra evitar erros bobos de digitação. Implemente a função acima, teste com os números de sandbox do seu gateway e lembre sempre: Luhn valida formato, não valida se o cartão funciona de verdade.",[16,834,835,836,840],{},"Quer testar sua implementação antes de subir pra produção? Experimente nosso ",[662,837,839],{"href":664,"rel":838},[666],"validador de cartão de crédito online",". Ele aplica exatamente a mesma lógica que você vai usar no código.",[842,843,844],"style",{},"html pre.shiki code .s0Tla, html code.shiki .s0Tla{--shiki-default:#FF79C6}html pre.shiki code .sAOxA, html code.shiki .sAOxA{--shiki-default:#50FA7B}html pre.shiki code .sCdxs, html code.shiki .sCdxs{--shiki-default:#F8F8F2}html pre.shiki code .sGEwX, html code.shiki .sGEwX{--shiki-default:#FFB86C;--shiki-default-font-style:italic}html pre.shiki code .shSDL, html code.shiki .shSDL{--shiki-default:#6272A4}html pre.shiki code .s-doY, html code.shiki .s-doY{--shiki-default:#FF5555}html pre.shiki code .sIQBb, html code.shiki .sIQBb{--shiki-default:#BD93F9}html pre.shiki code .seVfx, html code.shiki .seVfx{--shiki-default:#E9F284}html pre.shiki code .s-mGx, html code.shiki .s-mGx{--shiki-default:#F1FA8C}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":165,"searchDepth":194,"depth":194,"links":846},[847,848,851,852,853,859,867],{"id":25,"depth":194,"text":26},{"id":43,"depth":194,"text":44,"children":849},[850],{"id":97,"depth":201,"text":98},{"id":154,"depth":194,"text":155},{"id":671,"depth":194,"text":672},{"id":712,"depth":194,"text":713,"children":854},[855,856,857,858],{"id":719,"depth":201,"text":720},{"id":730,"depth":201,"text":731},{"id":747,"depth":201,"text":748},{"id":754,"depth":201,"text":755},{"id":774,"depth":194,"text":775,"children":860},[861,862,863,864,865,866],{"id":778,"depth":201,"text":779},{"id":793,"depth":201,"text":794},{"id":800,"depth":201,"text":801},{"id":807,"depth":201,"text":808},{"id":814,"depth":201,"text":815},{"id":821,"depth":201,"text":822},{"id":828,"depth":194,"text":829},[164,869],"tools","Aprenda a validar número de cartão de crédito com JavaScript usando o algoritmo de Luhn. Exemplo prático, código pronto e o que o Luhn não verifica no cartão.","how-to-validate-credit-card-with-javascript","md",{},"\u002Fblog\u002Fcomo-validar-cartao-de-credito-com-javascript","como-validar-cartao-de-credito-com-javascript","2026-09-17",{"title":6,"description":870},{"loc":874,"lastmod":879},"2026-10-04","blog\u002Fcomo-validar-cartao-de-credito-com-javascript","2026-10-06",1371,"jyozPXnuNTJeWJYhcCKCLJxDch-deDwFWJnYIyUkhyY",{"id":885,"title":886,"articleCover":887,"articleCoverEmbed":8,"articleCoverEmbedUploadDate":8,"articleCoverHeight":9,"articleCoverWidth":10,"authorId":11,"body":888,"categoriesIds":2254,"description":2255,"enAlternateSlug":2256,"extension":872,"meta":2257,"navigation":247,"path":2258,"ptBrAlternateSlug":2259,"publishedAt":876,"seo":2260,"sitemap":2261,"stem":2262,"updatedAt":881,"wordCount":2263,"__hash__":2264},"blog\u002Fblog\u002Fcomo-validar-cpf-com-javascript.md","Como validar um CPF com JavaScript","\u002Fimages\u002Fblog\u002Fjavascript\u002Fcomo-validar-cpf-com-javascript.webp",{"type":13,"value":889,"toc":2231},[890,893,900,904,907,915,918,921,925,928,936,939,945,948,954,957,963,966,972,975,981,986,990,993,999,1002,1008,1011,1017,1020,1026,1029,1035,1042,1047,1050,1052,1059,1062,1539,1542,1660,1672,1675,1698,1704,1711,1719,1723,1726,1919,1922,1924,1928,1931,1971,1978,1985,1989,1992,1999,2026,2033,2036,2040,2043,2046,2080,2083,2087,2090,2093,2095,2099,2102,2109,2112,2116,2119,2133,2136,2139,2171,2175,2178,2181,2184,2188,2197,2200,2204,2207,2210,2214,2220,2228],[16,891,892],{},"Validar CPF no front-end ajuda a evitar erros em formulários de cadastro, checkout e login. No back-end, a validação é uma segunda barreira contra dados digitados incorretamente e fraudes mais básicas.",[16,894,895,896,899],{},"Neste artigo, você vai entender o algoritmo do CPF e implementar uma função de ",[31,897,898],{},"validação de CPF"," em JavaScript puro, sem biblioteca externa.",[23,901,903],{"id":902},"o-que-são-os-dígitos-verificadores","O que são os dígitos verificadores",[16,905,906],{},"Um CPF tem 11 dígitos:",[117,908,909,912],{},[64,910,911],{},"Os 9 primeiros são a base do documento.",[64,913,914],{},"Os 2 últimos são os dígitos verificadores.",[16,916,917],{},"Esses dois dígitos são calculados a partir dos anteriores. A ideia é detectar erros comuns de digitação, como trocar ou remover um número.",[16,919,920],{},"A validação matemática, porém, não confirma se o CPF existe, pertence a determinada pessoa ou está regular na Receita Federal. Ela apenas verifica se os dígitos obedecem ao algoritmo do CPF.",[95,922,924],{"id":923},"primeiro-dígito-verificador","Primeiro dígito verificador",[16,926,927],{},"Considere o CPF sem formatação:",[160,929,934],{"className":930,"code":932,"language":933,"meta":165},[931],"language-text","52998224725\n","text",[53,935,932],{"__ignoreMap":165},[16,937,938],{},"Os 9 primeiros dígitos são:",[160,940,943],{"className":941,"code":942,"language":933,"meta":165},[931],"5 2 9 9 8 2 2 4 7\n",[53,944,942],{"__ignoreMap":165},[16,946,947],{},"Multiplicamos cada número pelos pesos de 10 a 2:",[160,949,952],{"className":950,"code":951,"language":933,"meta":165},[931],"5×10 + 2×9 + 9×8 + 9×7 + 8×6 + 2×5 + 2×4 + 4×3 + 7×2\n",[53,953,951],{"__ignoreMap":165},[16,955,956],{},"O resultado é:",[160,958,961],{"className":959,"code":960,"language":933,"meta":165},[931],"50 + 18 + 72 + 63 + 48 + 10 + 8 + 12 + 14 = 295\n",[53,962,960],{"__ignoreMap":165},[16,964,965],{},"Agora calculamos o resto da divisão por 11:",[160,967,970],{"className":968,"code":969,"language":933,"meta":165},[931],"295 % 11 = 9\n",[53,971,969],{"__ignoreMap":165},[16,973,974],{},"Como o resto é maior que 1, fazemos:",[160,976,979],{"className":977,"code":978,"language":933,"meta":165},[931],"11 - 9 = 2\n",[53,980,978],{"__ignoreMap":165},[16,982,983,984,56],{},"Portanto, o primeiro dígito verificador é ",[53,985,108],{},[95,987,989],{"id":988},"segundo-dígito-verificador","Segundo dígito verificador",[16,991,992],{},"Agora usamos os 10 primeiros dígitos, incluindo o verificador calculado:",[160,994,997],{"className":995,"code":996,"language":933,"meta":165},[931],"5 2 9 9 8 2 2 4 7 2\n",[53,998,996],{"__ignoreMap":165},[16,1000,1001],{},"Aplicamos os pesos de 11 a 2:",[160,1003,1006],{"className":1004,"code":1005,"language":933,"meta":165},[931],"5×11 + 2×10 + 9×9 + 9×8 + 8×7 + 2×6 + 2×5 + 4×4 + 7×3 + 2×2\n",[53,1007,1005],{"__ignoreMap":165},[16,1009,1010],{},"A soma fica:",[160,1012,1015],{"className":1013,"code":1014,"language":933,"meta":165},[931],"55 + 20 + 81 + 72 + 56 + 12 + 10 + 16 + 21 + 4 = 347\n",[53,1016,1014],{"__ignoreMap":165},[16,1018,1019],{},"O resto da divisão por 11 é:",[160,1021,1024],{"className":1022,"code":1023,"language":933,"meta":165},[931],"347 % 11 = 6\n",[53,1025,1023],{"__ignoreMap":165},[16,1027,1028],{},"Como o resto é maior que 1:",[160,1030,1033],{"className":1031,"code":1032,"language":933,"meta":165},[931],"11 - 6 = 5\n",[53,1034,1032],{"__ignoreMap":165},[16,1036,1037,1038,1041],{},"O segundo dígito verificador é ",[53,1039,1040],{},"5",". Assim, o CPF completo é:",[160,1043,1045],{"className":1044,"code":932,"language":933,"meta":165},[931],[53,1046,932],{"__ignoreMap":165},[16,1048,1049],{},"Esse é o algoritmo do CPF: calcular o primeiro dígito, incorporá-lo à sequência e calcular o segundo.",[23,1051,155],{"id":154},[16,1053,1054,1055,1058],{},"A função precisa lidar com entradas formatadas, como ",[53,1056,1057],{},"529.982.247-25",", e também com uma sequência de números sem pontuação.",[16,1060,1061],{},"Uma implementação possível é esta:",[160,1063,1065],{"className":162,"code":1064,"language":164,"meta":165,"style":165},"function validarCPF(cpf) {\n  \u002F\u002F Garante que a entrada seja tratada como texto\n  cpf = String(cpf).replace(\u002F\\D\u002Fg, \"\");\n\n  \u002F\u002F Um CPF válido deve ter exatamente 11 dígitos\n  if (cpf.length !== 11) {\n    return false;\n  }\n\n  \u002F\u002F Rejeita CPFs formados pelo mesmo dígito\n  if (\u002F^(\\d)\\1{10}$\u002F.test(cpf)) {\n    return false;\n  }\n\n  \u002F\u002F Calcula o primeiro dígito verificador\n  let soma = 0;\n\n  for (let i = 0; i \u003C 9; i++) {\n    soma += Number(cpf[i]) * (10 - i);\n  }\n\n  let resto = soma % 11;\n  const primeiroDigito = resto \u003C 2 ? 0 : 11 - resto;\n\n  \u002F\u002F O primeiro dígito calculado deve ser igual ao informado\n  if (primeiroDigito !== Number(cpf[9])) {\n    return false;\n  }\n\n  \u002F\u002F Calcula o segundo dígito verificador\n  soma = 0;\n\n  for (let i = 0; i \u003C 10; i++) {\n    soma += Number(cpf[i]) * (11 - i);\n  }\n\n  resto = soma % 11;\n  const segundoDigito = resto \u003C 2 ? 0 : 11 - resto;\n\n  \u002F\u002F O segundo dígito calculado também deve ser igual ao informado\n  return segundoDigito === Number(cpf[10]);\n}\n",[53,1066,1067,1081,1086,1117,1121,1126,1141,1149,1153,1157,1162,1195,1203,1207,1211,1216,1228,1232,1259,1284,1288,1292,1309,1339,1343,1348,1368,1376,1380,1384,1389,1400,1404,1430,1451,1455,1460,1476,1504,1509,1515,1534],{"__ignoreMap":165},[169,1068,1069,1071,1074,1076,1079],{"class":171,"line":172},[169,1070,176],{"class":175},[169,1072,1073],{"class":179}," validarCPF",[169,1075,184],{"class":183},[169,1077,1078],{"class":187},"cpf",[169,1080,191],{"class":183},[169,1082,1083],{"class":171,"line":194},[169,1084,1085],{"class":197},"  \u002F\u002F Garante que a entrada seja tratada como texto\n",[169,1087,1088,1091,1093,1096,1099,1101,1103,1105,1107,1109,1111,1113,1115],{"class":171,"line":201},[169,1089,1090],{"class":183},"  cpf ",[169,1092,210],{"class":175},[169,1094,1095],{"class":179}," String",[169,1097,1098],{"class":183},"(cpf).",[169,1100,216],{"class":179},[169,1102,184],{"class":183},[169,1104,222],{"class":221},[169,1106,226],{"class":225},[169,1108,222],{"class":221},[169,1110,231],{"class":175},[169,1112,234],{"class":183},[169,1114,238],{"class":237},[169,1116,241],{"class":183},[169,1118,1119],{"class":171,"line":244},[169,1120,248],{"emptyLinePlaceholder":247},[169,1122,1123],{"class":171,"line":251},[169,1124,1125],{"class":197},"  \u002F\u002F Um CPF válido deve ter exatamente 11 dígitos\n",[169,1127,1128,1130,1133,1136,1139],{"class":171,"line":257},[169,1129,260],{"class":175},[169,1131,1132],{"class":183}," (cpf.length ",[169,1134,1135],{"class":175},"!==",[169,1137,1138],{"class":225}," 11",[169,1140,191],{"class":183},[169,1142,1143,1145,1147],{"class":171,"line":286},[169,1144,289],{"class":175},[169,1146,292],{"class":225},[169,1148,295],{"class":183},[169,1150,1151],{"class":171,"line":298},[169,1152,301],{"class":183},[169,1154,1155],{"class":171,"line":304},[169,1156,248],{"emptyLinePlaceholder":247},[169,1158,1159],{"class":171,"line":309},[169,1160,1161],{"class":197},"  \u002F\u002F Rejeita CPFs formados pelo mesmo dígito\n",[169,1163,1164,1166,1168,1170,1173,1176,1179,1182,1185,1187,1189,1192],{"class":171,"line":325},[169,1165,260],{"class":175},[169,1167,360],{"class":183},[169,1169,222],{"class":221},[169,1171,1172],{"class":175},"^",[169,1174,184],{"class":1175},"smvxG",[169,1177,1178],{"class":225},"\\d",[169,1180,1181],{"class":1175},")",[169,1183,1184],{"class":175},"\\1{10}$",[169,1186,222],{"class":221},[169,1188,56],{"class":183},[169,1190,1191],{"class":179},"test",[169,1193,1194],{"class":183},"(cpf)) {\n",[169,1196,1197,1199,1201],{"class":171,"line":343},[169,1198,289],{"class":175},[169,1200,292],{"class":225},[169,1202,295],{"class":183},[169,1204,1205],{"class":171,"line":348},[169,1206,301],{"class":183},[169,1208,1209],{"class":171,"line":354},[169,1210,248],{"emptyLinePlaceholder":247},[169,1212,1213],{"class":171,"line":395},[169,1214,1215],{"class":197},"  \u002F\u002F Calcula o primeiro dígito verificador\n",[169,1217,1218,1220,1222,1224,1226],{"class":171,"line":417},[169,1219,312],{"class":175},[169,1221,315],{"class":183},[169,1223,210],{"class":175},[169,1225,320],{"class":225},[169,1227,295],{"class":183},[169,1229,1230],{"class":171,"line":422},[169,1231,248],{"emptyLinePlaceholder":247},[169,1233,1234,1236,1238,1240,1242,1244,1246,1248,1250,1252,1254,1257],{"class":171,"line":431},[169,1235,357],{"class":175},[169,1237,360],{"class":183},[169,1239,363],{"class":175},[169,1241,366],{"class":183},[169,1243,210],{"class":175},[169,1245,320],{"class":225},[169,1247,379],{"class":183},[169,1249,266],{"class":175},[169,1251,462],{"class":225},[169,1253,387],{"class":183},[169,1255,1256],{"class":175},"++",[169,1258,191],{"class":183},[169,1260,1261,1263,1265,1268,1271,1274,1276,1278,1281],{"class":171,"line":445},[169,1262,500],{"class":183},[169,1264,503],{"class":175},[169,1266,1267],{"class":179}," Number",[169,1269,1270],{"class":183},"(cpf[i]) ",[169,1272,1273],{"class":175},"*",[169,1275,360],{"class":183},[169,1277,412],{"class":225},[169,1279,1280],{"class":175}," -",[169,1282,1283],{"class":183}," i);\n",[169,1285,1286],{"class":171,"line":451},[169,1287,301],{"class":183},[169,1289,1290],{"class":171,"line":467},[169,1291,248],{"emptyLinePlaceholder":247},[169,1293,1294,1296,1299,1301,1303,1305,1307],{"class":171,"line":480},[169,1295,312],{"class":175},[169,1297,1298],{"class":183}," resto ",[169,1300,210],{"class":175},[169,1302,315],{"class":183},[169,1304,544],{"class":175},[169,1306,1138],{"class":225},[169,1308,295],{"class":183},[169,1310,1311,1313,1316,1318,1320,1322,1324,1327,1329,1332,1334,1336],{"class":171,"line":486},[169,1312,204],{"class":175},[169,1314,1315],{"class":183}," primeiroDigito ",[169,1317,210],{"class":175},[169,1319,1298],{"class":183},[169,1321,266],{"class":175},[169,1323,440],{"class":225},[169,1325,1326],{"class":175}," ?",[169,1328,320],{"class":225},[169,1330,1331],{"class":175}," :",[169,1333,1138],{"class":225},[169,1335,1280],{"class":175},[169,1337,1338],{"class":183}," resto;\n",[169,1340,1341],{"class":171,"line":492},[169,1342,248],{"emptyLinePlaceholder":247},[169,1344,1345],{"class":171,"line":497},[169,1346,1347],{"class":197},"  \u002F\u002F O primeiro dígito calculado deve ser igual ao informado\n",[169,1349,1350,1352,1355,1357,1359,1362,1365],{"class":171,"line":509},[169,1351,260],{"class":175},[169,1353,1354],{"class":183}," (primeiroDigito ",[169,1356,1135],{"class":175},[169,1358,1267],{"class":179},[169,1360,1361],{"class":183},"(cpf[",[169,1363,1364],{"class":225},"9",[169,1366,1367],{"class":183},"])) {\n",[169,1369,1370,1372,1374],{"class":171,"line":526},[169,1371,289],{"class":175},[169,1373,292],{"class":225},[169,1375,295],{"class":183},[169,1377,1378],{"class":171,"line":531},[169,1379,301],{"class":183},[169,1381,1382],{"class":171,"line":536},[169,1383,248],{"emptyLinePlaceholder":247},[169,1385,1386],{"class":171,"line":557},[169,1387,1388],{"class":197},"  \u002F\u002F Calcula o segundo dígito verificador\n",[169,1390,1391,1394,1396,1398],{"class":171,"line":563},[169,1392,1393],{"class":183},"  soma ",[169,1395,210],{"class":175},[169,1397,320],{"class":225},[169,1399,295],{"class":183},[169,1401,1402],{"class":171,"line":568},[169,1403,248],{"emptyLinePlaceholder":247},[169,1405,1406,1408,1410,1412,1414,1416,1418,1420,1422,1424,1426,1428],{"class":171,"line":574},[169,1407,357],{"class":175},[169,1409,360],{"class":183},[169,1411,363],{"class":175},[169,1413,366],{"class":183},[169,1415,210],{"class":175},[169,1417,320],{"class":225},[169,1419,379],{"class":183},[169,1421,266],{"class":175},[169,1423,547],{"class":225},[169,1425,387],{"class":183},[169,1427,1256],{"class":175},[169,1429,191],{"class":183},[169,1431,1432,1434,1436,1438,1440,1442,1444,1447,1449],{"class":171,"line":604},[169,1433,500],{"class":183},[169,1435,503],{"class":175},[169,1437,1267],{"class":179},[169,1439,1270],{"class":183},[169,1441,1273],{"class":175},[169,1443,360],{"class":183},[169,1445,1446],{"class":225},"11",[169,1448,1280],{"class":175},[169,1450,1283],{"class":183},[169,1452,1453],{"class":171,"line":627},[169,1454,301],{"class":183},[169,1456,1458],{"class":171,"line":1457},36,[169,1459,248],{"emptyLinePlaceholder":247},[169,1461,1463,1466,1468,1470,1472,1474],{"class":171,"line":1462},37,[169,1464,1465],{"class":183},"  resto ",[169,1467,210],{"class":175},[169,1469,315],{"class":183},[169,1471,544],{"class":175},[169,1473,1138],{"class":225},[169,1475,295],{"class":183},[169,1477,1479,1481,1484,1486,1488,1490,1492,1494,1496,1498,1500,1502],{"class":171,"line":1478},38,[169,1480,204],{"class":175},[169,1482,1483],{"class":183}," segundoDigito ",[169,1485,210],{"class":175},[169,1487,1298],{"class":183},[169,1489,266],{"class":175},[169,1491,440],{"class":225},[169,1493,1326],{"class":175},[169,1495,320],{"class":225},[169,1497,1331],{"class":175},[169,1499,1138],{"class":225},[169,1501,1280],{"class":175},[169,1503,1338],{"class":183},[169,1505,1507],{"class":171,"line":1506},39,[169,1508,248],{"emptyLinePlaceholder":247},[169,1510,1512],{"class":171,"line":1511},40,[169,1513,1514],{"class":197},"  \u002F\u002F O segundo dígito calculado também deve ser igual ao informado\n",[169,1516,1518,1520,1522,1525,1527,1529,1531],{"class":171,"line":1517},41,[169,1519,539],{"class":175},[169,1521,1483],{"class":183},[169,1523,1524],{"class":175},"===",[169,1526,1267],{"class":179},[169,1528,1361],{"class":183},[169,1530,412],{"class":225},[169,1532,1533],{"class":183},"]);\n",[169,1535,1537],{"class":171,"line":1536},42,[169,1538,560],{"class":183},[16,1540,1541],{},"Exemplos de uso:",[160,1543,1545],{"className":162,"code":1544,"language":164,"meta":165,"style":165},"console.log(validarCPF(\"529.982.247-25\"));\n\u002F\u002F true\n\nconsole.log(validarCPF(\"52998224725\"));\n\u002F\u002F true\n\nconsole.log(validarCPF(\"529.982.247-26\"));\n\u002F\u002F false\n\nconsole.log(validarCPF(\"111.111.111-11\"));\n\u002F\u002F false\n",[53,1546,1547,1569,1573,1577,1598,1602,1606,1627,1631,1635,1656],{"__ignoreMap":165},[169,1548,1549,1551,1553,1555,1558,1560,1562,1564,1566],{"class":171,"line":172},[169,1550,577],{"class":183},[169,1552,580],{"class":179},[169,1554,184],{"class":183},[169,1556,1557],{"class":179},"validarCPF",[169,1559,184],{"class":183},[169,1561,590],{"class":237},[169,1563,1057],{"class":593},[169,1565,590],{"class":237},[169,1567,1568],{"class":183},"));\n",[169,1570,1571],{"class":171,"line":194},[169,1572,601],{"class":197},[169,1574,1575],{"class":171,"line":201},[169,1576,248],{"emptyLinePlaceholder":247},[169,1578,1579,1581,1583,1585,1587,1589,1591,1594,1596],{"class":171,"line":244},[169,1580,577],{"class":183},[169,1582,580],{"class":179},[169,1584,184],{"class":183},[169,1586,1557],{"class":179},[169,1588,184],{"class":183},[169,1590,590],{"class":237},[169,1592,1593],{"class":593},"52998224725",[169,1595,590],{"class":237},[169,1597,1568],{"class":183},[169,1599,1600],{"class":171,"line":251},[169,1601,601],{"class":197},[169,1603,1604],{"class":171,"line":257},[169,1605,248],{"emptyLinePlaceholder":247},[169,1607,1608,1610,1612,1614,1616,1618,1620,1623,1625],{"class":171,"line":286},[169,1609,577],{"class":183},[169,1611,580],{"class":179},[169,1613,184],{"class":183},[169,1615,1557],{"class":179},[169,1617,184],{"class":183},[169,1619,590],{"class":237},[169,1621,1622],{"class":593},"529.982.247-26",[169,1624,590],{"class":237},[169,1626,1568],{"class":183},[169,1628,1629],{"class":171,"line":298},[169,1630,649],{"class":197},[169,1632,1633],{"class":171,"line":304},[169,1634,248],{"emptyLinePlaceholder":247},[169,1636,1637,1639,1641,1643,1645,1647,1649,1652,1654],{"class":171,"line":309},[169,1638,577],{"class":183},[169,1640,580],{"class":179},[169,1642,184],{"class":183},[169,1644,1557],{"class":179},[169,1646,184],{"class":183},[169,1648,590],{"class":237},[169,1650,1651],{"class":593},"111.111.111-11",[169,1653,590],{"class":237},[169,1655,1568],{"class":183},[169,1657,1658],{"class":171,"line":325},[169,1659,649],{"class":197},[16,1661,1662,1663,1666,1667,1669,1670,56],{},"O trecho ",[53,1664,1665],{},"replace(\u002F\\D\u002Fg, '')"," remove tudo que não for dígito. Isso permite aceitar tanto ",[53,1668,1057],{}," quanto ",[53,1671,1593],{},[16,1673,1674],{},"A expressão regular usada para dígitos repetidos merece atenção:",[160,1676,1678],{"className":162,"code":1677,"language":164,"meta":165,"style":165},"\u002F^(\\d)\\1{10}$\u002F;\n",[53,1679,1680],{"__ignoreMap":165},[169,1681,1682,1684,1686,1688,1690,1692,1694,1696],{"class":171,"line":172},[169,1683,222],{"class":221},[169,1685,1172],{"class":175},[169,1687,184],{"class":1175},[169,1689,1178],{"class":225},[169,1691,1181],{"class":1175},[169,1693,1184],{"class":175},[169,1695,222],{"class":221},[169,1697,295],{"class":183},[16,1699,1700,1701,1703],{},"Ela identifica uma sequência de 11 caracteres formada pelo mesmo dígito. Isso impede que valores como ",[53,1702,1651],{}," sejam aceitos.",[16,1705,1706,1707,1710],{},"Esse é um detalhe que costuma pegar quem já bateu cabeça com o problema: CPFs com todos os dígitos iguais passam pela conta matemática, mas devem ser rejeitados explicitamente. Se você implementar apenas os cálculos, ",[53,1708,1709],{},"11111111111"," será considerado válido pelo seu código.",[16,1712,1713,1714,56],{},"Se quiser testar entradas rapidamente sem criar um formulário, use ",[662,1715,1718],{"href":1716,"rel":1717},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas\u002Fvalidador-de-cpf",[666],"nosso validador de CPF online, gratuito",[95,1720,1722],{"id":1721},"validação-no-formulário","Validação no formulário",[16,1724,1725],{},"Você pode chamar a função no evento de envio do formulário:",[160,1727,1729],{"className":162,"code":1728,"language":164,"meta":165,"style":165},"const formulario = document.querySelector(\"#formulario\");\nconst campoCPF = document.querySelector(\"#cpf\");\nconst mensagem = document.querySelector(\"#mensagem\");\n\nformulario.addEventListener(\"submit\", function (evento) {\n  evento.preventDefault();\n\n  if (!validarCPF(campoCPF.value)) {\n    mensagem.textContent = \"Informe um CPF válido.\";\n    return;\n  }\n\n  mensagem.textContent = \"CPF válido.\";\n});\n",[53,1730,1731,1758,1782,1806,1810,1838,1849,1853,1867,1884,1890,1894,1898,1914],{"__ignoreMap":165},[169,1732,1733,1736,1739,1741,1744,1747,1749,1751,1754,1756],{"class":171,"line":172},[169,1734,1735],{"class":175},"const",[169,1737,1738],{"class":183}," formulario ",[169,1740,210],{"class":175},[169,1742,1743],{"class":183}," document.",[169,1745,1746],{"class":179},"querySelector",[169,1748,184],{"class":183},[169,1750,590],{"class":237},[169,1752,1753],{"class":593},"#formulario",[169,1755,590],{"class":237},[169,1757,241],{"class":183},[169,1759,1760,1762,1765,1767,1769,1771,1773,1775,1778,1780],{"class":171,"line":194},[169,1761,1735],{"class":175},[169,1763,1764],{"class":183}," campoCPF ",[169,1766,210],{"class":175},[169,1768,1743],{"class":183},[169,1770,1746],{"class":179},[169,1772,184],{"class":183},[169,1774,590],{"class":237},[169,1776,1777],{"class":593},"#cpf",[169,1779,590],{"class":237},[169,1781,241],{"class":183},[169,1783,1784,1786,1789,1791,1793,1795,1797,1799,1802,1804],{"class":171,"line":201},[169,1785,1735],{"class":175},[169,1787,1788],{"class":183}," mensagem ",[169,1790,210],{"class":175},[169,1792,1743],{"class":183},[169,1794,1746],{"class":179},[169,1796,184],{"class":183},[169,1798,590],{"class":237},[169,1800,1801],{"class":593},"#mensagem",[169,1803,590],{"class":237},[169,1805,241],{"class":183},[169,1807,1808],{"class":171,"line":244},[169,1809,248],{"emptyLinePlaceholder":247},[169,1811,1812,1815,1818,1820,1822,1825,1827,1829,1831,1833,1836],{"class":171,"line":251},[169,1813,1814],{"class":183},"formulario.",[169,1816,1817],{"class":179},"addEventListener",[169,1819,184],{"class":183},[169,1821,590],{"class":237},[169,1823,1824],{"class":593},"submit",[169,1826,590],{"class":237},[169,1828,234],{"class":183},[169,1830,176],{"class":175},[169,1832,360],{"class":183},[169,1834,1835],{"class":187},"evento",[169,1837,191],{"class":183},[169,1839,1840,1843,1846],{"class":171,"line":257},[169,1841,1842],{"class":183},"  evento.",[169,1844,1845],{"class":179},"preventDefault",[169,1847,1848],{"class":183},"();\n",[169,1850,1851],{"class":171,"line":286},[169,1852,248],{"emptyLinePlaceholder":247},[169,1854,1855,1857,1859,1862,1864],{"class":171,"line":298},[169,1856,260],{"class":175},[169,1858,360],{"class":183},[169,1860,1861],{"class":175},"!",[169,1863,1557],{"class":179},[169,1865,1866],{"class":183},"(campoCPF.value)) {\n",[169,1868,1869,1872,1874,1877,1880,1882],{"class":171,"line":304},[169,1870,1871],{"class":183},"    mensagem.textContent ",[169,1873,210],{"class":175},[169,1875,1876],{"class":237}," \"",[169,1878,1879],{"class":593},"Informe um CPF válido.",[169,1881,590],{"class":237},[169,1883,295],{"class":183},[169,1885,1886,1888],{"class":171,"line":309},[169,1887,289],{"class":175},[169,1889,295],{"class":183},[169,1891,1892],{"class":171,"line":325},[169,1893,301],{"class":183},[169,1895,1896],{"class":171,"line":343},[169,1897,248],{"emptyLinePlaceholder":247},[169,1899,1900,1903,1905,1907,1910,1912],{"class":171,"line":348},[169,1901,1902],{"class":183},"  mensagem.textContent ",[169,1904,210],{"class":175},[169,1906,1876],{"class":237},[169,1908,1909],{"class":593},"CPF válido.",[169,1911,590],{"class":237},[169,1913,295],{"class":183},[169,1915,1916],{"class":171,"line":354},[169,1917,1918],{"class":183},"});\n",[16,1920,1921],{},"Essa validação melhora a experiência no navegador, mas não substitui a validação no servidor. Qualquer código executado no front-end pode ser alterado ou ignorado pelo cliente. O back-end deve repetir a validação antes de salvar ou processar o dado.",[23,1923,713],{"id":712},[95,1925,1927],{"id":1926},"validar-cpf-só-com-regex-de-formato","Validar CPF só com regex de formato",[16,1929,1930],{},"Uma expressão como esta:",[160,1932,1934],{"className":162,"code":1933,"language":164,"meta":165,"style":165},"\u002F^\\d{3}\\.\\d{3}\\.\\d{3}-\\d{2}$\u002F;\n",[53,1935,1936],{"__ignoreMap":165},[169,1937,1938,1940,1942,1944,1947,1950,1952,1954,1956,1958,1960,1962,1964,1967,1969],{"class":171,"line":172},[169,1939,222],{"class":221},[169,1941,1172],{"class":175},[169,1943,1178],{"class":225},[169,1945,1946],{"class":175},"{3}",[169,1948,1949],{"class":593},"\\.",[169,1951,1178],{"class":225},[169,1953,1946],{"class":175},[169,1955,1949],{"class":593},[169,1957,1178],{"class":225},[169,1959,1946],{"class":175},[169,1961,373],{"class":593},[169,1963,1178],{"class":225},[169,1965,1966],{"class":175},"{2}$",[169,1968,222],{"class":221},[169,1970,295],{"class":183},[16,1972,1973,1974,1977],{},"verifica apenas se o texto tem o formato ",[53,1975,1976],{},"000.000.000-00",". Ela não calcula os dígitos verificadores.",[16,1979,1980,1981,1984],{},"Por exemplo, ",[53,1982,1983],{},"123.456.789-00"," pode estar perfeitamente formatado e ainda assim ser um CPF inválido. Regex pode ajudar a conferir a aparência da entrada, mas não substitui o algoritmo do CPF.",[95,1986,1988],{"id":1987},"esquecer-os-zeros-à-esquerda","Esquecer os zeros à esquerda",[16,1990,1991],{},"CPF é identificador, não número para fazer operações matemáticas comuns. Por isso, trate-o como string.",[16,1993,1994,1995,1998],{},"Se você converter um CPF para ",[53,1996,1997],{},"Number",", um valor com zero inicial pode perder esse zero:",[160,2000,2002],{"className":162,"code":2001,"language":164,"meta":165,"style":165},"const cpf = Number(\"012.345.678-90\");\n",[53,2003,2004],{"__ignoreMap":165},[169,2005,2006,2008,2011,2013,2015,2017,2019,2022,2024],{"class":171,"line":172},[169,2007,1735],{"class":175},[169,2009,2010],{"class":183}," cpf ",[169,2012,210],{"class":175},[169,2014,1267],{"class":179},[169,2016,184],{"class":183},[169,2018,590],{"class":237},[169,2020,2021],{"class":593},"012.345.678-90",[169,2023,590],{"class":237},[169,2025,241],{"class":183},[16,2027,2028,2029,2032],{},"Além disso, números muito grandes não devem ser usados como representação principal de documentos. A função deste artigo converte a entrada para texto com ",[53,2030,2031],{},"String(cpf)"," e remove a formatação antes de calcular.",[16,2034,2035],{},"Na prática, prefira manter o valor vindo do campo HTML como string desde o início.",[95,2037,2039],{"id":2038},"não-normalizar-a-entrada","Não normalizar a entrada",[16,2041,2042],{},"Se o código espera exatamente 11 dígitos, ele pode rejeitar um CPF formatado antes mesmo de fazer o cálculo.",[16,2044,2045],{},"Esta etapa resolve o problema:",[160,2047,2049],{"className":162,"code":2048,"language":164,"meta":165,"style":165},"cpf = String(cpf).replace(\u002F\\D\u002Fg, \"\");\n",[53,2050,2051],{"__ignoreMap":165},[169,2052,2053,2056,2058,2060,2062,2064,2066,2068,2070,2072,2074,2076,2078],{"class":171,"line":172},[169,2054,2055],{"class":183},"cpf ",[169,2057,210],{"class":175},[169,2059,1095],{"class":179},[169,2061,1098],{"class":183},[169,2063,216],{"class":179},[169,2065,184],{"class":183},[169,2067,222],{"class":221},[169,2069,226],{"class":225},[169,2071,222],{"class":221},[169,2073,231],{"class":175},[169,2075,234],{"class":183},[169,2077,238],{"class":237},[169,2079,241],{"class":183},[16,2081,2082],{},"Ela remove pontos, traços, espaços e outros caracteres não numéricos. Depois disso, a função verifica se sobraram exatamente 11 dígitos.",[95,2084,2086],{"id":2085},"validar-apenas-no-navegador","Validar apenas no navegador",[16,2088,2089],{},"A validação no front-end é útil para dar retorno imediato, mas não é uma camada de segurança. Um usuário pode fazer uma requisição diretamente ao servidor sem passar pelo JavaScript da página.",[16,2091,2092],{},"A mesma regra deve existir no back-end, de preferência em uma função centralizada e coberta por testes.",[23,2094,775],{"id":774},[95,2096,2098],{"id":2097},"como-saber-se-um-cpf-é-válido","Como saber se um CPF é válido?",[16,2100,2101],{},"Primeiro, remova pontos e traço e confirme que restaram 11 dígitos. Depois, rejeite sequências com todos os dígitos iguais e calcule os dois dígitos verificadores conforme o algoritmo do CPF.",[16,2103,2104,2105,2108],{},"O CPF só será matematicamente válido se os dois dígitos calculados forem iguais aos dois últimos dígitos informados. A função ",[53,2106,2107],{},"validarCPF(cpf)"," apresentada neste artigo executa todas essas etapas.",[16,2110,2111],{},"Isso não significa que o documento esteja ativo, regular ou associado a uma pessoa específica. Significa apenas que ele passa pela validação matemática.",[95,2113,2115],{"id":2114},"como-calcular-o-dígito-verificador-do-cpf","Como calcular o dígito verificador do CPF?",[16,2117,2118],{},"Para o primeiro dígito, multiplique os 9 dígitos base pelos pesos de 10 a 2. Some os resultados e calcule o resto da divisão por 11.",[117,2120,2121,2127],{},[64,2122,2123,2124,56],{},"Se o resto for 0 ou 1, o dígito será ",[53,2125,2126],{},"0",[64,2128,2129,2130,56],{},"Caso contrário, o dígito será ",[53,2131,2132],{},"11 - resto",[16,2134,2135],{},"Para o segundo dígito, faça a mesma operação usando os 10 primeiros dígitos e os pesos de 11 a 2.",[16,2137,2138],{},"Em JavaScript, a parte central do cálculo pode ser escrita assim:",[160,2140,2142],{"className":162,"code":2141,"language":164,"meta":165,"style":165},"const digito = resto \u003C 2 ? 0 : 11 - resto;\n",[53,2143,2144],{"__ignoreMap":165},[169,2145,2146,2148,2151,2153,2155,2157,2159,2161,2163,2165,2167,2169],{"class":171,"line":172},[169,2147,1735],{"class":175},[169,2149,2150],{"class":183}," digito ",[169,2152,210],{"class":175},[169,2154,1298],{"class":183},[169,2156,266],{"class":175},[169,2158,440],{"class":225},[169,2160,1326],{"class":175},[169,2162,320],{"class":225},[169,2164,1331],{"class":175},[169,2166,1138],{"class":225},[169,2168,1280],{"class":175},[169,2170,1338],{"class":183},[95,2172,2174],{"id":2173},"validar-cpf-é-a-mesma-coisa-que-consultar-na-receita-federal","Validar CPF é a mesma coisa que consultar na Receita Federal?",[16,2176,2177],{},"Não. A validação matemática é uma verificação local: o sistema calcula os dígitos e compara o resultado com o CPF informado.",[16,2179,2180],{},"Uma consulta oficial é outra operação. Ela pode verificar informações cadastrais e a situação do CPF em uma base oficial, normalmente por meio de um serviço autorizado ou dos canais disponibilizados pela Receita Federal.",[16,2182,2183],{},"Portanto, um CPF pode passar pelo algoritmo e ainda não estar regular, não existir no cadastro consultado ou não pertencer à pessoa que o informou. O código JavaScript não confirma identidade nem situação cadastral.",[95,2185,2187],{"id":2186},"dá-para-gerar-um-cpf-válido-para-testes","Dá para gerar um CPF válido para testes?",[16,2189,2190,2191,2196],{},"Sim. Para testar máscaras, formulários e APIs, você pode usar números que passam pela validação matemática sem usar dados reais. Se você precisa de números de CPF válidos só para testar formulários, ",[662,2192,2195],{"href":2193,"rel":2194},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas\u002Fgerador-de-cpf",[666],"nosso gerador de CPF"," resolve isso rapidinho.",[16,2198,2199],{},"Use dados de teste de forma controlada e deixe claro, no ambiente da equipe, que eles são fictícios. Também evite colocar documentos reais em exemplos públicos, arquivos de teste ou repositórios.",[95,2201,2203],{"id":2202},"a-função-valida-se-o-cpf-pertence-ao-usuário","A função valida se o CPF pertence ao usuário?",[16,2205,2206],{},"Não. Ela verifica somente o formato normalizado, a quantidade de dígitos, a regra dos dígitos verificadores e a rejeição de sequências repetidas.",[16,2208,2209],{},"Para confirmar titularidade, seria necessária uma etapa diferente, com uma fonte oficial ou um fluxo de verificação apropriado. A validação local não substitui esse processo.",[23,2211,2213],{"id":2212},"próximos-passos","Próximos passos",[16,2215,2216,2217,2219],{},"Agora você já tem o algoritmo do CPF e uma função ",[53,2218,2107],{}," pronta para adaptar ao seu projeto. Coloque a validação no front-end para orientar o usuário e repita a regra no back-end antes de persistir ou aceitar o cadastro.",[16,2221,2222,2223,2227],{},"Se quiser conferir valores sem escrever código, acesse ",[662,2224,2226],{"href":1716,"rel":2225},[666],"o nosso verificador de CPF online",". Depois, vale transformar os exemplos deste artigo em testes automatizados para cobrir entradas formatadas, CPFs inválidos e documentos com zeros à esquerda.",[842,2229,2230],{},"html pre.shiki code .s0Tla, html code.shiki .s0Tla{--shiki-default:#FF79C6}html pre.shiki code .sAOxA, html code.shiki .sAOxA{--shiki-default:#50FA7B}html pre.shiki code .sCdxs, html code.shiki .sCdxs{--shiki-default:#F8F8F2}html pre.shiki code .sGEwX, html code.shiki .sGEwX{--shiki-default:#FFB86C;--shiki-default-font-style:italic}html pre.shiki code .shSDL, html code.shiki .shSDL{--shiki-default:#6272A4}html pre.shiki code .s-doY, html code.shiki .s-doY{--shiki-default:#FF5555}html pre.shiki code .sIQBb, html code.shiki .sIQBb{--shiki-default:#BD93F9}html pre.shiki code .seVfx, html code.shiki .seVfx{--shiki-default:#E9F284}html pre.shiki code .smvxG, html code.shiki .smvxG{--shiki-default:#FFB86C}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s-mGx, html code.shiki .s-mGx{--shiki-default:#F1FA8C}",{"title":165,"searchDepth":194,"depth":194,"links":2232},[2233,2237,2240,2246,2253],{"id":902,"depth":194,"text":903,"children":2234},[2235,2236],{"id":923,"depth":201,"text":924},{"id":988,"depth":201,"text":989},{"id":154,"depth":194,"text":155,"children":2238},[2239],{"id":1721,"depth":201,"text":1722},{"id":712,"depth":194,"text":713,"children":2241},[2242,2243,2244,2245],{"id":1926,"depth":201,"text":1927},{"id":1987,"depth":201,"text":1988},{"id":2038,"depth":201,"text":2039},{"id":2085,"depth":201,"text":2086},{"id":774,"depth":194,"text":775,"children":2247},[2248,2249,2250,2251,2252],{"id":2097,"depth":201,"text":2098},{"id":2114,"depth":201,"text":2115},{"id":2173,"depth":201,"text":2174},{"id":2186,"depth":201,"text":2187},{"id":2202,"depth":201,"text":2203},{"id":2212,"depth":194,"text":2213},[164,869],"Aprenda como validar um CPF com JavaScript puro, calcular os dígitos verificadores, tratar a formatação e rejeitar sequências inválidas em formulários web.","how-to-validate-cpf-with-javascript",{},"\u002Fblog\u002Fcomo-validar-cpf-com-javascript","como-validar-cpf-com-javascript",{"title":886,"description":2255},{"loc":2258,"lastmod":881},"blog\u002Fcomo-validar-cpf-com-javascript",1197,"HhWvxesebX_RYojibYOXfOdEj4UD7XeUxaMM7Xe7_ic",{"id":2266,"title":2267,"articleCover":2268,"articleCoverEmbed":8,"articleCoverEmbedUploadDate":8,"articleCoverHeight":9,"articleCoverWidth":10,"authorId":11,"body":2269,"categoriesIds":2572,"description":2573,"enAlternateSlug":2574,"extension":872,"meta":2575,"navigation":247,"path":2576,"ptBrAlternateSlug":2577,"publishedAt":2578,"seo":2579,"sitemap":2580,"stem":2590,"updatedAt":881,"wordCount":2591,"__hash__":2592},"blog\u002Fblog\u002Fhub-de-ferramentas-gratuitas-para-desenvolvedores.md","Criei um Hub de Ferramentas Web Gratuitas para Devs","\u002Fimages\u002Fblog\u002Fferramentas\u002Fhub-ferramentas-gratuitas-para-desenvolvedores.webp",{"type":13,"value":2270,"toc":2553},[2271,2274,2285,2289,2293,2301,2304,2307,2314,2318,2328,2332,2342,2346,2350,2360,2364,2373,2377,2381,2389,2393,2397,2405,2409,2413,2426,2430,2434,2438,2445,2448,2452,2455,2458,2462,2465,2468,2472,2487,2501,2505,2511,2518,2522,2525,2539,2543],[16,2272,2273],{},"Sabe aquele momento em que você precisa gerar um CPF para testar um formulário? Ou quando precisa validar um cartão de crédito fake no ambiente de desenvolvimento? Durante minha carreira como dev, sempre recorria a diferentes sites para essas tarefas simples, mas essenciais do dia a dia.",[16,2275,2276,2277,2284],{},"Cada site possuía diferentes layouts e experiências de usuário, algumas boas, outras não. Pensando em criar algo que centralize essas diferentes ferramentas com uma interface simples e com excelente experiência de usuário, que criei o ",[31,2278,2279],{},[662,2280,2283],{"href":2281,"rel":2282},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas",[666],"Hub de Ferramentas para programadores do Código ao Ponto",", um hub totalmente gratuito que reúne várias ferramentas em um único local, que são diretas ao ponto e que funcionam sem a necessidade de criar um cadastro.",[23,2286,2288],{"id":2287},"quais-ferramentas-estão-disponíveis-no-hub","Quais ferramentas estão disponíveis no Hub?",[95,2290,2292],{"id":2291},"planning-poker-online","Planning Poker Online",[16,2294,2295,2300],{},[662,2296,2299],{"href":2297,"rel":2298},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas\u002Fplanning-poker",[666],"A ferramenta mais completa do hub",". Crie uma sala, compartilhe o link com o time (sem necessidade de cadastro), e todos podem votar simultaneamente nas estimativas de tarefas.",[16,2302,2303],{},"A ferramenta funciona em tempo real com WebSocket - quando alguém vota, todos veem instantaneamente. Tem temporizador da sessão, lista de participantes com status, e opções de votação além da sequência tradicional de Fibonacci.",[16,2305,2306],{},"É o tipo de ferramenta \"mão na roda\" quando seu time precisa fazer uma Sprint Planning e não encontra um Planning Poker de qualidade e gratuito.",[2308,2309],"img",{"alt":2310,"height":2311,"src":2312,"width":2313},"interface da ferramenta Planning Poker",405,"\u002Fimages\u002Fblog\u002Fferramentas\u002Fferramenta-planning-poker-gratuito.webp",768,[95,2315,2317],{"id":2316},"gerador-e-validador-de-cpf","Gerador e Validador de CPF",[16,2319,2320,2321,2327],{},"Uma das ferramentas mais populares do hub. O ",[31,2322,2323],{},[662,2324,2326],{"href":2193,"rel":2325},[666],"Gerador de CPF"," cria números válidos instantaneamente para uso em ambientes de teste. Esse sucesso de acessos se deu devido à sua boa posição nas páginas de resultado de pesquisa do Google para o termo \"Gerador de CPF\", variando entre a segunda e quarta posição.",[2308,2329],{"alt":2330,"height":2311,"src":2331,"width":2313},"interface da ferramenta Gerador de CPF","\u002Fimages\u002Fblog\u002Fferramentas\u002Fferramenta-gerador-de-cpf.webp",[16,2333,2334,2335,2341],{},"Como complemento, também foi criado o ",[31,2336,2337],{},[662,2338,2340],{"href":1716,"rel":2339},[666],"Validador de CPF"," que verifica se um número é válido estruturalmente com feedback imediato.",[2308,2343],{"alt":2344,"height":2311,"src":2345,"width":2313},"interface da ferramenta Validador de CPF","\u002Fimages\u002Fblog\u002Fferramentas\u002Fferramenta-validador-de-cpf.webp",[95,2347,2349],{"id":2348},"gerador-e-validador-de-cartão-de-crédito","Gerador e Validador de Cartão de Crédito",[16,2351,2352,2353,2359],{},"O ",[31,2354,2355],{},[662,2356,2358],{"href":768,"rel":2357},[666],"Gerador de cartão de crédito"," permite selecionar a bandeira (Visa, Mastercard, American Express, etc.) e cria dados fictícios completos: número do cartão, CVV e data de validade. Cada campo tem um botão de cópia rápida ao lado.",[2308,2361],{"alt":2362,"height":2311,"src":2363,"width":2313},"interface da ferramenta Gerador de Cartão de Crédito","\u002Fimages\u002Fblog\u002Fferramentas\u002Fferramenta-gerador-de-cartao-de-credito.webp",[16,2365,2352,2366,2372],{},[31,2367,2368],{},[662,2369,2371],{"href":664,"rel":2370},[666],"Validador de cartão de crédito"," identifica automaticamente a bandeira e verifica se o número é estruturalmente válido. Essencial para testar fluxos de pagamento.",[2308,2374],{"alt":2375,"height":2311,"src":2376,"width":2313},"interface da ferramenta Validador de Cartão de Crédito","\u002Fimages\u002Fblog\u002Fferramentas\u002Fferramenta-validador-de-cartao-de-credito.webp",[95,2378,2380],{"id":2379},"contador-de-palavras-e-caracteres","Contador de Palavras e Caracteres",[16,2382,2383,2388],{},[662,2384,2387],{"href":2385,"rel":2386},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas\u002Fcontador-de-caracteres-e-palavras",[666],"Conta em tempo real enquanto você digita ou cola texto",". Mostra caracteres totais, caracteres sem espaços, número de espaços e total de palavras. Útil para respeitar limites de caracteres em APIs ou validar campos de formulário.",[2308,2390],{"alt":2391,"height":2311,"src":2392,"width":2313},"interface da ferramenta Contador de Caracteres e Palavras","\u002Fimages\u002Fblog\u002Fferramentas\u002Fferramenta-contador-de-caracteres-e-palavras.webp",[95,2394,2396],{"id":2395},"conversor-de-formato-de-data","Conversor de Formato de Data",[16,2398,2399,2404],{},[662,2400,2403],{"href":2401,"rel":2402},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas\u002Fconversor-de-formato-de-data",[666],"Converte datas para os formatos mais usados em desenvolvimento",": ISO String, Timestamp e UTC String. Você pode usar a data\u002Fhora atual ou inserir uma data específica, com botão de cópia rápida no resultado.",[2308,2406],{"alt":2407,"height":2311,"src":2408,"width":2313},"interface da ferramenta Conversor de Formato de Data","\u002Fimages\u002Fblog\u002Fferramentas\u002Fferramentas-gerador-e-conversor-de-formato-de-datas.webp",[95,2410,2412],{"id":2411},"gerador-de-link-do-whatsapp","Gerador de Link do WhatsApp",[16,2414,2415,2416,2421,2422,2425],{},"Insira o número de telefone (com seleção de código do país) e a mensagem desejada. ",[662,2417,2420],{"href":2418,"rel":2419},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas\u002Fgerador-de-url-mensagem-do-whatsapp",[666],"A ferramenta"," gera um link direto para abrir a conversa no WhatsApp, com ",[31,2423,2424],{},"pré-visualização em tempo real"," mostrando exatamente como a mensagem vai aparecer, incluindo formatações e emojis. Muito útil para testar os textos que serão usados naquelas tarefas em que o usuário clica em \"Entrar em contato pelo Whatsapp\".",[2308,2427],{"alt":2428,"height":2311,"src":2429,"width":2313},"interface da ferramenta Gerador de URL pré-preenchida com texto no Whatsapp","\u002Fimages\u002Fblog\u002Fferramentas\u002Fferramenta-gerador-de-link-compartilhavel-no-whatsapp.webp",[23,2431,2433],{"id":2432},"decisões-de-design-e-usabilidade","Decisões de design e usabilidade",[95,2435,2437],{"id":2436},"sem-fricção-sem-barreiras","Sem fricção, sem barreiras",[16,2439,2440,2441,2444],{},"A decisão mais importante do projeto foi: ",[31,2442,2443],{},"nenhuma ferramenta exige cadastro",". Isso foi não-negociável desde o início. Acesse, use, pronto.",[16,2446,2447],{},"Para o Planning Poker, que é colaborativo, você pode criar as salas com links compartilháveis. Sem login, sem senha, sem complicação.",[95,2449,2451],{"id":2450},"interface-limpa-e-intuitiva","Interface limpa e intuitiva",[16,2453,2454],{},"Cada ferramenta segue um padrão visual consistente: área de input à esquerda, resultado à direita, e botões de ação bem visíveis.",[16,2456,2457],{},"Abaixo de cada ferramenta, tem uma seção educativa explicando casos de uso, exemplos práticos e como aquela ferramenta pode ajudar no dia a dia. A ideia é que mesmo quem nunca usou entenda rapidamente o valor.",[95,2459,2461],{"id":2460},"acessível-em-português-e-inglês","Acessível em português e inglês",[16,2463,2464],{},"Desde o início, implementei internacionalização. O sistema detecta automaticamente o idioma do navegador, mas você pode trocar manualmente quando quiser.",[16,2466,2467],{},"Português para atender a comunidade brasileira, inglês para alcançar desenvolvedores do mundo todo. A arquitetura está preparada para adicionar novos idiomas facilmente.",[95,2469,2471],{"id":2470},"responsivo-e-rápido","Responsivo e rápido",[16,2473,2474,2475,2480,2481,2486],{},"Todas essas ferramentas possuem suas versões em ",[662,2476,2479],{"href":2477,"rel":2478},"https:\u002F\u002Fcodigoaoponto.com\u002Fen\u002Ftools",[666],"Inglês com o I18N"," e são testadas com o ",[662,2482,2485],{"href":2483,"rel":2484},"https:\u002F\u002Fpagespeed.web.dev\u002F",[666],"Lighthouse\u002FPageSpeed Insights"," para garantir boa performance de carregamento e estabilidade visual.",[16,2488,2489,2490,105,2495,2500],{},"A como meta mínima de pontuação foi de 90 pontos no PageSpeed Insights em todas as categorias, o que é um grande desafio, especialmente quando se usa scripts de terceiros como ",[662,2491,2494],{"href":2492,"rel":2493},"https:\u002F\u002Fdevelopers.google.com\u002Fanalytics",[666],"Google Analytics",[662,2496,2499],{"href":2497,"rel":2498},"https:\u002F\u002Fadsense.google.com\u002Fstart",[666],"Google Adsense",", mas que fazendo as devidas otimizações, entregam uma ótima velocidade de carregamento.",[23,2502,2504],{"id":2503},"a-stack-por-trás","A stack por trás",[16,2506,2352,2507,2510],{},[31,2508,2509],{},"Nuxt 4"," foi escolhido no frontend pelo seu foco em performance e SEO, aspectos muito importantes para ser bem ranqueado pelo Google.",[16,2512,2513,2514,2517],{},"No backend, foi escolhido o ",[31,2515,2516],{},"NestJS"," pela sua arquitetura modular e suporte nativo a WebSocket, necessário para o Planning Poker. Além de também ser em JavaScript, facilitando o desenvolvimento Full Stack do projeto.",[23,2519,2521],{"id":2520},"o-que-vem-por-aí","O que vem por aí",[16,2523,2524],{},"O backlog tem algumas ideias interessantes:",[117,2526,2527,2533],{},[64,2528,2529,2532],{},[31,2530,2531],{},"Sprint Retro"," para cerimônias de retrospectiva",[64,2534,2535,2538],{},[31,2536,2537],{},"Mais utilitários"," conforme a comunidade for sugerindo",[23,2540,2542],{"id":2541},"quer-conhecer","Quer conhecer?",[16,2544,2545,2546,2552],{},"A ferramenta tem ajudado centenas de usuários diariamente, você também pode ser um deles ",[31,2547,2548],{},[662,2549,2551],{"href":2281,"rel":2550},[666],"Clicando aqui",", espero te ajudar, muito obrigado 🙋🏻",{"title":165,"searchDepth":194,"depth":194,"links":2554},[2555,2563,2569,2570,2571],{"id":2287,"depth":194,"text":2288,"children":2556},[2557,2558,2559,2560,2561,2562],{"id":2291,"depth":201,"text":2292},{"id":2316,"depth":201,"text":2317},{"id":2348,"depth":201,"text":2349},{"id":2379,"depth":201,"text":2380},{"id":2395,"depth":201,"text":2396},{"id":2411,"depth":201,"text":2412},{"id":2432,"depth":194,"text":2433,"children":2564},[2565,2566,2567,2568],{"id":2436,"depth":201,"text":2437},{"id":2450,"depth":201,"text":2451},{"id":2460,"depth":201,"text":2461},{"id":2470,"depth":201,"text":2471},{"id":2503,"depth":194,"text":2504},{"id":2520,"depth":194,"text":2521},{"id":2541,"depth":194,"text":2542},[869],"Criei um hub de ferramentas web gratuitas para programadores: gerador de CPF, validadores, Planning Poker e outros utilitários, em português e inglês.","free-developer-tools-hub",{},"\u002Fblog\u002Fhub-de-ferramentas-gratuitas-para-desenvolvedores","hub-de-ferramentas-gratuitas-para-desenvolvedores","2026-01-06",{"title":2267,"description":2573},{"loc":2576,"images":2581,"lastmod":881},[2582,2583,2584,2585,2586,2587,2588,2589],{"loc":2312},{"loc":2331},{"loc":2345},{"loc":2363},{"loc":2376},{"loc":2392},{"loc":2408},{"loc":2429},"blog\u002Fhub-de-ferramentas-gratuitas-para-desenvolvedores",1034,"yjmUjnoFNggMq3x61INaFg-ySaqtVv517zm-qVl13o4",1791682338138]