// Engineering Log
HTTP, HTTPS y TLS: Parte 8 — ¿Qué son JA3 y JA4? Huellas del cliente TLS
Publicado el 12.10.2026
// Ruta rapida
Este articulo pertenece al tema Seguridad y proteccion.
JA3 y JA4: maneras de obtener una huella corta (fingerprint) de un cliente TLS a partir de su primer mensaje ClientHello. Diferentes programas — Chrome, Firefox, curl, la biblioteca Python requests, el cliente Go, un programa malicioso — forman el ClientHello de manera distinta: ofrecen distintos conjuntos de cifrados, extensiones, grupos de intercambio de claves en distinto orden. De esos campos se compone una cadena, la cadena se hashifica y se obtiene un identificador idéntico para todas las copias de un mismo programa y distinto para distintos programas. La huella se calcula antes de descifrar el tráfico y sin la participación del cliente, por eso se usa para protección contra bots, búsqueda de malware en la red y en sistemas DPI.
La principal diferencia con el encabezado User-Agent: User-Agent lo escribe el propio cliente, y un script puede hacerse pasar fácilmente por el navegador Chrome. La huella TLS la determina la biblioteca que establece la conexión, y si un script en Python se presenta como Chrome pero su ClientHello proviene de OpenSSL, esa discrepancia se ve de inmediato.
Qué entra en el ClientHello
ClientHello se envía en texto claro (si no se usa ECH) y contiene:
- la versión del protocolo y la lista de versiones soportadas;
- la lista de conjuntos de cifrado en orden de preferencia;
- la lista de extensiones: SNI, ALPN,
supported_groups,signature_algorithms,key_share,session_tickety una decena más; - los grupos de intercambio de claves (curvas elípticas):
x25519,secp256r1,X25519MLKEM768; - los algoritmos de firma;
- los protocolos ALPN:
h2,http/1.1.
Todo esto lo fija la biblioteca TLS (BoringSSL en Chrome, NSS en Firefox, OpenSSL en curl y Python, crypto/tls en Go) y sus ajustes en la aplicación.
JA3
JA3 fue propuesto en 2017 por investigadores de Salesforce (John Althouse, Jeff Atkinson, Josh Atkins — por las iniciales). La cadena JA3 consta de cinco campos del ClientHello, escritos como números decimales separados por comas, y los valores dentro de cada campo separados por guiones:
Versión,Cifrados,Extensiones,Grupos,Formatos_de_puntos
771,4865-4866-4867-49195-49199-...,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-21,29-23-24,0La huella es el MD5 de esa cadena: 32 caracteres hexadecimales, por ejemplo 375c6162a492dfbf2795909110ce8424. Los valores GREASE (especiales “rellenos” que los navegadores insertan para que los servidores no rompan al ver valores desconocidos) se descartan al calcularla.
Para la respuesta del servidor existe JA3S — a partir de los campos del ServerHello. El par JA3 + JA3S destaca bien programas maliciosos concretos y sus servidores de control: un mismo programa que se conecta al mismo software servidor siempre da el mismo par.
Por qué JA3 dejó de funcionar para navegadores. En JA3 las extensiones aparecen en el orden en que las envía el cliente. Desde Chrome 110 (febrero de 2023) el navegador mezcla el orden de las extensiones en cada nueva conexión — se hizo para que los servidores no dependan de un orden fijo y no obstaculicen la evolución de TLS. Como resultado, un mismo Chrome da un JA3 nuevo casi en cada conexión, y las bases de huellas de navegadores perdieron sentido. Además, MD5 de toda la cadena no permite entender en qué se parecen dos huellas: el cambio de un solo cifrado da un hash completamente diferente.
JA4
JA4 fue propuesto en 2023 por John Althouse, ya en la compañía FoxIO. La huella es legible por humanos, resistente al reordenamiento de extensiones y tiene en cuenta QUIC.
Ejemplo para Chrome:
t13d1516h2_8daaf6152771_e5627efa2ab1Tres partes separadas por guiones bajos.
Parte a — descripción, legible sin descifrado:
| Símbolos | Significado | Ejemplo |
|---|---|---|
| 1 | transporte: t — TLS sobre TCP, q — QUIC, d — DTLS | t |
| 2–3 | versión TLS: la máxima de supported_versions | 13 — TLS 1.3 |
| 4 | d — hay SNI (conexión por nombre), i — no hay SNI (por IP) | d |
| 5–6 | número de cifrados sin GREASE | 15 |
| 7–8 | número de extensiones sin GREASE | 16 |
| 9–10 | primera y última letra del primer protocolo ALPN, 00 — no hay ALPN | h2 |
Parte b — los primeros 12 caracteres SHA-256 de la lista de cifrados, ordenada por valor. No importa el orden en que el cliente los envió.
Parte c — los primeros 12 caracteres SHA-256 de la lista ordenada de extensiones (sin SNI ni ALPN — ya están contadas en la parte a) y de la lista de algoritmos de firma en el orden original.
La ordenación soluciona el problema de Chrome: el reordenamiento de extensiones no cambia la huella. Y las partes separadas permiten buscar coincidencias parciales: por ejemplo, todos los clientes con el mismo conjunto de cifrados (misma parte b) pero con extensiones diferentes.
Para depuración hay variantes “crudas”: JA4_r — mismas listas sin hasheo, JA4_o — en el orden original, sin ordenar.
Familia JA4+. Además de JA4 para clientes TLS, FoxIO describió:
JA4S— respuesta del servidor (ServerHello);JA4H— cliente HTTP: método, versión, presencia de cookie y Referer, número de cabeceras, su orden, idioma;JA4X— manera en que se generó el certificado X.509;JA4L— latencia y distancia al cliente;JA4T,JA4TS— parámetros TCP (tamaño de ventana, opciones);JA4SSH— sesiones SSH.
Licencia. El propio JA4 se distribuye bajo la licencia BSD 3-Clause, igual que JA3. Los demás métodos JA4+ están bajo la FoxIO License 1.1: pueden usarse gratuitamente para proteger a la propia compañía y en investigaciones, pero un fabricante que venda un producto que incluya estas huellas necesita una licencia comercial.
Dónde se usan las huellas
Protección contra bots. Cloudflare, Akamai, AWS WAF y otros sistemas de protección comparan la huella con el User-Agent declarado y con una base de clientes conocidos. Un script en Python con User-Agent de navegador recibe captcha o 403. Cloudflare permite usar los campos cf.bot_management.ja3_hash y cf.bot_management.ja4 en reglas WAF en los planes con Bot Management.
Huella HTTP/2. Además de TLS, se distinguen clientes por parámetros de HTTP/2: los valores en el frame SETTINGS, el tamaño de ventana, prioridades y el orden de los pseudocabeceras. Esa huella se llama “huella Akamai” por la compañía que publicó el método.
Detección de malware. Sistemas de detección de intrusiones (Suricata, Zeek) calculan JA3/JA4 para cada conexión, y el analista busca huellas de programas y herramientas conocidas como Cobalt Strike, sin descifrar el tráfico.
DPI y bloqueos. El equipo de filtrado por huella de ClientHello distingue navegador de cliente VPN o proxy, que usan TLS para camuflarse. Por eso las modernas herramientas de evasión de bloqueos (Xray con el protocolo REALITY, sing-box) no forman el ClientHello por sí mismas, sino que copian la huella de un navegador mediante la biblioteca uTLS.
Inventario. En una red corporativa se ve por las huellas qué programas acceden a Internet: bibliotecas TLS obsoletas, clientes inesperados, scripts hechos a medida.
Suplantación de la huella
La huella la determina la biblioteca TLS, por eso sólo puede suplantarse usando otra biblioteca o sus ajustes:
- uTLS — biblioteca para Go que forma el ClientHello byte a byte como el de un navegador elegido;
- curl-impersonate — compilación de curl con BoringSSL y ajustes que replican Chrome, y con NSS — que replican Firefox, incluyendo la huella HTTP/2 y el orden de cabeceras;
- curl_cffi — wrapper sobre curl-impersonate para Python.
Cambiar el User-Agent, las cabeceras o el proxy no cambia la huella. Y a la inversa: una coincidencia total con el navegador a nivel TLS pero discrepancias en HTTP/2, el orden de cabeceras o el comportamiento de JavaScript también se detectan. Las huellas son uno de los indicios, no un veredicto definitivo: detrás de un JA4 hay millones de navegadores idénticos, y no se puede distinguir a un usuario concreto por ello.
Cómo averiguar tu huella
Mediante un servicio. Abra en el navegador o solicite con curl https://tls.peet.ws/api/all — el servicio devolverá JSON con las huellas de su cliente: tls.ja3, tls.ja3_hash, tls.ja4, tls.ja4_r y la huella HTTP/2 http2.akamai_fingerprint_hash.
curl -s https://tls.peet.ws/api/all | python3 -c \
'import json,sys; d=json.load(sys.stdin); print(d["tls"]["ja3_hash"], d["tls"]["ja4"], d["http_version"])'Resultados con distintos clientes. Medición en septiembre de 2026, tres solicitudes por cliente:
| Cliente | JA3 | JA4 | Protocolo |
|---|---|---|---|
| curl 8.7.1, macOS (LibreSSL) | 375c6162… | t13d497h2_0d8feac7bc37_7395dae3b2f3 | h2 |
| curl 8.22, Alpine (OpenSSL 3.5) | 446fb8bd… | t13d3012h2_1d37bd780c83_882d495ac381 | h2 |
| Python urllib, macOS (OpenSSL 3) | 4bdac5ab… | t13d1713h1_ab0a1bf427ad_89ab6efea773 | HTTP/1.1 |
| Python requests, Debian (OpenSSL 3) | 86dab210… | t13d1713h1_ab0a1bf427ad_8537cf56674e | HTTP/1.1 |
Node.js 26, fetch | 98384658… | t13d5212h1_b262b3658495_8e6e362c5eac | h2 |
Go 1.27, net/http | 03117a8e… | t13d1312h2_f57a46bbacb6_f50d94e863eb | h2 |
| curl-impersonate, perfil Chrome 116 | cambia: 0ea31aef…, 97ca64e9… | t13d1516h2_8daaf6152771_e5627efa2ab1 | h2 |
Qué se observa en la tabla:
- cada cliente tiene su propia huella, y el User-Agent no la afecta. Un script en Python que se llame Chrome seguirá mostrando
t13d1713h1_…; - la parte a se lee sin necesidad de referencia: Python ofrece 17 cifrados y 13 extensiones y pone primero en ALPN
http/1.1(h1), Go — 13 cifrados y 12 extensiones yh2; curl en macOS con LibreSSL ofrece 49 cifrados, incluidos obsoletos; - misma parte b para Python urllib y requests (
ab0a1bf427ad) — el mismo conjunto de cifrados de OpenSSL; la diferencia en la parte c — extensiones y algoritmos de firma distintos en distintas compilaciones; - JA3 del perfil Chrome cambia en cada solicitud, mientras que JA4 permanece como
t13d1516h2_8daaf6152771_e5627efa2ab1, que es el ejemplo de huella de Chrome en la especificación JA4. Así se ve el reordenamiento de extensiones; - el servicio no lo calcula perfectamente: en curl en macOS en la parte a aparece
497en lugar de4907— el número de extensiones no se rellenó con cero hasta dos dígitos. Al comparar huellas de distintas fuentes, verifique que las calculen de la misma forma.
Abra la misma página en su navegador varias veces seguidas: JA3 cambiará, JA4 no.
En Wireshark. A partir de la versión 4.2, Wireshark calcula las huellas por sí mismo. En el ClientHello analizado hay campos tls.handshake.ja3, tls.handshake.ja3_full y tls.handshake.ja4; puede añadirlos como columna y filtrar:
tls.handshake.ja4 == "t13d1516h2_8daaf6152771_e5627efa2ab1"Desde la línea de comandos:
tshark -r capture.pcap -Y 'tls.handshake.type == 1' \
-T fields -e ip.src -e tls.handshake.extensions_server_name -e tls.handshake.ja4En su propio servidor. Nginx no calcula huellas; para eso hay módulos externos y proxies separados (por ejemplo, fingerproxy — proxy inverso en Go que pasa JA3, JA4 y la huella HTTP/2 a la aplicación en cabeceras). En sitios detrás de Cloudflare las huellas están disponibles en las reglas WAF y en los logs en los planes con Bot Management.
Cuándo usar y cuándo no
Las huellas son útiles:
- en reglas WAF contra solicitudes automatizadas, cuando el User-Agent declara ser navegador pero la huella indica biblioteca;
- en investigaciones de incidentes: buscar todas las conexiones de una misma herramienta en la red;
- para permitir acceso a una API solo a determinados clientes dentro de la compañía (como indicador adicional, no único).
No conviene basarse en ellas:
- como autenticación — la huella puede falsificarse;
- para bloquear mediante una “lista negra” de huellas sin verificación: una biblioteca popular tiene un JA4 con millones de clientes legítimos, y junto con el bot bloqueará, por ejemplo, a todos los usuarios de la app móvil que use esa biblioteca;
- para rastrear a un usuario concreto — la huella describe el programa, no a la persona.
Errores típicos
- Reglas basadas en JA3 para navegadores después de 2023 — la huella de Chrome y Firefox cambia en cada conexión.
- Las huellas se calculan en el servidor detrás de una CDN o balanceador que termina TLS — verá la huella del balanceador y no la del cliente.
- Bloquear por huella tras actualizar la biblioteca cliente de sus propios usuarios — nuevas versiones de OpenSSL y navegadores cambian el conjunto de extensiones (por ejemplo, con la aparición de
X25519MLKEM768).
// Tarea parecida
Si estas resolviendo algo parecido
Este articulo pertenece a uno de los temas principales de trabajo. Puedes seguir leyendo sobre el tema, ir a la pagina principal para entender a que me dedico o abrir directamente los servicios.
Tema del articulo
Seguridad y proteccion
SSL, hardening, accesos, proteccion de servicios y configuraciones seguras.
Tareas frecuentes de esta tema
- Configurar SSL, certificados y conexiones seguras
- Restringir accesos y cerrar puntos de entrada innecesarios
- Reforzar la configuracion del servidor y los servicios
// Siguiente paso
Si necesitas ayuda con este tema y no solo otro articulo, es mejor ir directo a la pagina del servicio. La pagina principal y la seleccion de materiales quedan como rutas secundarias.
Abrir servicios// Contact
¿Necesitas ayuda?
Escríbeme y te ayudaré a resolver el problema
Respondo en un día laborable (03:00-13:00 GMT)
Или оставьте заявку здесь:
// Related