Skip to content

Commit 8ab4c10

Browse files
committed
ft: guard against double application of stealth
1 parent b19e308 commit 8ab4c10

File tree

5 files changed

+184
-89
lines changed

5 files changed

+184
-89
lines changed

playwright_stealth/stealth.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ def enabled_scripts():
6565

6666
_USER_AGENT_OVERRIDE_PIGGYBACK_KEY = "_stealth_user_agent"
6767
_SEC_CH_UA_OVERRIDE_PIGGYBACK_KEY = "_stealth_sec_ch_ua"
68+
_STEALTH_APPLIED_KEY = "_playwright_stealth_applied"
6869

6970
def __init__(
7071
self,
@@ -206,6 +207,14 @@ def _evasion_scripts(self) -> str:
206207
if self.webgl_vendor:
207208
yield SCRIPTS["webgl_vendor"]
208209

210+
def warn_if_stealth_applied(self, obj: Any) -> bool:
211+
if hasattr(obj, self._STEALTH_APPLIED_KEY):
212+
warnings.warn(
213+
"Stealth has already been applied to this page or context. Skipping duplicate application.",
214+
)
215+
return True
216+
return False
217+
209218
def use_async(self, ctx: async_api.PlaywrightContextManager) -> AsyncWrappingContextManager:
210219
"""
211220
Instruments the playwright context manager.
@@ -229,12 +238,14 @@ def use_sync(self, ctx: sync_api.PlaywrightContextManager) -> SyncWrappingContex
229238
return SyncWrappingContextManager(self, ctx)
230239

231240
async def apply_stealth_async(self, page_or_context: Union[async_api.Page, async_api.BrowserContext]) -> None:
232-
if len(self.script_payload) > 0:
241+
if len(self.script_payload) > 0 and not self.warn_if_stealth_applied(page_or_context):
233242
await page_or_context.add_init_script(self.script_payload)
243+
setattr(page_or_context, self._STEALTH_APPLIED_KEY, True)
234244

235245
def apply_stealth_sync(self, page_or_context: Union[sync_api.Page, sync_api.BrowserContext]) -> None:
236-
if len(self.script_payload) > 0:
246+
if len(self.script_payload) > 0 and not self.warn_if_stealth_applied(page_or_context):
237247
page_or_context.add_init_script(self.script_payload)
248+
setattr(page_or_context, self._STEALTH_APPLIED_KEY, True)
238249

239250
def hook_playwright_context(self, ctx: Union[async_api.Playwright, sync_api.Playwright]) -> None:
240251
"""
@@ -293,14 +304,16 @@ def sync_hooked_method(*args, **kwargs) -> sync_api.Browser:
293304
def _generate_hooked_new_context(self, new_context_method: Callable, new_page_method: Callable) -> Callable:
294305
async def hooked_new_context_async(*args, **kwargs):
295306
context = await new_context_method(
296-
*args, **(await self._kwargs_new_page_context_with_patches_async(new_page_method, kwargs))
307+
*args,
308+
**(await self._kwargs_new_page_context_with_patches_async(new_page_method, kwargs)),
297309
)
298310
await self.apply_stealth_async(context)
299311
return context
300312

301313
def hooked_browser_method_sync(*args, **kwargs):
302314
context = new_context_method(
303-
*args, **(self._kwargs_new_page_context_with_patches_sync(new_page_method, kwargs))
315+
*args,
316+
**(self._kwargs_new_page_context_with_patches_sync(new_page_method, kwargs)),
304317
)
305318
self.apply_stealth_sync(context)
306319
return context
@@ -376,7 +389,11 @@ async def get_user_agent_and_sec_ch_ua_async() -> Tuple[str, str]:
376389
await temp_page.close(reason="playwright_stealth internal temp utility page")
377390
sec_ch_ua = self._get_greased_chrome_sec_ua_ch(stealth_user_agent)
378391
setattr(browser_instance, self._SEC_CH_UA_OVERRIDE_PIGGYBACK_KEY, sec_ch_ua)
379-
setattr(browser_instance, self._USER_AGENT_OVERRIDE_PIGGYBACK_KEY, stealth_user_agent)
392+
setattr(
393+
browser_instance,
394+
self._USER_AGENT_OVERRIDE_PIGGYBACK_KEY,
395+
stealth_user_agent,
396+
)
380397
return stealth_user_agent, sec_ch_ua
381398

382399
new_kwargs = deepcopy(packed_kwargs)
@@ -417,7 +434,11 @@ def get_user_agent_and_sec_ch_ua_sync() -> Tuple[str, str]:
417434
sec_ch_ua = self._get_greased_chrome_sec_ua_ch(stealth_user_agent)
418435
temp_page.close(reason="playwright_stealth internal temp utility page")
419436
setattr(browser_instance, self._SEC_CH_UA_OVERRIDE_PIGGYBACK_KEY, sec_ch_ua)
420-
setattr(browser_instance, self._USER_AGENT_OVERRIDE_PIGGYBACK_KEY, stealth_user_agent)
437+
setattr(
438+
browser_instance,
439+
self._USER_AGENT_OVERRIDE_PIGGYBACK_KEY,
440+
stealth_user_agent,
441+
)
421442
return stealth_user_agent, sec_ch_ua
422443

423444
new_kwargs = deepcopy(packed_kwargs)

0 commit comments

Comments
 (0)