3939
4040USER_AGENT = (
4141 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
42- "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
42+ "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36"
43+ )
44+ SEC_CH_UA = '"Not;A=Brand";v="8", "Chromium";v="150", "Google Chrome";v="150"'
45+ SEC_CH_UA_FULL_VERSION_LIST = (
46+ '"Not;A=Brand";v="8.0.0.0", "Chromium";v="150.0.7871.13", "Google Chrome";v="150.0.7871.13"'
4347)
44- SEC_CH_UA = '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"'
4548
4649# 正则:从 anchor HTML 提取 base token
4750_TOKEN_RE = re .compile (r'id="recaptcha-token"[^>]*value="([^"]+)"' )
@@ -72,14 +75,22 @@ def _anchor_headers() -> Dict[str, str]:
7275 "sec-ch-ua" : SEC_CH_UA ,
7376 "sec-ch-ua-mobile" : "?0" ,
7477 "sec-ch-ua-platform" : '"Windows"' ,
78+ "sec-ch-ua-arch" : '"x86"' ,
79+ "sec-ch-ua-bitness" : '"64"' ,
80+ "sec-ch-ua-full-version" : '"150.0.7871.13"' ,
81+ "sec-ch-ua-full-version-list" : SEC_CH_UA_FULL_VERSION_LIST ,
82+ "sec-ch-ua-platform-version" : '"19.0.0"' ,
83+ "sec-ch-ua-model" : '""' ,
84+ "sec-ch-ua-wow64" : "?0" ,
85+ "sec-ch-ua-form-factors" : '"Desktop"' ,
7586 "upgrade-insecure-requests" : "1" ,
7687 "user-agent" : USER_AGENT ,
7788 "accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8" ,
7889 "sec-fetch-site" : "cross-site" ,
7990 "sec-fetch-mode" : "navigate" ,
8091 "sec-fetch-dest" : "iframe" ,
8192 "accept-encoding" : "gzip, deflate, br" ,
82- "accept-language" : "en-US ,en;q=0.9 " ,
93+ "accept-language" : "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7 ,en-US ;q=0.6 " ,
8394 }
8495
8596
@@ -88,6 +99,14 @@ def _xhr_headers(content_type: str, accept: str, origin: str, referer: str, site
8899 "sec-ch-ua" : SEC_CH_UA ,
89100 "sec-ch-ua-mobile" : "?0" ,
90101 "sec-ch-ua-platform" : '"Windows"' ,
102+ "sec-ch-ua-arch" : '"x86"' ,
103+ "sec-ch-ua-bitness" : '"64"' ,
104+ "sec-ch-ua-full-version" : '"150.0.7871.13"' ,
105+ "sec-ch-ua-full-version-list" : SEC_CH_UA_FULL_VERSION_LIST ,
106+ "sec-ch-ua-platform-version" : '"19.0.0"' ,
107+ "sec-ch-ua-model" : '""' ,
108+ "sec-ch-ua-wow64" : "?0" ,
109+ "sec-ch-ua-form-factors" : '"Desktop"' ,
91110 "user-agent" : USER_AGENT ,
92111 "accept" : accept ,
93112 "origin" : origin ,
@@ -96,7 +115,7 @@ def _xhr_headers(content_type: str, accept: str, origin: str, referer: str, site
96115 "sec-fetch-dest" : "empty" ,
97116 "referer" : referer ,
98117 "accept-encoding" : "gzip, deflate, br" ,
99- "accept-language" : "en-US ,en;q=0.9 " ,
118+ "accept-language" : "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7 ,en-US ;q=0.6 " ,
100119 "priority" : "u=1, i" ,
101120 }
102121 if content_type :
@@ -105,13 +124,19 @@ def _xhr_headers(content_type: str, accept: str, origin: str, referer: str, site
105124
106125
107126def _batch_graphql_headers () -> Dict [str , str ]:
108- return _xhr_headers (
127+ h = _xhr_headers (
109128 "application/json" ,
110129 "*/*" ,
111130 "https://console.cloud.google.com" ,
112131 "https://console.cloud.google.com/" ,
113132 "cross-site" ,
114133 )
134+ h ["x-goog-authuser" ] = "0"
135+ h ["x-browser-channel" ] = "stable"
136+ h ["x-browser-copyright" ] = "Copyright 2026 Google LLC. All Rights Reserved."
137+ h ["x-browser-year" ] = "2026"
138+ h ["x-goog-ext-353267353-jspb" ] = "[null,null,null,194274]"
139+ return h
115140
116141
117142# ==================== reCAPTCHA ====================
@@ -122,6 +147,21 @@ async def _fetch_recaptcha_token_once() -> Optional[str]:
122147 import wreq
123148 from wreq .emulation import Emulation
124149
150+ _EMULATION_POOL = [
151+ Emulation .Chrome131 , Emulation .Chrome132 , Emulation .Chrome133 ,
152+ Emulation .Chrome134 , Emulation .Chrome135 , Emulation .Chrome136 ,
153+ Emulation .Chrome137 , Emulation .Chrome138 , Emulation .Chrome139 ,
154+ Emulation .Chrome140 , Emulation .Chrome141 , Emulation .Chrome142 ,
155+ Emulation .Chrome143 , Emulation .Chrome144 , Emulation .Chrome145 ,
156+ Emulation .Chrome146 , Emulation .Chrome147 ,
157+ Emulation .Edge131 , Emulation .Edge134 , Emulation .Edge135 ,
158+ Emulation .Edge136 , Emulation .Edge137 , Emulation .Edge138 ,
159+ Emulation .Edge139 , Emulation .Edge140 , Emulation .Edge141 ,
160+ Emulation .Edge142 , Emulation .Edge143 , Emulation .Edge144 ,
161+ Emulation .Edge145 , Emulation .Edge146 , Emulation .Edge147 ,
162+ ]
163+ emulation = random .choice (_EMULATION_POOL )
164+
125165 cb = _random_string (10 )
126166 anchor_url = (
127167 f"{ RECAPTCHA_BASE } /recaptcha/enterprise/anchor"
@@ -133,7 +173,7 @@ async def _fetch_recaptcha_token_once() -> Optional[str]:
133173 anchor_resp = await wreq .get (
134174 anchor_url ,
135175 headers = _anchor_headers (),
136- emulation = Emulation . Chrome131 ,
176+ emulation = emulation ,
137177 )
138178 if anchor_resp .status != 200 :
139179 log .warning (f"[VERTEX RECAPTCHA] anchor GET failed: status={ anchor_resp .status } " )
@@ -171,7 +211,7 @@ async def _fetch_recaptcha_token_once() -> Optional[str]:
171211 reload_url ,
172212 form = form_data ,
173213 headers = reload_headers ,
174- emulation = Emulation . Chrome131 ,
214+ emulation = emulation ,
175215 )
176216 if reload_resp .status != 200 :
177217 log .warning (f"[VERTEX RECAPTCHA] reload POST failed: status={ reload_resp .status } " )
0 commit comments