@zorilla/puppeteer-extra-plugin-stealth 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +21 -0
- package/LICENSE +21 -0
- package/README.md +324 -0
- package/dist/evasions/README.md +13 -0
- package/dist/evasions/_template/README.md +18 -0
- package/dist/evasions/_template/index.d.ts +13 -0
- package/dist/evasions/_template/index.d.ts.map +1 -0
- package/dist/evasions/_template/index.js +26 -0
- package/dist/evasions/_template/index.js.map +1 -0
- package/dist/evasions/_template/package.json +5 -0
- package/dist/evasions/_utils/README.md +287 -0
- package/dist/evasions/_utils/index.d.ts +238 -0
- package/dist/evasions/_utils/index.d.ts.map +1 -0
- package/dist/evasions/_utils/index.js +588 -0
- package/dist/evasions/_utils/index.js.map +1 -0
- package/dist/evasions/_utils/withUtils.d.ts +12 -0
- package/dist/evasions/_utils/withUtils.d.ts.map +1 -0
- package/dist/evasions/_utils/withUtils.js +47 -0
- package/dist/evasions/_utils/withUtils.js.map +1 -0
- package/dist/evasions/chrome.app/README.md +16 -0
- package/dist/evasions/chrome.app/index.d.ts +11 -0
- package/dist/evasions/chrome.app/index.d.ts.map +1 -0
- package/dist/evasions/chrome.app/index.js +97 -0
- package/dist/evasions/chrome.app/index.js.map +1 -0
- package/dist/evasions/chrome.app/package.json +5 -0
- package/dist/evasions/chrome.csi/README.md +29 -0
- package/dist/evasions/chrome.csi/index.d.ts +25 -0
- package/dist/evasions/chrome.csi/index.d.ts.map +1 -0
- package/dist/evasions/chrome.csi/index.js +69 -0
- package/dist/evasions/chrome.csi/index.js.map +1 -0
- package/dist/evasions/chrome.csi/package.json +5 -0
- package/dist/evasions/chrome.loadTimes/README.md +27 -0
- package/dist/evasions/chrome.loadTimes/index.d.ts +23 -0
- package/dist/evasions/chrome.loadTimes/index.d.ts.map +1 -0
- package/dist/evasions/chrome.loadTimes/index.js +163 -0
- package/dist/evasions/chrome.loadTimes/index.js.map +1 -0
- package/dist/evasions/chrome.loadTimes/package.json +5 -0
- package/dist/evasions/chrome.runtime/README.md +32 -0
- package/dist/evasions/chrome.runtime/index.d.ts +14 -0
- package/dist/evasions/chrome.runtime/index.d.ts.map +1 -0
- package/dist/evasions/chrome.runtime/index.js +252 -0
- package/dist/evasions/chrome.runtime/index.js.map +1 -0
- package/dist/evasions/chrome.runtime/package.json +5 -0
- package/dist/evasions/chrome.runtime/staticData.json +41 -0
- package/dist/evasions/defaultArgs/README.md +17 -0
- package/dist/evasions/defaultArgs/index.d.ts +2 -0
- package/dist/evasions/defaultArgs/index.d.ts.map +1 -0
- package/dist/evasions/defaultArgs/index.js +43 -0
- package/dist/evasions/defaultArgs/index.js.map +1 -0
- package/dist/evasions/defaultArgs/package.json +5 -0
- package/dist/evasions/iframe.contentWindow/README.md +19 -0
- package/dist/evasions/iframe.contentWindow/index.d.ts +15 -0
- package/dist/evasions/iframe.contentWindow/index.d.ts.map +1 -0
- package/dist/evasions/iframe.contentWindow/index.js +132 -0
- package/dist/evasions/iframe.contentWindow/index.js.map +1 -0
- package/dist/evasions/iframe.contentWindow/package.json +5 -0
- package/dist/evasions/media.codecs/README.md +38 -0
- package/dist/evasions/media.codecs/index.d.ts +12 -0
- package/dist/evasions/media.codecs/index.d.ts.map +1 -0
- package/dist/evasions/media.codecs/index.js +89 -0
- package/dist/evasions/media.codecs/index.js.map +1 -0
- package/dist/evasions/media.codecs/package.json +5 -0
- package/dist/evasions/navigator.hardwareConcurrency/README.md +19 -0
- package/dist/evasions/navigator.hardwareConcurrency/index.d.ts +2 -0
- package/dist/evasions/navigator.hardwareConcurrency/index.d.ts.map +1 -0
- package/dist/evasions/navigator.hardwareConcurrency/index.js +45 -0
- package/dist/evasions/navigator.hardwareConcurrency/index.js.map +1 -0
- package/dist/evasions/navigator.hardwareConcurrency/package.json +5 -0
- package/dist/evasions/navigator.languages/README.md +17 -0
- package/dist/evasions/navigator.languages/index.d.ts +2 -0
- package/dist/evasions/navigator.languages/index.d.ts.map +1 -0
- package/dist/evasions/navigator.languages/index.js +44 -0
- package/dist/evasions/navigator.languages/index.js.map +1 -0
- package/dist/evasions/navigator.languages/package.json +5 -0
- package/dist/evasions/navigator.permissions/README.md +16 -0
- package/dist/evasions/navigator.permissions/index.d.ts +2 -0
- package/dist/evasions/navigator.permissions/index.d.ts.map +1 -0
- package/dist/evasions/navigator.permissions/index.js +66 -0
- package/dist/evasions/navigator.permissions/index.js.map +1 -0
- package/dist/evasions/navigator.permissions/package.json +5 -0
- package/dist/evasions/navigator.plugins/README.md +24 -0
- package/dist/evasions/navigator.plugins/data.json +48 -0
- package/dist/evasions/navigator.plugins/functionMocks.d.ts +9 -0
- package/dist/evasions/navigator.plugins/functionMocks.d.ts.map +1 -0
- package/dist/evasions/navigator.plugins/functionMocks.js +47 -0
- package/dist/evasions/navigator.plugins/functionMocks.js.map +1 -0
- package/dist/evasions/navigator.plugins/index.d.ts +19 -0
- package/dist/evasions/navigator.plugins/index.d.ts.map +1 -0
- package/dist/evasions/navigator.plugins/index.js +98 -0
- package/dist/evasions/navigator.plugins/index.js.map +1 -0
- package/dist/evasions/navigator.plugins/magicArray.d.ts +2 -0
- package/dist/evasions/navigator.plugins/magicArray.d.ts.map +1 -0
- package/dist/evasions/navigator.plugins/magicArray.js +145 -0
- package/dist/evasions/navigator.plugins/magicArray.js.map +1 -0
- package/dist/evasions/navigator.plugins/mimeTypes.d.ts +2 -0
- package/dist/evasions/navigator.plugins/mimeTypes.d.ts.map +1 -0
- package/dist/evasions/navigator.plugins/mimeTypes.js +18 -0
- package/dist/evasions/navigator.plugins/mimeTypes.js.map +1 -0
- package/dist/evasions/navigator.plugins/package.json +5 -0
- package/dist/evasions/navigator.plugins/plugins.d.ts +2 -0
- package/dist/evasions/navigator.plugins/plugins.d.ts.map +1 -0
- package/dist/evasions/navigator.plugins/plugins.js +18 -0
- package/dist/evasions/navigator.plugins/plugins.js.map +1 -0
- package/dist/evasions/navigator.vendor/README.md +36 -0
- package/dist/evasions/navigator.vendor/index.d.ts +2 -0
- package/dist/evasions/navigator.vendor/index.d.ts.map +1 -0
- package/dist/evasions/navigator.vendor/index.js +64 -0
- package/dist/evasions/navigator.vendor/index.js.map +1 -0
- package/dist/evasions/navigator.vendor/package.json +5 -0
- package/dist/evasions/navigator.webdriver/README.md +17 -0
- package/dist/evasions/navigator.webdriver/index.d.ts +13 -0
- package/dist/evasions/navigator.webdriver/index.d.ts.map +1 -0
- package/dist/evasions/navigator.webdriver/index.js +48 -0
- package/dist/evasions/navigator.webdriver/index.js.map +1 -0
- package/dist/evasions/navigator.webdriver/package.json +5 -0
- package/dist/evasions/sourceurl/README.md +17 -0
- package/dist/evasions/sourceurl/_fixtures/test.html +35 -0
- package/dist/evasions/sourceurl/index.d.ts +12 -0
- package/dist/evasions/sourceurl/index.d.ts.map +1 -0
- package/dist/evasions/sourceurl/index.js +82 -0
- package/dist/evasions/sourceurl/index.js.map +1 -0
- package/dist/evasions/sourceurl/package.json +5 -0
- package/dist/evasions/user-agent-override/README.md +53 -0
- package/dist/evasions/user-agent-override/index.d.ts +2 -0
- package/dist/evasions/user-agent-override/index.d.ts.map +1 -0
- package/dist/evasions/user-agent-override/index.js +206 -0
- package/dist/evasions/user-agent-override/index.js.map +1 -0
- package/dist/evasions/user-agent-override/package.json +5 -0
- package/dist/evasions/webgl.vendor/README.md +20 -0
- package/dist/evasions/webgl.vendor/index.d.ts +17 -0
- package/dist/evasions/webgl.vendor/index.d.ts.map +1 -0
- package/dist/evasions/webgl.vendor/index.js +57 -0
- package/dist/evasions/webgl.vendor/index.js.map +1 -0
- package/dist/evasions/webgl.vendor/package.json +5 -0
- package/dist/evasions/window.outerdimensions/README.md +17 -0
- package/dist/evasions/window.outerdimensions/index.d.ts +13 -0
- package/dist/evasions/window.outerdimensions/index.d.ts.map +1 -0
- package/dist/evasions/window.outerdimensions/index.js +42 -0
- package/dist/evasions/window.outerdimensions/index.js.map +1 -0
- package/dist/evasions/window.outerdimensions/package.json +5 -0
- package/dist/index.d.ts +130 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +164 -0
- package/dist/index.js.map +1 -0
- package/examples/detect-headless.js +95 -0
- package/examples/test1.js +20 -0
- package/examples/test2.js +25 -0
- package/package.json +70 -0
- package/src/evasions/README.md +13 -0
- package/src/evasions/_template/README.md +18 -0
- package/src/evasions/_template/index.js +26 -0
- package/src/evasions/_template/package.json +5 -0
- package/src/evasions/_utils/README.md +287 -0
- package/src/evasions/_utils/index.js +588 -0
- package/src/evasions/_utils/withUtils.js +47 -0
- package/src/evasions/chrome.app/README.md +16 -0
- package/src/evasions/chrome.app/index.js +97 -0
- package/src/evasions/chrome.app/package.json +5 -0
- package/src/evasions/chrome.csi/README.md +29 -0
- package/src/evasions/chrome.csi/index.js +69 -0
- package/src/evasions/chrome.csi/package.json +5 -0
- package/src/evasions/chrome.loadTimes/README.md +27 -0
- package/src/evasions/chrome.loadTimes/index.js +163 -0
- package/src/evasions/chrome.loadTimes/package.json +5 -0
- package/src/evasions/chrome.runtime/README.md +32 -0
- package/src/evasions/chrome.runtime/index.js +252 -0
- package/src/evasions/chrome.runtime/package.json +5 -0
- package/src/evasions/chrome.runtime/staticData.json +41 -0
- package/src/evasions/defaultArgs/README.md +17 -0
- package/src/evasions/defaultArgs/index.js +43 -0
- package/src/evasions/defaultArgs/package.json +5 -0
- package/src/evasions/iframe.contentWindow/README.md +19 -0
- package/src/evasions/iframe.contentWindow/index.js +132 -0
- package/src/evasions/iframe.contentWindow/package.json +5 -0
- package/src/evasions/media.codecs/README.md +38 -0
- package/src/evasions/media.codecs/index.js +89 -0
- package/src/evasions/media.codecs/package.json +5 -0
- package/src/evasions/navigator.hardwareConcurrency/README.md +19 -0
- package/src/evasions/navigator.hardwareConcurrency/index.js +45 -0
- package/src/evasions/navigator.hardwareConcurrency/package.json +5 -0
- package/src/evasions/navigator.languages/README.md +17 -0
- package/src/evasions/navigator.languages/index.js +44 -0
- package/src/evasions/navigator.languages/package.json +5 -0
- package/src/evasions/navigator.permissions/README.md +16 -0
- package/src/evasions/navigator.permissions/index.js +66 -0
- package/src/evasions/navigator.permissions/package.json +5 -0
- package/src/evasions/navigator.plugins/README.md +24 -0
- package/src/evasions/navigator.plugins/data.json +48 -0
- package/src/evasions/navigator.plugins/functionMocks.js +47 -0
- package/src/evasions/navigator.plugins/index.js +98 -0
- package/src/evasions/navigator.plugins/magicArray.js +145 -0
- package/src/evasions/navigator.plugins/mimeTypes.js +18 -0
- package/src/evasions/navigator.plugins/package.json +5 -0
- package/src/evasions/navigator.plugins/plugins.js +18 -0
- package/src/evasions/navigator.vendor/README.md +36 -0
- package/src/evasions/navigator.vendor/index.js +64 -0
- package/src/evasions/navigator.vendor/package.json +5 -0
- package/src/evasions/navigator.webdriver/README.md +17 -0
- package/src/evasions/navigator.webdriver/index.js +48 -0
- package/src/evasions/navigator.webdriver/package.json +5 -0
- package/src/evasions/sourceurl/README.md +17 -0
- package/src/evasions/sourceurl/_fixtures/test.html +35 -0
- package/src/evasions/sourceurl/index.js +82 -0
- package/src/evasions/sourceurl/package.json +5 -0
- package/src/evasions/user-agent-override/README.md +53 -0
- package/src/evasions/user-agent-override/index.js +206 -0
- package/src/evasions/user-agent-override/package.json +5 -0
- package/src/evasions/webgl.vendor/README.md +20 -0
- package/src/evasions/webgl.vendor/index.js +57 -0
- package/src/evasions/webgl.vendor/package.json +5 -0
- package/src/evasions/window.outerdimensions/README.md +17 -0
- package/src/evasions/window.outerdimensions/index.js +42 -0
- package/src/evasions/window.outerdimensions/package.json +5 -0
- package/src/index.d.ts +111 -0
- package/src/index.ts +188 -0
- package/test/cat-and-mouse.test.ts +170 -0
- package/test/evasions/_utils/index.test.ts +710 -0
- package/test/evasions/chrome.app/index.test.ts +69 -0
- package/test/evasions/chrome.csi/index.test.ts +46 -0
- package/test/evasions/chrome.loadTimes/index.test.ts +61 -0
- package/test/evasions/chrome.runtime/index.test.ts +282 -0
- package/test/evasions/defaultArgs/index.test.ts +36 -0
- package/test/evasions/iframe.contentWindow/index.test.js +450 -0
- package/test/evasions/media.codecs/index.test.js +103 -0
- package/test/evasions/navigator.hardwareConcurrency/index.test.js +58 -0
- package/test/evasions/navigator.languages/index.test.js +101 -0
- package/test/evasions/navigator.permissions/index.test.js +104 -0
- package/test/evasions/navigator.plugins/index.test.js +55 -0
- package/test/evasions/navigator.plugins/mimeTypes.test.js +220 -0
- package/test/evasions/navigator.plugins/plugins.test.js +181 -0
- package/test/evasions/navigator.vendor/index.test.js +68 -0
- package/test/evasions/navigator.webdriver/index.test.js +47 -0
- package/test/evasions/sourceurl/_fixtures/test.html +35 -0
- package/test/evasions/sourceurl/index.test.js +62 -0
- package/test/evasions/user-agent-override/index.test.js +338 -0
- package/test/evasions/webgl.vendor/index.test.js +220 -0
- package/test/fixtures/dummy-with-service-worker.html +22 -0
- package/test/fixtures/dummy.html +11 -0
- package/test/fixtures/sw.js +1 -0
- package/test/fpscanner.test.ts +54 -0
- package/test/index.test.ts +51 -0
- package/test/service-worker.test.ts +112 -0
- package/test/stealth/_results/_thumbs/headful-chrome-stealth.js.png +0 -0
- package/test/stealth/_results/_thumbs/headful-chrome-vanilla.js.png +0 -0
- package/test/stealth/_results/_thumbs/headful-chromium-stealth.js.png +0 -0
- package/test/stealth/_results/_thumbs/headful-chromium-vanilla.js.png +0 -0
- package/test/stealth/_results/_thumbs/headless-chrome-stealth.js.png +0 -0
- package/test/stealth/_results/_thumbs/headless-chrome-vanilla.js.png +0 -0
- package/test/stealth/_results/_thumbs/headless-chromium-stealth.js.png +0 -0
- package/test/stealth/_results/_thumbs/headless-chromium-vanilla.js.png +0 -0
- package/test/stealth/_results/headful-chrome-stealth.js.png +0 -0
- package/test/stealth/_results/headful-chrome-vanilla.js.png +0 -0
- package/test/stealth/_results/headful-chromium-stealth.js.png +0 -0
- package/test/stealth/_results/headful-chromium-vanilla.js.png +0 -0
- package/test/stealth/_results/headless-chrome-stealth.js.png +0 -0
- package/test/stealth/_results/headless-chrome-vanilla.js.png +0 -0
- package/test/stealth/_results/headless-chromium-stealth.js.png +0 -0
- package/test/stealth/_results/headless-chromium-vanilla.js.png +0 -0
- package/test/stealth/headful-chrome-stealth.js +25 -0
- package/test/stealth/headful-chrome-vanilla.js +23 -0
- package/test/stealth/headful-chromium-stealth.js +22 -0
- package/test/stealth/headful-chromium-vanilla.js +20 -0
- package/test/stealth/headless-chrome-stealth.js +25 -0
- package/test/stealth/headless-chrome-vanilla.js +23 -0
- package/test/stealth/headless-chromium-stealth.js +22 -0
- package/test/stealth/headless-chromium-vanilla.js +20 -0
- package/test/util.js +82 -0
- package/tsconfig.json +10 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +28 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { PuppeteerExtraPlugin } from '@zorilla/puppeteer-extra-plugin';
|
|
2
|
+
|
|
3
|
+
import withUtils from '../_utils/withUtils.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* By default puppeteer will have a fixed `navigator.vendor` property.
|
|
7
|
+
*
|
|
8
|
+
* This plugin makes it possible to change this property.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* const puppeteer = require("puppeteer-extra")
|
|
12
|
+
*
|
|
13
|
+
* const StealthPlugin = require("puppeteer-extra-plugin-stealth")
|
|
14
|
+
* const stealth = StealthPlugin()
|
|
15
|
+
* // Remove this specific stealth plugin from the default set
|
|
16
|
+
* stealth.enabledEvasions.delete("navigator.vendor")
|
|
17
|
+
* puppeteer.use(stealth)
|
|
18
|
+
*
|
|
19
|
+
* // Stealth plugins are just regular `puppeteer-extra` plugins and can be added as such
|
|
20
|
+
* const NavigatorVendorPlugin = require("puppeteer-extra-plugin-stealth/evasions/navigator.vendor")
|
|
21
|
+
* const nvp = NavigatorVendorPlugin({ vendor: 'Apple Computer, Inc.' }) // Custom vendor
|
|
22
|
+
* puppeteer.use(nvp)
|
|
23
|
+
*
|
|
24
|
+
* @param {Object} [opts] - Options
|
|
25
|
+
* @param {string} [opts.vendor] - The vendor to use in `navigator.vendor` (default: `Google Inc.`)
|
|
26
|
+
*
|
|
27
|
+
*/
|
|
28
|
+
class Plugin extends PuppeteerExtraPlugin {
|
|
29
|
+
constructor(opts = {}) {
|
|
30
|
+
super(opts);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get name() {
|
|
34
|
+
return 'stealth/evasions/navigator.vendor';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get defaults() {
|
|
38
|
+
return {
|
|
39
|
+
vendor: 'Google Inc.',
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async onPageCreated(page) {
|
|
44
|
+
this.debug('onPageCreated', {
|
|
45
|
+
opts: this.opts,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
await withUtils(page).evaluateOnNewDocument(
|
|
49
|
+
(utils, { opts }) => {
|
|
50
|
+
utils.replaceGetterWithProxy(
|
|
51
|
+
Object.getPrototypeOf(navigator),
|
|
52
|
+
'vendor',
|
|
53
|
+
utils.makeHandler().getterValue(opts.vendor)
|
|
54
|
+
);
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
opts: this.opts,
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
} // onPageCreated
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const defaultExport = opts => new Plugin(opts);
|
|
64
|
+
module.exports = defaultExport;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
## API
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
#### Table of Contents
|
|
5
|
+
|
|
6
|
+
- [class: Plugin](#class-plugin)
|
|
7
|
+
|
|
8
|
+
### class: [Plugin](https://github.com/zorillajs/zorilla/blob/e6133619b051febed630ada35241664eba59b9fa/packages/puppeteer-extra-plugin-stealth/evasions/navigator.webdriver/index.js#L9-L23)
|
|
9
|
+
|
|
10
|
+
- `opts` (optional, default `{}`)
|
|
11
|
+
|
|
12
|
+
**Extends: PuppeteerExtraPlugin**
|
|
13
|
+
|
|
14
|
+
Pass the Webdriver Test.
|
|
15
|
+
Will delete `navigator.webdriver` property.
|
|
16
|
+
|
|
17
|
+
---
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { PuppeteerExtraPlugin } from '@zorilla/puppeteer-extra-plugin';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pass the Webdriver Test.
|
|
5
|
+
* Will delete `navigator.webdriver` property.
|
|
6
|
+
*/
|
|
7
|
+
class Plugin extends PuppeteerExtraPlugin {
|
|
8
|
+
constructor(opts = {}) {
|
|
9
|
+
super(opts);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get name() {
|
|
13
|
+
return 'stealth/evasions/navigator.webdriver';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async onPageCreated(page) {
|
|
17
|
+
await page.evaluateOnNewDocument(() => {
|
|
18
|
+
if (navigator.webdriver === false) {
|
|
19
|
+
// Post Chrome 89.0.4339.0 and already good
|
|
20
|
+
} else if (navigator.webdriver === undefined) {
|
|
21
|
+
// Pre Chrome 89.0.4339.0 and already good
|
|
22
|
+
} else {
|
|
23
|
+
// Pre Chrome 88.0.4291.0 and needs patching
|
|
24
|
+
delete Object.getPrototypeOf(navigator).webdriver;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Post Chrome 88.0.4291.0
|
|
30
|
+
// Note: this will add an infobar to Chrome with a warning that an unsupported flag is set
|
|
31
|
+
// To remove this bar on Linux, run: mkdir -p /etc/opt/chrome/policies/managed && echo '{ "CommandLineFlagSecurityWarningsEnabled": false }' > /etc/opt/chrome/policies/managed/managed_policies.json
|
|
32
|
+
async beforeLaunch(options) {
|
|
33
|
+
// If disable-blink-features is already passed, append the AutomationControlled switch
|
|
34
|
+
const idx = options.args.findIndex(arg =>
|
|
35
|
+
arg.startsWith('--disable-blink-features=')
|
|
36
|
+
);
|
|
37
|
+
if (idx !== -1) {
|
|
38
|
+
const arg = options.args[idx];
|
|
39
|
+
options.args[idx] = `${arg},AutomationControlled`;
|
|
40
|
+
} else {
|
|
41
|
+
options.args.push('--disable-blink-features=AutomationControlled');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default function (pluginConfig) {
|
|
47
|
+
return new Plugin(pluginConfig);
|
|
48
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
## API
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
#### Table of Contents
|
|
5
|
+
|
|
6
|
+
- [class: Plugin](#class-plugin)
|
|
7
|
+
|
|
8
|
+
### class: [Plugin](https://github.com/zorillajs/zorilla/blob/e6133619b051febed630ada35241664eba59b9fa/packages/puppeteer-extra-plugin-stealth/evasions/sourceurl/index.js#L9-L58)
|
|
9
|
+
|
|
10
|
+
- `opts` (optional, default `{}`)
|
|
11
|
+
|
|
12
|
+
**Extends: PuppeteerExtraPlugin**
|
|
13
|
+
|
|
14
|
+
Strip sourceURL from scripts injected by puppeteer.
|
|
15
|
+
It can be used to identify the presence of pptr via stacktraces.
|
|
16
|
+
|
|
17
|
+
---
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>Page Title</title>
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<h1 id="result">Please use `document.querySelector`..</h1>
|
|
10
|
+
|
|
11
|
+
<script>
|
|
12
|
+
function test() {
|
|
13
|
+
const err = new Error('Test Error')
|
|
14
|
+
const isPptr = err.stack
|
|
15
|
+
.toString()
|
|
16
|
+
.includes('__puppeteer_evaluation_script')
|
|
17
|
+
|
|
18
|
+
document.getElementById('result').innerHTML = isPptr ? 'FAIL' : 'PASS'
|
|
19
|
+
console.log({ err, isPptr })
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function overrideFunction(item) {
|
|
23
|
+
item.obj[item.propName] = ((orig) => function() {
|
|
24
|
+
test()
|
|
25
|
+
return orig.apply(this, arguments)
|
|
26
|
+
})(item.obj[item.propName])
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
overrideFunction({
|
|
30
|
+
propName: 'querySelector',
|
|
31
|
+
obj: document
|
|
32
|
+
})
|
|
33
|
+
</script>
|
|
34
|
+
</body>
|
|
35
|
+
</html>
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { PuppeteerExtraPlugin } from '@zorilla/puppeteer-extra-plugin';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Strip sourceURL from scripts injected by puppeteer.
|
|
5
|
+
* It can be used to identify the presence of pptr via stacktraces.
|
|
6
|
+
*/
|
|
7
|
+
class Plugin extends PuppeteerExtraPlugin {
|
|
8
|
+
constructor(opts = {}) {
|
|
9
|
+
super(opts);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get name() {
|
|
13
|
+
return 'stealth/evasions/sourceurl';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async onPageCreated(page) {
|
|
17
|
+
const client =
|
|
18
|
+
page && typeof page._client === 'function'
|
|
19
|
+
? page._client()
|
|
20
|
+
: page._client;
|
|
21
|
+
if (!client) {
|
|
22
|
+
this.debug('Warning, missing properties to intercept CDP.', { page });
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Intercept CDP commands and strip identifying and unnecessary sourceURL
|
|
27
|
+
// https://github.com/puppeteer/puppeteer/blob/9b3005c105995cd267fdc7fb95b78aceab82cf0e/new-docs/puppeteer.cdpsession.md
|
|
28
|
+
const debug = this.debug;
|
|
29
|
+
client.send = ((originalMethod, context) =>
|
|
30
|
+
async function () {
|
|
31
|
+
const [method, paramArgs] = arguments || [];
|
|
32
|
+
const next = async () => {
|
|
33
|
+
try {
|
|
34
|
+
return await originalMethod.apply(context, [method, paramArgs]);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
// This seems to happen sometimes when redirects cause other outstanding requests to be cut short
|
|
37
|
+
if (
|
|
38
|
+
error instanceof Error &&
|
|
39
|
+
error.message.includes(
|
|
40
|
+
`Protocol error (Network.getResponseBody): No resource with given identifier found`
|
|
41
|
+
)
|
|
42
|
+
) {
|
|
43
|
+
debug(
|
|
44
|
+
`Caught and ignored an error about a missing network resource.`,
|
|
45
|
+
{ error }
|
|
46
|
+
);
|
|
47
|
+
} else {
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
if (!method || !paramArgs) {
|
|
54
|
+
return next();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// To find the methods/props in question check `_evaluateInternal` at:
|
|
58
|
+
// https://github.com/puppeteer/puppeteer/blob/main/src/common/ExecutionContext.ts#L186
|
|
59
|
+
const methodsToPatch = {
|
|
60
|
+
'Runtime.evaluate': 'expression',
|
|
61
|
+
'Runtime.callFunctionOn': 'functionDeclaration',
|
|
62
|
+
};
|
|
63
|
+
const SOURCE_URL_SUFFIX =
|
|
64
|
+
'//# sourceURL=__puppeteer_evaluation_script__';
|
|
65
|
+
|
|
66
|
+
if (!methodsToPatch[method] || !paramArgs[methodsToPatch[method]]) {
|
|
67
|
+
return next();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
debug('Stripping sourceURL', { method });
|
|
71
|
+
paramArgs[methodsToPatch[method]] = paramArgs[
|
|
72
|
+
methodsToPatch[method]
|
|
73
|
+
].replace(SOURCE_URL_SUFFIX, '');
|
|
74
|
+
|
|
75
|
+
return next();
|
|
76
|
+
})(client.send, client);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export default function (pluginConfig) {
|
|
81
|
+
return new Plugin(pluginConfig);
|
|
82
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
## API
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
#### Table of Contents
|
|
5
|
+
|
|
6
|
+
- [class: Plugin](#class-plugin)
|
|
7
|
+
|
|
8
|
+
### class: [Plugin](https://github.com/zorillajs/zorilla/blob/ab0047d1af7dc38412744abdb61bcfc35c42dc34/packages/puppeteer-extra-plugin-stealth/evasions/user-agent-override/index.js#L42-L203)
|
|
9
|
+
|
|
10
|
+
- `opts` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** Options (optional, default `{}`)
|
|
11
|
+
- `opts.userAgent` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** The user agent to use (default: browser.userAgent())
|
|
12
|
+
- `opts.locale` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** The locale to use in `Accept-Language` header and in `navigator.languages` (default: `en-US,en`)
|
|
13
|
+
- `opts.maskLinux` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Wether to hide Linux as platform in the user agent or not - true by default
|
|
14
|
+
|
|
15
|
+
**Extends: PuppeteerExtraPlugin**
|
|
16
|
+
|
|
17
|
+
Fixes the UserAgent info (composed of UA string, Accept-Language, Platform, and UA hints).
|
|
18
|
+
|
|
19
|
+
If you don't provide any values this plugin will default to using the regular UserAgent string (while stripping the headless part).
|
|
20
|
+
Default language is set to "en-US,en", the other settings match the UserAgent string.
|
|
21
|
+
If you are running on Linux, it will mask the settins to look like Windows. This behavior can be disabled with the `maskLinux` option.
|
|
22
|
+
|
|
23
|
+
By default puppeteer will not set a `Accept-Language` header in headless:
|
|
24
|
+
It's (theoretically) possible to fix that using either `page.setExtraHTTPHeaders` or a `--lang` launch arg.
|
|
25
|
+
Unfortunately `page.setExtraHTTPHeaders` will lowercase everything and launch args are not always available. :)
|
|
26
|
+
|
|
27
|
+
In addition, the `navigator.platform` property is always set to the host value, e.g. `Linux` which makes detection very easy.
|
|
28
|
+
|
|
29
|
+
Note: You cannot use the regular `page.setUserAgent()` puppeteer call in your code,
|
|
30
|
+
as it will reset the language and platform values you set with this plugin.
|
|
31
|
+
|
|
32
|
+
Example:
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
const puppeteer = require('@zorilla/puppeteer-extra')
|
|
36
|
+
|
|
37
|
+
const StealthPlugin = require('@zorilla/puppeteer-extra-plugin-stealth')
|
|
38
|
+
const stealth = StealthPlugin()
|
|
39
|
+
// Remove this specific stealth plugin from the default set
|
|
40
|
+
stealth.enabledEvasions.delete('user-agent-override')
|
|
41
|
+
puppeteer.use(stealth)
|
|
42
|
+
|
|
43
|
+
// Stealth plugins are just regular `puppeteer-extra` plugins and can be added as such
|
|
44
|
+
const UserAgentOverride = require('@zorilla/puppeteer-extra-plugin-stealth/evasions/user-agent-override')
|
|
45
|
+
// Define custom UA and locale
|
|
46
|
+
const ua = UserAgentOverride({
|
|
47
|
+
userAgent: 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)',
|
|
48
|
+
locale: 'de-DE,de'
|
|
49
|
+
})
|
|
50
|
+
puppeteer.use(ua)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { PuppeteerExtraPlugin } from '@zorilla/puppeteer-extra-plugin';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Fixes the UserAgent info (composed of UA string, Accept-Language, Platform, and UA hints).
|
|
5
|
+
*
|
|
6
|
+
* If you don't provide any values this plugin will default to using the regular UserAgent string (while stripping the headless part).
|
|
7
|
+
* Default language is set to "en-US,en", the other settings match the UserAgent string.
|
|
8
|
+
* If you are running on Linux, it will mask the settins to look like Windows. This behavior can be disabled with the `maskLinux` option.
|
|
9
|
+
*
|
|
10
|
+
* By default puppeteer will not set a `Accept-Language` header in headless:
|
|
11
|
+
* It's (theoretically) possible to fix that using either `page.setExtraHTTPHeaders` or a `--lang` launch arg.
|
|
12
|
+
* Unfortunately `page.setExtraHTTPHeaders` will lowercase everything and launch args are not always available. :)
|
|
13
|
+
*
|
|
14
|
+
* In addition, the `navigator.platform` property is always set to the host value, e.g. `Linux` which makes detection very easy.
|
|
15
|
+
*
|
|
16
|
+
* Note: You cannot use the regular `page.setUserAgent()` puppeteer call in your code,
|
|
17
|
+
* as it will reset the language and platform values you set with this plugin.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* const puppeteer = require("puppeteer-extra")
|
|
21
|
+
*
|
|
22
|
+
* const StealthPlugin = require("puppeteer-extra-plugin-stealth")
|
|
23
|
+
* const stealth = StealthPlugin()
|
|
24
|
+
* // Remove this specific stealth plugin from the default set
|
|
25
|
+
* stealth.enabledEvasions.delete("user-agent-override")
|
|
26
|
+
* puppeteer.use(stealth)
|
|
27
|
+
*
|
|
28
|
+
* // Stealth plugins are just regular `puppeteer-extra` plugins and can be added as such
|
|
29
|
+
* const UserAgentOverride = require("puppeteer-extra-plugin-stealth/evasions/user-agent-override")
|
|
30
|
+
* // Define custom UA and locale
|
|
31
|
+
* const ua = UserAgentOverride({ userAgent: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)", locale: "de-DE,de" })
|
|
32
|
+
* puppeteer.use(ua)
|
|
33
|
+
*
|
|
34
|
+
* @param {Object} [opts] - Options
|
|
35
|
+
* @param {string} [opts.userAgent] - The user agent to use (default: browser.userAgent())
|
|
36
|
+
* @param {string} [opts.locale] - The locale to use in `Accept-Language` header and in `navigator.languages` (default: `en-US,en`)
|
|
37
|
+
* @param {boolean} [opts.maskLinux] - Wether to hide Linux as platform in the user agent or not - true by default
|
|
38
|
+
*
|
|
39
|
+
*/
|
|
40
|
+
class Plugin extends PuppeteerExtraPlugin {
|
|
41
|
+
constructor(opts = {}) {
|
|
42
|
+
super(opts);
|
|
43
|
+
|
|
44
|
+
this._headless = false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get name() {
|
|
48
|
+
return 'stealth/evasions/user-agent-override';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
get dependencies() {
|
|
52
|
+
return new Set(['user-preferences']);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
get defaults() {
|
|
56
|
+
return {
|
|
57
|
+
userAgent: null,
|
|
58
|
+
locale: 'en-US,en',
|
|
59
|
+
maskLinux: true,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async onPageCreated(page) {
|
|
64
|
+
// Determine the full user agent string, strip the "Headless" part
|
|
65
|
+
let ua =
|
|
66
|
+
this.opts.userAgent ||
|
|
67
|
+
(await page.browser().userAgent()).replace('HeadlessChrome/', 'Chrome/');
|
|
68
|
+
|
|
69
|
+
if (
|
|
70
|
+
this.opts.maskLinux &&
|
|
71
|
+
ua.includes('Linux') &&
|
|
72
|
+
!ua.includes('Android') // Skip Android user agents since they also contain Linux
|
|
73
|
+
) {
|
|
74
|
+
ua = ua.replace(/\(([^)]+)\)/, '(Windows NT 10.0; Win64; x64)'); // Replace the first part in parentheses with Windows data
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Full version number from Chrome
|
|
78
|
+
const uaVersion = ua.includes('Chrome/')
|
|
79
|
+
? ua.match(/Chrome\/([\d|.]+)/)[1]
|
|
80
|
+
: (await page.browser().version()).match(/\/([\d|.]+)/)[1];
|
|
81
|
+
|
|
82
|
+
// Get platform identifier (short or long version)
|
|
83
|
+
const _getPlatform = (extended = false) => {
|
|
84
|
+
if (ua.includes('Mac OS X')) {
|
|
85
|
+
return extended ? 'Mac OS X' : 'MacIntel';
|
|
86
|
+
} else if (ua.includes('Android')) {
|
|
87
|
+
return 'Android';
|
|
88
|
+
} else if (ua.includes('Linux')) {
|
|
89
|
+
return 'Linux';
|
|
90
|
+
} else {
|
|
91
|
+
return extended ? 'Windows' : 'Win32';
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// Source in C++: https://source.chromium.org/chromium/chromium/src/+/master:components/embedder_support/user_agent_utils.cc;l=55-100
|
|
96
|
+
const _getBrands = () => {
|
|
97
|
+
const seed = uaVersion.split('.')[0]; // the major version number of Chrome
|
|
98
|
+
|
|
99
|
+
const order = [
|
|
100
|
+
[0, 1, 2],
|
|
101
|
+
[0, 2, 1],
|
|
102
|
+
[1, 0, 2],
|
|
103
|
+
[1, 2, 0],
|
|
104
|
+
[2, 0, 1],
|
|
105
|
+
[2, 1, 0],
|
|
106
|
+
][seed % 6];
|
|
107
|
+
const escapedChars = [' ', ' ', ';'];
|
|
108
|
+
|
|
109
|
+
const greaseyBrand = `${escapedChars[order[0]]}Not${
|
|
110
|
+
escapedChars[order[1]]
|
|
111
|
+
}A${escapedChars[order[2]]}Brand`;
|
|
112
|
+
|
|
113
|
+
const greasedBrandVersionList = [];
|
|
114
|
+
greasedBrandVersionList[order[0]] = {
|
|
115
|
+
brand: greaseyBrand,
|
|
116
|
+
version: '99',
|
|
117
|
+
};
|
|
118
|
+
greasedBrandVersionList[order[1]] = {
|
|
119
|
+
brand: 'Chromium',
|
|
120
|
+
version: seed,
|
|
121
|
+
};
|
|
122
|
+
greasedBrandVersionList[order[2]] = {
|
|
123
|
+
brand: 'Google Chrome',
|
|
124
|
+
version: seed,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
return greasedBrandVersionList;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
// Return OS version
|
|
131
|
+
const _getPlatformVersion = () => {
|
|
132
|
+
if (ua.includes('Mac OS X ')) {
|
|
133
|
+
return ua.match(/Mac OS X ([^)]+)/)[1];
|
|
134
|
+
} else if (ua.includes('Android ')) {
|
|
135
|
+
return ua.match(/Android ([^;]+)/)[1];
|
|
136
|
+
} else if (ua.includes('Windows ')) {
|
|
137
|
+
return ua.match(/Windows .*?([\d|.]+);?/)[1];
|
|
138
|
+
} else {
|
|
139
|
+
return '';
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// Get architecture, this seems to be empty on mobile and x86 on desktop
|
|
144
|
+
const _getPlatformArch = () => (_getMobile() ? '' : 'x86');
|
|
145
|
+
|
|
146
|
+
// Return the Android model, empty on desktop
|
|
147
|
+
const _getPlatformModel = () =>
|
|
148
|
+
_getMobile() ? ua.match(/Android.*?;\s([^)]+)/)[1] : '';
|
|
149
|
+
|
|
150
|
+
const _getMobile = () => ua.includes('Android');
|
|
151
|
+
|
|
152
|
+
const override = {
|
|
153
|
+
userAgent: ua,
|
|
154
|
+
platform: _getPlatform(),
|
|
155
|
+
userAgentMetadata: {
|
|
156
|
+
brands: _getBrands(),
|
|
157
|
+
fullVersion: uaVersion,
|
|
158
|
+
platform: _getPlatform(true),
|
|
159
|
+
platformVersion: _getPlatformVersion(),
|
|
160
|
+
architecture: _getPlatformArch(),
|
|
161
|
+
model: _getPlatformModel(),
|
|
162
|
+
mobile: _getMobile(),
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// In case of headless, override the acceptLanguage in CDP.
|
|
167
|
+
// This is not preferred, as it messed up the header order.
|
|
168
|
+
// On headful, we set the user preference language setting instead.
|
|
169
|
+
if (this._headless) {
|
|
170
|
+
override.acceptLanguage = this.opts.locale || 'en-US,en';
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
this.debug('onPageCreated - Will set these user agent options', {
|
|
174
|
+
override,
|
|
175
|
+
opts: this.opts,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const client =
|
|
179
|
+
typeof page._client === 'function' ? page._client() : page._client;
|
|
180
|
+
client.send('Network.setUserAgentOverride', override);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async beforeLaunch(options) {
|
|
184
|
+
// Check if launched headless
|
|
185
|
+
this._headless = options.headless;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async beforeConnect() {
|
|
189
|
+
// Treat browsers using connect() as headless browsers
|
|
190
|
+
this._headless = true;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
get data() {
|
|
194
|
+
return [
|
|
195
|
+
{
|
|
196
|
+
name: 'userPreferences',
|
|
197
|
+
value: {
|
|
198
|
+
intl: { accept_languages: this.opts.locale || 'en-US,en' },
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
];
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const defaultExport = opts => new Plugin(opts);
|
|
206
|
+
module.exports = defaultExport;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
## API
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
#### Table of Contents
|
|
5
|
+
|
|
6
|
+
- [class: Plugin](#class-plugin)
|
|
7
|
+
|
|
8
|
+
### class: [Plugin](https://github.com/zorillajs/zorilla/blob/e6133619b051febed630ada35241664eba59b9fa/packages/puppeteer-extra-plugin-stealth/evasions/webgl.vendor/index.js#L17-L55)
|
|
9
|
+
|
|
10
|
+
- `opts` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** Options (optional, default `{}`)
|
|
11
|
+
- `opts.vendor` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** The vendor string to use (default: `Intel Inc.`)
|
|
12
|
+
- `opts.renderer` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** The renderer string (default: `Intel Iris OpenGL Engine`)
|
|
13
|
+
|
|
14
|
+
**Extends: PuppeteerExtraPlugin**
|
|
15
|
+
|
|
16
|
+
Fix WebGL Vendor/Renderer being set to Google in headless mode
|
|
17
|
+
|
|
18
|
+
Example data (Apple Retina MBP 13): {vendor: "Intel Inc.", renderer: "Intel(R) Iris(TM) Graphics 6100"}
|
|
19
|
+
|
|
20
|
+
---
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { PuppeteerExtraPlugin } from '@zorilla/puppeteer-extra-plugin';
|
|
2
|
+
|
|
3
|
+
import withUtils from '../_utils/withUtils.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Fix WebGL Vendor/Renderer being set to Google in headless mode
|
|
7
|
+
*
|
|
8
|
+
* Example data (Apple Retina MBP 13): {vendor: "Intel Inc.", renderer: "Intel(R) Iris(TM) Graphics 6100"}
|
|
9
|
+
*
|
|
10
|
+
* @param {Object} [opts] - Options
|
|
11
|
+
* @param {string} [opts.vendor] - The vendor string to use (default: `Intel Inc.`)
|
|
12
|
+
* @param {string} [opts.renderer] - The renderer string (default: `Intel Iris OpenGL Engine`)
|
|
13
|
+
*/
|
|
14
|
+
class Plugin extends PuppeteerExtraPlugin {
|
|
15
|
+
constructor(opts = {}) {
|
|
16
|
+
super(opts);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
get name() {
|
|
20
|
+
return 'stealth/evasions/webgl.vendor';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* global WebGLRenderingContext WebGL2RenderingContext */
|
|
24
|
+
async onPageCreated(page) {
|
|
25
|
+
await withUtils(page).evaluateOnNewDocument((utils, opts) => {
|
|
26
|
+
const getParameterProxyHandler = {
|
|
27
|
+
apply: (target, ctx, args) => {
|
|
28
|
+
const param = (args || [])[0];
|
|
29
|
+
const result = utils.cache.Reflect.apply(target, ctx, args);
|
|
30
|
+
// UNMASKED_VENDOR_WEBGL
|
|
31
|
+
if (param === 37445) {
|
|
32
|
+
return opts.vendor || 'Intel Inc.'; // default in headless: Google Inc.
|
|
33
|
+
}
|
|
34
|
+
// UNMASKED_RENDERER_WEBGL
|
|
35
|
+
if (param === 37446) {
|
|
36
|
+
return opts.renderer || 'Intel Iris OpenGL Engine'; // default in headless: Google SwiftShader
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// There's more than one WebGL rendering context
|
|
43
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext#Browser_compatibility
|
|
44
|
+
// To find out the original values here: Object.getOwnPropertyDescriptors(WebGLRenderingContext.prototype.getParameter)
|
|
45
|
+
const addProxy = (obj, propName) => {
|
|
46
|
+
utils.replaceWithProxy(obj, propName, getParameterProxyHandler);
|
|
47
|
+
};
|
|
48
|
+
// For whatever weird reason loops don't play nice with Object.defineProperty, here's the next best thing:
|
|
49
|
+
addProxy(WebGLRenderingContext.prototype, 'getParameter');
|
|
50
|
+
addProxy(WebGL2RenderingContext.prototype, 'getParameter');
|
|
51
|
+
}, this.opts);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default function (pluginConfig) {
|
|
56
|
+
return new Plugin(pluginConfig);
|
|
57
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
## API
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
#### Table of Contents
|
|
5
|
+
|
|
6
|
+
- [class: Plugin](#class-plugin)
|
|
7
|
+
|
|
8
|
+
### class: [Plugin](https://github.com/zorillajs/zorilla/blob/e6133619b051febed630ada35241664eba59b9fa/packages/puppeteer-extra-plugin-stealth/evasions/window.outerdimensions/index.js#L9-L40)
|
|
9
|
+
|
|
10
|
+
- `opts` (optional, default `{}`)
|
|
11
|
+
|
|
12
|
+
**Extends: PuppeteerExtraPlugin**
|
|
13
|
+
|
|
14
|
+
Fix missing window.outerWidth/window.outerHeight in headless mode
|
|
15
|
+
Will also set the viewport to match window size, unless specified by user
|
|
16
|
+
|
|
17
|
+
---
|