This commit is contained in:
kgod
2026-05-26 21:02:17 +08:00
commit 8697477a53
10000 changed files with 1541403 additions and 0 deletions
@@ -0,0 +1,130 @@
Metadata-Version: 2.4
Name: playwright-stealth
Version: 2.0.3
Summary: Make your playwright instance stealthy
License-Expression: MIT
License-File: LICENSE
Author: Mattwmaster58
Author-email: mattwmaster58@gmail.com>
Requires-Python: >=3.9
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Provides-Extra: black
Requires-Dist: black (>=25.9.0) ; extra == "black"
Requires-Dist: playwright (>=1.40.0)
Project-URL: Homepage, https://github.com/Mattwmaster58/playwright_stealth
Project-URL: changelog, https://github.com/Mattwmaster58/playwright_stealth/raw/main/CHANGELOG.md
Description-Content-Type: text/markdown
# playwright_stealth
Fork of AtuboDad's port
of [puppeteer-extra-plugin-stealth](https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth),
with some improvements. Don't expect this to bypass anything but the simplest of bot detection methods. Consider this a
proof-of-concept starting point.
I've merged some of the outstanding PRs, added some features, and cleaned up the API surface. See
the [changelog](https://github.com/Mattwmaster58/playwright_stealth/blob/main/CHANGELOG.md). The latest major version includes breaking changes.
## Install
Install from PyPi:
```
$ pip install playwright-stealth
```
## Example Usage
### Recommended Usage
```python
import asyncio
from playwright.async_api import async_playwright
from playwright_stealth import Stealth
async def main():
# This is the recommended usage. All pages created will have stealth applied:
async with Stealth().use_async(async_playwright()) as p:
browser = await p.chromium.launch()
page = await browser.new_page()
webdriver_status = await page.evaluate("navigator.webdriver")
print("from new_page: ", webdriver_status)
different_context = await browser.new_context()
page_from_different_context = await different_context.new_page()
different_context_status = await page_from_different_context.evaluate("navigator.webdriver")
print("from new_context: ", different_context_status)
asyncio.run(main())
```
### Specifying config options and applying evasions manually to an entire context
```python
import asyncio
from playwright.async_api import async_playwright
from playwright_stealth import Stealth, ALL_EVASIONS_DISABLED_KWARGS
async def advanced_example():
# Custom configuration with specific languages
custom_languages = ("fr-FR", "fr")
stealth = Stealth(
navigator_languages_override=custom_languages,
init_scripts_only=True
)
async with async_playwright() as p:
browser = await p.chromium.launch()
context = await browser.new_context()
await stealth.apply_stealth_async(context)
# Test stealth on multiple pages
page_1 = await context.new_page()
page_2 = await context.new_page()
# Verify language settings
for i, page in enumerate([page_1, page_2], 1):
is_mocked = await page.evaluate("navigator.languages") == custom_languages
print(f"Stealth applied to page {i}: {is_mocked}")
# Example of selective evasion usage
no_evasions = Stealth(**ALL_EVASIONS_DISABLED_KWARGS)
single_evasion = Stealth(**{**ALL_EVASIONS_DISABLED_KWARGS, "navigator_webdriver": True})
print("Total evasions (none):", len(no_evasions.script_payload))
print("Total evasions (single):", len(single_evasion.script_payload))
asyncio.run(advanced_example())
```
## Todo
- make this work with playwright.launch_persistent_context
- the difficult because sometimes we sniff the UA if an override isn't provided, and this is difficult to do when
launch_persistent_context is launched
- sec-platform (we have navigator_platform)
- docs
## A set of Test results
### playwright with stealth
![playwright without stealth](https://github.com/Mattwmaster58/playwright_stealth/blob/main/images/example_with_stealth.png)
### playwright without stealth
![playwright with stealth](https://github.com/Mattwmaster58/playwright_stealth/raw/main/images/example_without_stealth.png)
@@ -0,0 +1,34 @@
playwright_stealth-2.0.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
playwright_stealth-2.0.3.dist-info/METADATA,sha256=WZmVrN3XWS4nFdiAfzFszoZC6Y_aU5bG-pfv2__Cis4,4471
playwright_stealth-2.0.3.dist-info/RECORD,,
playwright_stealth-2.0.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
playwright_stealth-2.0.3.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
playwright_stealth-2.0.3.dist-info/licenses/LICENSE,sha256=-Co3J2q7uJltdBn6I-ts-xE4u7B-RsTkJpNL5fTd33A,1065
playwright_stealth/__init__.py,sha256=jaxbJ_g0R7NZ3uMHdFdw37SAZMl2iqwg7R8C4dkNIdY,101
playwright_stealth/__pycache__/__init__.cpython-312.pyc,,
playwright_stealth/__pycache__/case_insensitive_dict.cpython-312.pyc,,
playwright_stealth/__pycache__/context_managers.cpython-312.pyc,,
playwright_stealth/__pycache__/stealth.cpython-312.pyc,,
playwright_stealth/case_insensitive_dict.py,sha256=ENG40YICW7G5D68PTZ9yDfCKN4bngjHfCGJ5aTvXqUw,2509
playwright_stealth/context_managers.py,sha256=EoP0OcA33h-WEX0FKl9H3IpbMkx0EnBv1ZznDsSh3hE,1450
playwright_stealth/js/evasions/chrome.app.js,sha256=NsaSoBL5I49Gid3Pf1Ivd_AI-oNi4AuFbpS4HxDjoUQ,1681
playwright_stealth/js/evasions/chrome.csi.js,sha256=THKR5T4_12nE5PHgsdaKxL-J-i_dCTkMUBEOFKwIOLo,933
playwright_stealth/js/evasions/chrome.hairline.js,sha256=8gOqWlI7vkx5074tI5Jxct7fbZQN_ATwlgj-Xate4sg,442
playwright_stealth/js/evasions/chrome.load.times.js,sha256=OHbn30JUMfZEAk7gMYonDOCgLSw03Sch4KJs7ZT9OYc,3942
playwright_stealth/js/evasions/chrome.runtime.js,sha256=OkF0BAZL5d-i7v4yREL8OQKpSVoGvoeNNIBynQJ2elc,8140
playwright_stealth/js/evasions/error.prototype.js,sha256=FZBH5NQVWd0IKLTV4upfs1b0MNRk5h_m-KTGlDQ4XnI,125
playwright_stealth/js/evasions/iframe.contentWindow.js,sha256=HRsF9jXmsl7q8e8xUeize-tR8qIhu3R3OavfFOQS0z0,2981
playwright_stealth/js/evasions/media.codecs.js,sha256=O2u8KO_6Is_Q5XdQA0b5o4cctxOCl5EVxf-9EC-GDFE,1549
playwright_stealth/js/evasions/navigator.hardwareConcurrency.js,sha256=BCOOfIoMBLPmfC967pcrIyzMc-sx1EkCUQZEO_6Kz5o,160
playwright_stealth/js/evasions/navigator.languages.js,sha256=MH-LQJiDEfJJNvRkNw1Kmmp7WJxKwVw6r387l5xS99Y,399
playwright_stealth/js/evasions/navigator.permissions.js,sha256=LAfDV90rdIjUl4MqMbuI8eidhwR6qglWWhBb0sS9FW8,549
playwright_stealth/js/evasions/navigator.platform.js,sha256=fV65l0LvcRU_3owq1JtBO_TOjPxOCaVuYjOu8uJnx6Y,276
playwright_stealth/js/evasions/navigator.plugins.js,sha256=PbaQwklDzAG3KPNwMbUbEGLC-BpPC23qPb_PdeoqQYY,2441
playwright_stealth/js/evasions/navigator.userAgent.js,sha256=BebaAyncvY6qLSIb0r0XFoeCiczWYWX2WGhMCYf_-q8,301
playwright_stealth/js/evasions/navigator.userAgentData.js,sha256=DNQcnNnm4ZCqB5qhRE3VQxLkPmOmRBTGYESP9XTUZes,2616
playwright_stealth/js/evasions/navigator.vendor.js,sha256=fvPwgV7aPWKonQou4Szf2_4AFHTCv9iuVrIp9JbpUQY,161
playwright_stealth/js/evasions/navigator.webdriver.js,sha256=UgUz9QrO_F1jhduyZ254MwigjfoP6LgMx0TWPV1UybM,884
playwright_stealth/js/evasions/webgl.vendor.js,sha256=T9ZCsC4uBRCriLK7DoMrO_Rt1d3nvssT7FcemN0u8lQ,1126
playwright_stealth/js/generate.magic.arrays.js,sha256=m-dqRtzs_763d2XDBWqb-cn9Zb78MtX3GfQFsIt8zKQ,5262
playwright_stealth/js/utils.js,sha256=eZsxYpZZnyVl9lRlTfB6kQ3SkQy3XBZHjNs7IJ-o6I8,17331
playwright_stealth/stealth.py,sha256=vEH59pRiBEP5m26m7x9uzXk4WDqs8yyUy9ngyz-mVUo,27638
@@ -0,0 +1,4 @@
Wheel-Version: 1.0
Generator: poetry-core 2.3.0
Root-Is-Purelib: true
Tag: py3-none-any
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 ASAS1314
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.