Biblioteca JavaScript leve (≈ 9 KB minificada, zero dependências) para detectar o navegador do cliente, classificar o nível de suporte e avisar o usuário quando for necessário atualizar. Parametrizável por chamada, com API ergonômica para desenvolvedor e compatibilidade preservada com IE11.
- Versão: 3.0.0
- Licença: MIT
- O que mudou na v3
- Instalação
- Uso mínimo
- Uso programático
- Uso via bundler (ES modules / CommonJS)
- Configuração (
Config) - Retorno (
Resultado) - Eventos
- Navegadores detectados
- Como o suporte é classificado
- Segurança
- Compatibilidade
- Desenvolvimento
- Migrando da v1 para a v3
- Contribuições
A v3 é uma reescrita completa focada em correção, segurança e experiência do
desenvolvedor. Ela preserva os campos de retorno antigos (s, j, f, m), então
código chamador da v1 continua funcionando sem alterações.
Bugs críticos da v1 que a v3 corrige:
- Edge (Chromium) agora é detectado corretamente — antes caía em
Chromepor causa do tokenEdg/(nãoEdge/) no user agent. - Chrome iOS (
CriOS/), Firefox iOS (FxiOS/) e Edge iOS (EdgiOS/) são identificados corretamente — antes todos caíam em Safari. - Safari 17.4 e outras versões decimais são comparadas como decimais — antes
parseInttruncava e impedia atingir suporte completo. - User agents desconhecidos não quebram mais a execução — a v1 lançava
TypeErrorem.slicesobreundefined. - Usuários com navegador totalmente atualizado não recebem mais o link "Clique para atualizar" indevidamente.
- Link de atualização agora tem
rel="noopener noreferrer"(mitigação de tabnabbing reverso). - URLs usam
https://explícito.
Novidades de DX:
- Configuração completa por chamada: versões, URLs, mensagens, seletor do elemento, classe CSS, nome do evento, debug.
- Retorno enriquecido com nomes legíveis (
'Chrome'em vez de só'c'), classificação como string ('suportado' | 'desatualizado' | 'nao-suportado') e booleans de conveniência. CustomEventdisparado nawindowpermite integração desacoplada.- Validação de configuração com
TypeErrorexplicando exatamente qual chave está inválida. - Tipagem via JSDoc
@typedef(intellisense automático no VS Code). - Funções internas expostas em
checarNavegadorCliente.internopara testes.
npm install checar-versao-do-navegador-do-cliente
# ou
yarn add checar-versao-do-navegador-do-cliente
# ou
pnpm add checar-versao-do-navegador-do-cliente<!-- unpkg (sempre a última versão major 3) -->
<script src="https://unpkg.com/checar-versao-do-navegador-do-cliente@3/checarNavegadorCliente.min.js"></script>
<!-- jsDelivr -->
<script src="https://cdn.jsdelivr.net/npm/checar-versao-do-navegador-do-cliente@3/checarNavegadorCliente.min.js"></script>Baixe checarNavegadorCliente.js ou checarNavegadorCliente.min.js e inclua:
<div id="infos-ao-cliente"></div>
<script src="checarNavegadorCliente.js"></script>A biblioteca usa formato UMD — funciona diretamente em <script>, require() e
import sem configuração adicional.
<!doctype html>
<html lang="pt-br">
<head>
<meta charset="utf-8">
<title>Meu sistema</title>
<style>.info { background: #fffbe6; padding: 8px; border: 1px solid #ffe58f; }</style>
</head>
<body>
<div id="infos-ao-cliente"></div>
<!-- ... resto da página ... -->
<script src="checarNavegadorCliente.js"></script>
</body>
</html>Se o navegador do usuário estiver desatualizado ou não suportado, a <div> é
preenchida com a mensagem apropriada e um link para atualização. Se estiver
totalmente atualizado, nada acontece.
// Desliga a auto-execução para controlar o momento
checarNavegadorCliente.auto = false;
// Chama com override parcial
var resultado = checarNavegadorCliente({
versoes: {
c: [120, 130], // Chrome mínimo 120, alvo 130
f: [120, 128] // Firefox mínimo 120, alvo 128
},
elemento: '#meu-aviso-custom',
debug: true
});
if (resultado.naoSuportado) {
// Redirecionar, bloquear, registrar telemetria etc.
}Sem passar argumentos, checarNavegadorCliente() usa todos os defaults — útil
para executar manualmente em momentos específicos do ciclo de vida da página.
A biblioteca é UMD, então funciona com qualquer bundler (Webpack, Vite, Rollup, esbuild, Parcel). Ela detecta o ambiente e usa o mecanismo de export apropriado.
// ES modules
import checarNavegadorCliente from 'checar-versao-do-navegador-do-cliente';
const resultado = checarNavegadorCliente({ debug: true });
if (resultado.naoSuportado) { /* ... */ }// CommonJS
const checarNavegadorCliente = require('checar-versao-do-navegador-do-cliente');
const resultado = checarNavegadorCliente({ debug: true });Nota sobre SSR (Next.js, Nuxt, Remix etc.): em ambiente Node sem window
nem navigator, a função retorna nivel: 0 e navegador.codigo: null graciosamente.
Você pode chamá-la em SSR sem proteção — o resultado será "não suportado" mas não
causará erro. Para só executar no cliente, faça o check usual:
if (typeof window !== 'undefined') {
const resultado = checarNavegadorCliente();
}Todos os campos são opcionais. O que você passar é mesclado sobre os defaults.
| Campo | Tipo | Default | Descrição |
|---|---|---|---|
versoes |
{ [codigo]: [minima, recomendada] } |
Ver Navegadores | Override parcial da tabela de versões. Só os códigos que você passar são sobrescritos. Valores aceitam decimais (Safari 17.4, Brave 1.57). |
urls |
{ [codigo]: string } |
URLs oficiais | Override parcial das URLs de atualização. |
mensagens |
{ naoSuportado?, desatualizado?, linkAtualizar? } |
Textos em PT-BR | Override dos textos exibidos ao usuário. |
elemento |
string | HTMLElement | null | false |
'#infos-ao-cliente' |
Seletor CSS, referência direta ao elemento, ou null/false para desativar totalmente a manipulação de DOM. |
classe |
string |
'info' |
Classe CSS adicionada ao elemento quando há aviso. |
dispararEvento |
boolean |
true |
Dispara CustomEvent na window. |
nomeEvento |
string |
'navegador:checado' |
Nome do evento disparado. |
debug |
boolean |
false |
Imprime diagnóstico em console.info. |
Também disponíveis como propriedades da função:
checarNavegadorCliente.auto— definafalseantes doloadpara pular auto-execução.checarNavegadorCliente.padroes— objetos com os defaults (versoes,urls,mensagens,nomes,config).checarNavegadorCliente.interno— funções puras para testes (detectar,calcularNivel,viaClientHints,viaUserAgent, etc.).checarNavegadorCliente.versao— string da versão atual.
{
// Classificação
nivel: 2, // 0 | 1 | 2
classificacao: 'suportado', // 'suportado' | 'desatualizado' | 'nao-suportado'
// Booleans derivados
suportado: true, // nivel >= 1
suportadoCompleto: true, // nivel === 2
desatualizado: false, // nivel === 1
naoSuportado: false, // nivel === 0
// Navegador detectado
navegador: {
codigo: 'c', // código curto
nome: 'Chrome', // nome legível humano
versao: 130, // versão detectada
versaoMinima: 109, // mínima da config
versaoRecomendada: 117, // alvo da config
urlAtualizacao: 'https://www.google.com/intl/pt-BR/chrome/update/'
},
// Metadados da detecção
deteccao: {
metodo: 'client-hints', // 'client-hints' | 'user-agent' | null
userAgent: 'Mozilla/5.0 ...'
},
// Aliases legados (mesmos valores da v1, para retrocompatibilidade)
s: 2, // === nivel
j: true, // === true (JavaScript habilitado)
f: true, // === suportadoCompleto
m: true // === suportado
}Quando o navegador não é reconhecido (user agent incomum, crawler, etc.), o retorno é seguro e estruturado:
{
nivel: 0,
classificacao: 'nao-suportado',
suportado: false, suportadoCompleto: false, desatualizado: false, naoSuportado: true,
navegador: {
codigo: null, nome: null, versao: 0,
versaoMinima: null, versaoRecomendada: null, urlAtualizacao: null
},
deteccao: { metodo: null, userAgent: '...' },
s: 0, j: true, f: false, m: false
}O evento navegador:checado é disparado na window após cada execução (a menos que
você passe dispararEvento: false). O objeto Resultado completo fica em event.detail.
window.addEventListener('navegador:checado', function (e) {
console.log(e.detail.navegador.nome + ' ' + e.detail.navegador.versao);
if (e.detail.naoSuportado) {
mostrarBloqueio();
}
});| Código | Navegador | Método primário | Padrão [min, recomendada] |
|---|---|---|---|
c |
Chrome (e Chrome iOS via CriOS/) |
Client Hints / UA Chrome\/ |
[109, 117] |
f |
Firefox (e Firefox iOS via FxiOS/) |
UA Firefox\/ / FxiOS\/ |
[115, 119] |
s |
Safari | UA Version\/ + Safari\/ |
[16, 17.4] |
o |
Opera | UA OPR\/ / Client Hints |
[95, 103] |
e |
Edge Chromium (e Edge iOS/Android) | UA Edg\/ / EdgiOS\/ / EdgA\/ / Client Hints |
[109, 117] |
sm |
Samsung Internet | UA SamsungBrowser\/ |
[24, 24] |
b |
Brave | Client Hints (UA é idêntico ao Chrome por política de privacidade) | [1.48, 1.57] |
a |
Android WebView | UA ; wv) com Chrome\/ |
[109, 117] |
i |
Internet Explorer | UA Trident\/ / MSIE |
[11, 11] |
Nota sobre Brave: o Brave remove deliberadamente o token "Brave" do user agent. A detecção só funciona via Client Hints (Chromium 90+). Em navegadores mais antigos, Brave é identificado como Chrome — o que é seguro, porque o Brave segue o ciclo de release do Chromium.
Cada navegador tem uma faixa [minimaAceitavel, recomendada]:
versao >= recomendada→ suporte completo (nível 2,suportado= true,suportadoCompleto= true). Nenhum aviso é exibido.minimaAceitavel <= versao < recomendada→ desatualizado (nível 1). Mensagem amigável de atualização é exibida.versao < minimaAceitavel→ não suportado (nível 0). Mensagem indicando incompatibilidade é exibida.- Navegador não reconhecido ou sem entrada na tabela → não suportado (nível 0).
- Nunca usa
innerHTML— todo texto é inserido viacreateTextNode, imune a XSS via atributos textuais. - Todos os links de atualização usam
target="_blank"comrel="noopener noreferrer", mitigando tabnabbing reverso mesmo em IE11 e WebViews antigos. - URLs de atualização são
https://explícitos — não herdam HTTP quando a página estiver em HTTP. - A função pode ser chamada várias vezes com segurança: ela limpa os filhos do elemento antes de reescrever (idempotente).
- Falhas de DOM, console ou evento são isoladas em
try/catche nunca afetam o retorno.
Código em ES5 estrito, sem dependências. Testado contra user agents reais de:
- Chrome, Firefox, Safari, Opera, Edge Chromium
- Chrome iOS, Firefox iOS, Edge iOS
- Samsung Internet, Android WebView
- Internet Explorer 11
- User agents desconhecidos (crawlers, apps customizados)
Este projeto usa apenas Node e Terser — sem framework de testes, sem bundler, sem transpilação. O fonte é ES5 e pode ser executado diretamente.
npm installIsso instala apenas o Terser (dev dependency) para minificação.
npm test # Roda a suíte contra o fonte
npm run test:min # Roda a suíte contra o minificado
npm run build # Gera checarNavegadorCliente.min.js via Tersernpm run prepublishOnly encadeia build + test + test:min automaticamente antes
de qualquer publicação no npm, garantindo que a versão minificada sempre passa
pelos mesmos testes do fonte.
checarNavegadorCliente.js — Fonte UMD (~25 KB, com JSDoc)
checarNavegadorCliente.min.js — Minificado via Terser (~9 KB)
tests/suite.js — Suíte de testes (zero dependências)
demo.html — Página de teste visual manual
README.md CHANGELOG.md LICENSE — Documentação
.github/workflows/ci.yml — CI: testa em Node 14/18/20/22
package.json — Publicação npm
Código da v1 continua funcionando. Se você usa as chaves s, j, f, m do
retorno, elas permanecem exatamente como antes.
Ajustes recomendados para aproveitar a v3:
// Antes (v1):
var r = checarNavegador();
if (r.s === 0) bloquear();
// Depois (v3) — mais legível, mesmo efeito:
var r = checarNavegadorCliente();
if (r.naoSuportado) bloquear();Se você customizava o script editando a tabela versoes dentro do arquivo, agora
passe pela config:
// Antes (v1): precisava editar o .js
// Depois (v3):
checarNavegadorCliente.auto = false;
window.addEventListener('load', function () {
checarNavegadorCliente({ versoes: { c: [120, 130] } });
});A chamada global antiga era checarNavegador (não exportada). Agora é
checarNavegadorCliente (exportada em window). Se algum código fazia
window.checarNavegador, atualize para window.checarNavegadorCliente.
Issues e pull requests são bem-vindos. Ao contribuir:
- Mantenha a compatibilidade ES5 / IE11. Sem
const,let,=>,async, template literals, spread,Object.assignetc. - Use
Array.isArray(nãoinstanceof Array) para robustez em cross-realm. - Todo efeito colateral (DOM, evento, console) deve estar isolado em
try/catch. - Novos navegadores/variantes devem ser cobertos em
detectar()na ordem correta de especificidade e refletidos emVERSOES_PADRAO,URLS_PADRAOeNOMES_LEGIVEIS. - Se adicionar campos ao retorno, mantenha os existentes — eles são API pública estável.
MIT. Veja LICENSE para o texto completo.