feat(emulate): Add Chrome 150, 151, 152 - #107
Conversation
Added Chrome 150/151/152 to Emulation profiles and included them in the weighted version selector, newest first. The `sec-ch-ua` brand list is version-seeded, so the GREASE token and the brand ordering differ per version and cannot be extrapolated from 149. Each string was derived from Chromium's `GenerateBrandVersionList` and then confirmed against real browser binaries over HTTP/2: 150 "Not;A=Brand";v="8", "Chromium";v="150", "Google Chrome";v="150" 151 "Not=A?Brand";v="99", "Google Chrome";v="151", "Chromium";v="151" 152 "Chromium";v="152", "Not?A_Brand";v="24", "Google Chrome";v="152" Captures came from Chrome for Testing 150.0.7828.0 / 151.0.7872.0 / 152.0.7923.0; the same capture path reproduces the existing v149 string byte for byte against Chrome 149.0.7827.155, which validates the method. Chrome for Testing is Chromium-branded, so its output omits the `Google Chrome` entry while the GREASE and Chromium entries match exactly. HTTP/2 is unchanged across these versions (Akamai hash 52d84b11737d980aef856699f885ca86), so the profiles reuse `v132::build_emulation`. TLS is not fully reproducible with wreq 6.0's public options and this is documented in a source comment rather than silently approximated: 149 t13d1516h2_8daaf6152771_d8a2da3f94cd 150 t13d1517h2_8daaf6152771_cb7bf5808d99 151 t13d1518h2_8daaf6152771_4980c97edce0 152 same normalized JA4 as 151 Chrome 150 added the ML-DSA signature schemes 0x0904/0x0905/0x0906 and the trust-anchor extension 0xca34; Chrome 151 added extension 0x12e0. Header emulation is exact; the TLS delta remains a known limitation. Adds hermetic header tests for Chrome152 on Windows and macOS.
Chrome 150 moved `accept-language` from just after `accept-encoding` to just after the `sec-ch-ua` block. Measured over HTTP/2 against real binaries (Chrome 149.0.7827.155, Chrome for Testing 150.0.7828.0 / 151.0.7872.0 / 152.0.7923.0): 149 sec-ch-ua … upgrade-insecure-requests … accept-encoding accept-language priority 150+ sec-ch-ua … accept-language upgrade-insecure-requests … accept-encoding priority The v150/v151/v152 blocks added in this branch reused `header_initializer_with_zstd_priority`, which emits the 149 order, so they were byte-wrong on a header the profiles exist to reproduce. Adds `header_initializer_with_zstd_priority_v150` and a `zstd_only` arm of `header_chrome_accept_encoding` (the existing arm bundles the language header, which 150+ no longer emits there). Profiles up to 149 keep the existing initializer and are untouched. Verified on the wire through the napi binding, one hermetic HTTP/2 server per profile: chrome_150/151/152 emit accept-language at 4/13 and chrome_149/148/142 stay at 12/13, each matching its real binary exactly.
|
Pushed a follow-up commit ( What was wrongChrome 150 moved Measured over HTTP/2 against real binaries: Position 12/13 → 4/13. Locale-invariant: probing with no locale flags, with The fixAdds Profiles up to 149 are untouched and keep the existing initializer. That VerificationBuilt through the napi binding and captured on the wire, one hermetic HTTP/2
Full header sequence compared element-wise, not just the one position.
|
Builds on 0x676e67#107. The 150-152 profiles reused v132's transport, so their ClientHello was a 149-era fingerprint (JA4 t13d1516h2) under a Chrome/152 UA; real Chrome 152 is t13d1517h2. Adds a preset with the ML-DSA signature algorithms (0x0904/05/06) ahead of the classical eight and the trust_anchors extension (0xca34). JA4 matches a real Chrome 152 capture: t13d1517h2_8daaf6152771_cb7bf5808d99. trust_anchors is sent empty by default. The emulation-chromium-pki feature fills it with Chrome's anchor IDs from chromium-root-certs and adds chromium_root_store() so the client verifies against Chrome's roots. Requires wreq #1220 (TlsOptions::requested_trust_anchors).
Adds Chrome 150, 151 and 152 to the emulation profiles and to the weighted
version selector (newest first), following the shape of #99.
sec-ch-ua brand strings
The GREASE token and the brand ordering are version-seeded, so they cannot be
extrapolated from 149. Each value was derived from Chromium's
GenerateBrandVersionListand then confirmed against a real binary:sec-ch-ua"Google Chrome";v="149", "Chromium";v="149", "Not)A;Brand";v="24""Not;A=Brand";v="8", "Chromium";v="150", "Google Chrome";v="150""Not=A?Brand";v="99", "Google Chrome";v="151", "Chromium";v="151""Chromium";v="152", "Not?A_Brand";v="24", "Google Chrome";v="152"Verification method: each browser was driven headless into a local HTTP/2
server and
sec-ch-uawas read off the request. Captures came fromChrome for Testing
150.0.7828.0,151.0.7872.0and152.0.7923.0.The same capture path reproduces the existing v149 string byte for byte
against installed Chrome
149.0.7827.155, which is what validates the methodrather than the derivation alone. Chrome for Testing is Chromium-branded, so
its output omits the
Google Chromeentry while the GREASE and Chromiumentries match exactly.
HTTP/2
Unchanged across 149 to 152 (Akamai hash
52d84b11737d980aef856699f885ca86),so the new profiles reuse
v132::build_emulationlike v148/v149.TLS: known limitation, documented in the source
TLS does change across these versions and
wreq6.0's public options cannotexpress the delta, so this PR does not claim TLS parity:
Chrome 150 added the ML-DSA signature schemes
0x0904/0x0905/0x0906andthe trust-anchor extension
0xca34(BoringSSL,
trust anchors);
Chrome 151 added extension
0x12e0.Header emulation is exact; the TLS delta is called out in a source comment so
consumers know which layer moved.
Tests
Adds hermetic header assertions for
Chrome152on Windows and macOS intests/client.rs, using the existing local-server helper.cargo clippy --all-targets --all-features— cleancargo build --all-features— cleanNote on the existing suite:
cargo test --all-featuresshows 34 failures intests/emulate_chrome.rs. These are pre-existing on this branch's base —verified by stashing the change and re-running, which produces the identical
34 — and appear to require outbound network access.
Not included
No changes to other browser families, no dependency or feature changes, and no
reformatting of untouched code.