{"id":19738271,"url":"https://github.com/httptoolkit/read-tls-client-hello","last_synced_at":"2025-04-04T23:07:27.126Z","repository":{"id":61517878,"uuid":"550868085","full_name":"httptoolkit/read-tls-client-hello","owner":"httptoolkit","description":"A pure-JS module to read TLS client hello data and calculate TLS fingerprints from an incoming socket connection.","archived":false,"fork":false,"pushed_at":"2025-02-19T18:52:30.000Z","size":40,"stargazers_count":43,"open_issues_count":0,"forks_count":7,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-28T22:11:47.058Z","etag":null,"topics":["client-hello","networking","nodejs","tls","tls-fingerprint"],"latest_commit_sha":null,"homepage":"https://httptoolkit.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/httptoolkit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-13T13:08:28.000Z","updated_at":"2025-03-14T12:10:29.000Z","dependencies_parsed_at":"2025-02-27T22:07:11.747Z","dependency_job_id":"b31bc7b0-49fc-4080-bd36-3a18d2ffa625","html_url":"https://github.com/httptoolkit/read-tls-client-hello","commit_stats":{"total_commits":25,"total_committers":2,"mean_commits":12.5,"dds":"0.040000000000000036","last_synced_commit":"71262c118106a89e248baefe49c73cf79838a838"},"previous_names":["httptoolkit/read-tls-fingerprint"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/httptoolkit%2Fread-tls-client-hello","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/httptoolkit%2Fread-tls-client-hello/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/httptoolkit%2Fread-tls-client-hello/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/httptoolkit%2Fread-tls-client-hello/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/httptoolkit","download_url":"https://codeload.github.com/httptoolkit/read-tls-client-hello/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247261600,"owners_count":20910108,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["client-hello","networking","nodejs","tls","tls-fingerprint"],"created_at":"2024-11-12T01:13:44.637Z","updated_at":"2025-04-04T23:07:27.108Z","avatar_url":"https://github.com/httptoolkit.png","language":"TypeScript","readme":"# Read-TLS-Client-Hello [![Build Status](https://github.com/httptoolkit/read-tls-client-hello/workflows/CI/badge.svg)](https://github.com/httptoolkit/read-tls-client-hello/actions) [![Available on NPM](https://img.shields.io/npm/v/read-tls-client-hello.svg)](https://npmjs.com/package/read-tls-client-hello)\n\n\u003e _Part of [HTTP Toolkit](https://httptoolkit.tech): powerful tools for building, testing \u0026 debugging HTTP(S)_\n\nA pure-JS module to read TLS client hello data and calculate TLS fingerprints from an incoming socket connection. Tiny, with zero runtime dependencies.\n\nUsing this, you can analyze incoming TLS connections before you start a full handshake, and using their fingerprints you can recognize certain TLS clients - e.g. specific browser, cURL, or even the specific versions of a specific programming language a client is using - regardless of the content of the request they send.\n\nSee https://httptoolkit.com/blog/tls-fingerprinting-node-js/#how-does-tls-fingerprinting-work for more background on how TLS fingerprinting works.\n\nBe aware that fingerprinting is _not_ a 100% reliable test. Most clients can modify their TLS fingerprint with a bit of work (though few do). In many cases, it's even possible to mimic another arbitrary fingerprint on demand (e.g. using libraries like [CycleTLS](https://www.npmjs.com/package/cycletls)). Most of the time though, for clients that aren't actively messing with you, the fingerprint will tell you what kind of client is making the connection.\n\n## Docs\n\n### TLS server helper\n\nThe easiest way to use this is to use the built-in `trackClientHellos` helper, which can be applied to any `tls.TLSServer` instance, including `https.Server` instances, like so:\n\n```javascript\nconst https = require('https');\nconst { trackClientHellos } = require('read-tls-client-hello');\n\nconst server = new https.Server({ /* your TLS options etc */ });\n\ntrackClientHellos(server); // \u003c-- Automatically track everything on this server\n\nserver.on('request', (request, response) =\u003e {\n    // In your normal request handler, check `tlsClientHello` on the request's socket:\n    console.log('Received request with TLS client hello:', request.socket.tlsClientHello);\n});\n```\n\nA `tlsClientHello` property will be attached to all sockets, containing the parsed data returned by `readTlsClientHello` (see below), a `ja3` property with the JA3 TLS fingerprint for the client hello, e.g. `cd08e31494f9531f560d64c695473da9` and a `ja4` property with the JA4 TLS fingerprint for the client hello, e.g. `t13d591000_a33745022dd6_1f22a2ca17c4`.\n\n### Reading a TLS client hello\n\nTo read all available data from a TLS client hello manually, pass a stream (e.g. a `net.Socket`) to the exported `readTlsClientHello(stream)`, before the TLS handshake (or any other processing) starts. This returns a promise containing all data parsed from the client hello.\n\nThis method reads the initial data from the socket, parses it, and then unshifts it back into the socket, so that once the returned promise resolves the stream can be used like new, to start a normal TLS session using the same client hello.\n\nIf parsing fails, this method will throw an error, but will still ensure all data is returned to the socket first, so that non-TLS streams can also be processed as normal.\n\nThe returned promise resolves to an object, containing:\n\n* `serverName` - The server name requested in the client hello (or undefined if SNI was not used)\n* `alpnProtocols` - A array of ALPN protcol names requested in the client hello (or undefined if ALPN was not used)\n* `fingerprintData` - An array containing the raw components used for JA3 TLS fingerprinting:\n    1. The TLS version number as a Uint16 (771 for TLS 1.2+)\n    2. An array of cipher ids (excluding GREASE)\n    3. An array of extension ids (excluding GREASE)\n    4. An array of supported group ids (excluding GREASE)\n    5. An array of supported elliptic curve ids\n    6. An array of signature algorithms (TLS 1.3)\n\n### TLS fingerprinting\n\nTo calculate TLS fingerprints manually, there are a few options exported from this module:\n\n* `getTlsFingerprintAsJa3` - Reads from a stream, just like `readTlsClientHello` above, but returns a promise for the JA3 hash string, e.g. `cd08e31494f9531f560d64c695473da9`, instead of the raw hello components.\n* `getTlsFingerprintAsJa4` - Reads from a stream, just like `readTlsClientHello` above, but returns a promise for the JA4 hash string, e.g. `t13d591000_a33745022dd6_1f22a2ca17c4`, instead of the raw hello components.\n* `readTlsClientHello(stream)` - Reads the entire hello (see above). In the returned object, you can read the raw data components used for JA3 fingerprinting from the `fingerprintData` property.\n* `calculateJa3FromFingerprintData(data)` - Takes raw TLS fingerprint data, and returns the corresponding JA3 hash.\n* `calculateJa4FromHelloData(data)` - Takes the full hello data, including the serverName, alpnProtocols \u0026 fingerprinting parameters returned by `readTlsClientHello`, and returns the corresponding JA4 hash, eg. `t13d591000_a33745022dd6_1f22a2ca17c4`.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhttptoolkit%2Fread-tls-client-hello","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhttptoolkit%2Fread-tls-client-hello","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhttptoolkit%2Fread-tls-client-hello/lists"}