Above the TLS line is JavaScript's to rewrite. Below it, the ClientHello your OS TLS library puts on the wire, JavaScript never touches. It hashes into JA3 / JA4 and the HTTP/2 SETTINGS fingerprint. Pick a client and watch what the wire says versus what the User-Agent claims.
client
spoofed page JS · navigator.userAgent
▲ JS rewrites this  ·  JS cannot reach ▼
TLS stack · emits the ClientHello
ClientHello ▶
detector
reads the wire
hashes the bytes
cross-checks the UA
ClientHello · assembled by the TLS library, sent before encryption, not written by JavaScript
version
cipher suites
extensions
named groups
ALPN
JA3 · MD5 of ClientHello fields
JA4 · sorted, survives randomization
HTTP/2 SETTINGS · a separate fingerprint (Akamai)
UA claims Chrome vs wire says Chrome
Cipher and extension IDs are illustrative; the structure they show (GREASE, extension order, ALPN, HTTP/2) is real. The Chrome JA3/JA4 strings are the worked example from the docs.