@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.
Files changed (270) hide show
  1. package/.claude/settings.local.json +21 -0
  2. package/LICENSE +21 -0
  3. package/README.md +324 -0
  4. package/dist/evasions/README.md +13 -0
  5. package/dist/evasions/_template/README.md +18 -0
  6. package/dist/evasions/_template/index.d.ts +13 -0
  7. package/dist/evasions/_template/index.d.ts.map +1 -0
  8. package/dist/evasions/_template/index.js +26 -0
  9. package/dist/evasions/_template/index.js.map +1 -0
  10. package/dist/evasions/_template/package.json +5 -0
  11. package/dist/evasions/_utils/README.md +287 -0
  12. package/dist/evasions/_utils/index.d.ts +238 -0
  13. package/dist/evasions/_utils/index.d.ts.map +1 -0
  14. package/dist/evasions/_utils/index.js +588 -0
  15. package/dist/evasions/_utils/index.js.map +1 -0
  16. package/dist/evasions/_utils/withUtils.d.ts +12 -0
  17. package/dist/evasions/_utils/withUtils.d.ts.map +1 -0
  18. package/dist/evasions/_utils/withUtils.js +47 -0
  19. package/dist/evasions/_utils/withUtils.js.map +1 -0
  20. package/dist/evasions/chrome.app/README.md +16 -0
  21. package/dist/evasions/chrome.app/index.d.ts +11 -0
  22. package/dist/evasions/chrome.app/index.d.ts.map +1 -0
  23. package/dist/evasions/chrome.app/index.js +97 -0
  24. package/dist/evasions/chrome.app/index.js.map +1 -0
  25. package/dist/evasions/chrome.app/package.json +5 -0
  26. package/dist/evasions/chrome.csi/README.md +29 -0
  27. package/dist/evasions/chrome.csi/index.d.ts +25 -0
  28. package/dist/evasions/chrome.csi/index.d.ts.map +1 -0
  29. package/dist/evasions/chrome.csi/index.js +69 -0
  30. package/dist/evasions/chrome.csi/index.js.map +1 -0
  31. package/dist/evasions/chrome.csi/package.json +5 -0
  32. package/dist/evasions/chrome.loadTimes/README.md +27 -0
  33. package/dist/evasions/chrome.loadTimes/index.d.ts +23 -0
  34. package/dist/evasions/chrome.loadTimes/index.d.ts.map +1 -0
  35. package/dist/evasions/chrome.loadTimes/index.js +163 -0
  36. package/dist/evasions/chrome.loadTimes/index.js.map +1 -0
  37. package/dist/evasions/chrome.loadTimes/package.json +5 -0
  38. package/dist/evasions/chrome.runtime/README.md +32 -0
  39. package/dist/evasions/chrome.runtime/index.d.ts +14 -0
  40. package/dist/evasions/chrome.runtime/index.d.ts.map +1 -0
  41. package/dist/evasions/chrome.runtime/index.js +252 -0
  42. package/dist/evasions/chrome.runtime/index.js.map +1 -0
  43. package/dist/evasions/chrome.runtime/package.json +5 -0
  44. package/dist/evasions/chrome.runtime/staticData.json +41 -0
  45. package/dist/evasions/defaultArgs/README.md +17 -0
  46. package/dist/evasions/defaultArgs/index.d.ts +2 -0
  47. package/dist/evasions/defaultArgs/index.d.ts.map +1 -0
  48. package/dist/evasions/defaultArgs/index.js +43 -0
  49. package/dist/evasions/defaultArgs/index.js.map +1 -0
  50. package/dist/evasions/defaultArgs/package.json +5 -0
  51. package/dist/evasions/iframe.contentWindow/README.md +19 -0
  52. package/dist/evasions/iframe.contentWindow/index.d.ts +15 -0
  53. package/dist/evasions/iframe.contentWindow/index.d.ts.map +1 -0
  54. package/dist/evasions/iframe.contentWindow/index.js +132 -0
  55. package/dist/evasions/iframe.contentWindow/index.js.map +1 -0
  56. package/dist/evasions/iframe.contentWindow/package.json +5 -0
  57. package/dist/evasions/media.codecs/README.md +38 -0
  58. package/dist/evasions/media.codecs/index.d.ts +12 -0
  59. package/dist/evasions/media.codecs/index.d.ts.map +1 -0
  60. package/dist/evasions/media.codecs/index.js +89 -0
  61. package/dist/evasions/media.codecs/index.js.map +1 -0
  62. package/dist/evasions/media.codecs/package.json +5 -0
  63. package/dist/evasions/navigator.hardwareConcurrency/README.md +19 -0
  64. package/dist/evasions/navigator.hardwareConcurrency/index.d.ts +2 -0
  65. package/dist/evasions/navigator.hardwareConcurrency/index.d.ts.map +1 -0
  66. package/dist/evasions/navigator.hardwareConcurrency/index.js +45 -0
  67. package/dist/evasions/navigator.hardwareConcurrency/index.js.map +1 -0
  68. package/dist/evasions/navigator.hardwareConcurrency/package.json +5 -0
  69. package/dist/evasions/navigator.languages/README.md +17 -0
  70. package/dist/evasions/navigator.languages/index.d.ts +2 -0
  71. package/dist/evasions/navigator.languages/index.d.ts.map +1 -0
  72. package/dist/evasions/navigator.languages/index.js +44 -0
  73. package/dist/evasions/navigator.languages/index.js.map +1 -0
  74. package/dist/evasions/navigator.languages/package.json +5 -0
  75. package/dist/evasions/navigator.permissions/README.md +16 -0
  76. package/dist/evasions/navigator.permissions/index.d.ts +2 -0
  77. package/dist/evasions/navigator.permissions/index.d.ts.map +1 -0
  78. package/dist/evasions/navigator.permissions/index.js +66 -0
  79. package/dist/evasions/navigator.permissions/index.js.map +1 -0
  80. package/dist/evasions/navigator.permissions/package.json +5 -0
  81. package/dist/evasions/navigator.plugins/README.md +24 -0
  82. package/dist/evasions/navigator.plugins/data.json +48 -0
  83. package/dist/evasions/navigator.plugins/functionMocks.d.ts +9 -0
  84. package/dist/evasions/navigator.plugins/functionMocks.d.ts.map +1 -0
  85. package/dist/evasions/navigator.plugins/functionMocks.js +47 -0
  86. package/dist/evasions/navigator.plugins/functionMocks.js.map +1 -0
  87. package/dist/evasions/navigator.plugins/index.d.ts +19 -0
  88. package/dist/evasions/navigator.plugins/index.d.ts.map +1 -0
  89. package/dist/evasions/navigator.plugins/index.js +98 -0
  90. package/dist/evasions/navigator.plugins/index.js.map +1 -0
  91. package/dist/evasions/navigator.plugins/magicArray.d.ts +2 -0
  92. package/dist/evasions/navigator.plugins/magicArray.d.ts.map +1 -0
  93. package/dist/evasions/navigator.plugins/magicArray.js +145 -0
  94. package/dist/evasions/navigator.plugins/magicArray.js.map +1 -0
  95. package/dist/evasions/navigator.plugins/mimeTypes.d.ts +2 -0
  96. package/dist/evasions/navigator.plugins/mimeTypes.d.ts.map +1 -0
  97. package/dist/evasions/navigator.plugins/mimeTypes.js +18 -0
  98. package/dist/evasions/navigator.plugins/mimeTypes.js.map +1 -0
  99. package/dist/evasions/navigator.plugins/package.json +5 -0
  100. package/dist/evasions/navigator.plugins/plugins.d.ts +2 -0
  101. package/dist/evasions/navigator.plugins/plugins.d.ts.map +1 -0
  102. package/dist/evasions/navigator.plugins/plugins.js +18 -0
  103. package/dist/evasions/navigator.plugins/plugins.js.map +1 -0
  104. package/dist/evasions/navigator.vendor/README.md +36 -0
  105. package/dist/evasions/navigator.vendor/index.d.ts +2 -0
  106. package/dist/evasions/navigator.vendor/index.d.ts.map +1 -0
  107. package/dist/evasions/navigator.vendor/index.js +64 -0
  108. package/dist/evasions/navigator.vendor/index.js.map +1 -0
  109. package/dist/evasions/navigator.vendor/package.json +5 -0
  110. package/dist/evasions/navigator.webdriver/README.md +17 -0
  111. package/dist/evasions/navigator.webdriver/index.d.ts +13 -0
  112. package/dist/evasions/navigator.webdriver/index.d.ts.map +1 -0
  113. package/dist/evasions/navigator.webdriver/index.js +48 -0
  114. package/dist/evasions/navigator.webdriver/index.js.map +1 -0
  115. package/dist/evasions/navigator.webdriver/package.json +5 -0
  116. package/dist/evasions/sourceurl/README.md +17 -0
  117. package/dist/evasions/sourceurl/_fixtures/test.html +35 -0
  118. package/dist/evasions/sourceurl/index.d.ts +12 -0
  119. package/dist/evasions/sourceurl/index.d.ts.map +1 -0
  120. package/dist/evasions/sourceurl/index.js +82 -0
  121. package/dist/evasions/sourceurl/index.js.map +1 -0
  122. package/dist/evasions/sourceurl/package.json +5 -0
  123. package/dist/evasions/user-agent-override/README.md +53 -0
  124. package/dist/evasions/user-agent-override/index.d.ts +2 -0
  125. package/dist/evasions/user-agent-override/index.d.ts.map +1 -0
  126. package/dist/evasions/user-agent-override/index.js +206 -0
  127. package/dist/evasions/user-agent-override/index.js.map +1 -0
  128. package/dist/evasions/user-agent-override/package.json +5 -0
  129. package/dist/evasions/webgl.vendor/README.md +20 -0
  130. package/dist/evasions/webgl.vendor/index.d.ts +17 -0
  131. package/dist/evasions/webgl.vendor/index.d.ts.map +1 -0
  132. package/dist/evasions/webgl.vendor/index.js +57 -0
  133. package/dist/evasions/webgl.vendor/index.js.map +1 -0
  134. package/dist/evasions/webgl.vendor/package.json +5 -0
  135. package/dist/evasions/window.outerdimensions/README.md +17 -0
  136. package/dist/evasions/window.outerdimensions/index.d.ts +13 -0
  137. package/dist/evasions/window.outerdimensions/index.d.ts.map +1 -0
  138. package/dist/evasions/window.outerdimensions/index.js +42 -0
  139. package/dist/evasions/window.outerdimensions/index.js.map +1 -0
  140. package/dist/evasions/window.outerdimensions/package.json +5 -0
  141. package/dist/index.d.ts +130 -0
  142. package/dist/index.d.ts.map +1 -0
  143. package/dist/index.js +164 -0
  144. package/dist/index.js.map +1 -0
  145. package/examples/detect-headless.js +95 -0
  146. package/examples/test1.js +20 -0
  147. package/examples/test2.js +25 -0
  148. package/package.json +70 -0
  149. package/src/evasions/README.md +13 -0
  150. package/src/evasions/_template/README.md +18 -0
  151. package/src/evasions/_template/index.js +26 -0
  152. package/src/evasions/_template/package.json +5 -0
  153. package/src/evasions/_utils/README.md +287 -0
  154. package/src/evasions/_utils/index.js +588 -0
  155. package/src/evasions/_utils/withUtils.js +47 -0
  156. package/src/evasions/chrome.app/README.md +16 -0
  157. package/src/evasions/chrome.app/index.js +97 -0
  158. package/src/evasions/chrome.app/package.json +5 -0
  159. package/src/evasions/chrome.csi/README.md +29 -0
  160. package/src/evasions/chrome.csi/index.js +69 -0
  161. package/src/evasions/chrome.csi/package.json +5 -0
  162. package/src/evasions/chrome.loadTimes/README.md +27 -0
  163. package/src/evasions/chrome.loadTimes/index.js +163 -0
  164. package/src/evasions/chrome.loadTimes/package.json +5 -0
  165. package/src/evasions/chrome.runtime/README.md +32 -0
  166. package/src/evasions/chrome.runtime/index.js +252 -0
  167. package/src/evasions/chrome.runtime/package.json +5 -0
  168. package/src/evasions/chrome.runtime/staticData.json +41 -0
  169. package/src/evasions/defaultArgs/README.md +17 -0
  170. package/src/evasions/defaultArgs/index.js +43 -0
  171. package/src/evasions/defaultArgs/package.json +5 -0
  172. package/src/evasions/iframe.contentWindow/README.md +19 -0
  173. package/src/evasions/iframe.contentWindow/index.js +132 -0
  174. package/src/evasions/iframe.contentWindow/package.json +5 -0
  175. package/src/evasions/media.codecs/README.md +38 -0
  176. package/src/evasions/media.codecs/index.js +89 -0
  177. package/src/evasions/media.codecs/package.json +5 -0
  178. package/src/evasions/navigator.hardwareConcurrency/README.md +19 -0
  179. package/src/evasions/navigator.hardwareConcurrency/index.js +45 -0
  180. package/src/evasions/navigator.hardwareConcurrency/package.json +5 -0
  181. package/src/evasions/navigator.languages/README.md +17 -0
  182. package/src/evasions/navigator.languages/index.js +44 -0
  183. package/src/evasions/navigator.languages/package.json +5 -0
  184. package/src/evasions/navigator.permissions/README.md +16 -0
  185. package/src/evasions/navigator.permissions/index.js +66 -0
  186. package/src/evasions/navigator.permissions/package.json +5 -0
  187. package/src/evasions/navigator.plugins/README.md +24 -0
  188. package/src/evasions/navigator.plugins/data.json +48 -0
  189. package/src/evasions/navigator.plugins/functionMocks.js +47 -0
  190. package/src/evasions/navigator.plugins/index.js +98 -0
  191. package/src/evasions/navigator.plugins/magicArray.js +145 -0
  192. package/src/evasions/navigator.plugins/mimeTypes.js +18 -0
  193. package/src/evasions/navigator.plugins/package.json +5 -0
  194. package/src/evasions/navigator.plugins/plugins.js +18 -0
  195. package/src/evasions/navigator.vendor/README.md +36 -0
  196. package/src/evasions/navigator.vendor/index.js +64 -0
  197. package/src/evasions/navigator.vendor/package.json +5 -0
  198. package/src/evasions/navigator.webdriver/README.md +17 -0
  199. package/src/evasions/navigator.webdriver/index.js +48 -0
  200. package/src/evasions/navigator.webdriver/package.json +5 -0
  201. package/src/evasions/sourceurl/README.md +17 -0
  202. package/src/evasions/sourceurl/_fixtures/test.html +35 -0
  203. package/src/evasions/sourceurl/index.js +82 -0
  204. package/src/evasions/sourceurl/package.json +5 -0
  205. package/src/evasions/user-agent-override/README.md +53 -0
  206. package/src/evasions/user-agent-override/index.js +206 -0
  207. package/src/evasions/user-agent-override/package.json +5 -0
  208. package/src/evasions/webgl.vendor/README.md +20 -0
  209. package/src/evasions/webgl.vendor/index.js +57 -0
  210. package/src/evasions/webgl.vendor/package.json +5 -0
  211. package/src/evasions/window.outerdimensions/README.md +17 -0
  212. package/src/evasions/window.outerdimensions/index.js +42 -0
  213. package/src/evasions/window.outerdimensions/package.json +5 -0
  214. package/src/index.d.ts +111 -0
  215. package/src/index.ts +188 -0
  216. package/test/cat-and-mouse.test.ts +170 -0
  217. package/test/evasions/_utils/index.test.ts +710 -0
  218. package/test/evasions/chrome.app/index.test.ts +69 -0
  219. package/test/evasions/chrome.csi/index.test.ts +46 -0
  220. package/test/evasions/chrome.loadTimes/index.test.ts +61 -0
  221. package/test/evasions/chrome.runtime/index.test.ts +282 -0
  222. package/test/evasions/defaultArgs/index.test.ts +36 -0
  223. package/test/evasions/iframe.contentWindow/index.test.js +450 -0
  224. package/test/evasions/media.codecs/index.test.js +103 -0
  225. package/test/evasions/navigator.hardwareConcurrency/index.test.js +58 -0
  226. package/test/evasions/navigator.languages/index.test.js +101 -0
  227. package/test/evasions/navigator.permissions/index.test.js +104 -0
  228. package/test/evasions/navigator.plugins/index.test.js +55 -0
  229. package/test/evasions/navigator.plugins/mimeTypes.test.js +220 -0
  230. package/test/evasions/navigator.plugins/plugins.test.js +181 -0
  231. package/test/evasions/navigator.vendor/index.test.js +68 -0
  232. package/test/evasions/navigator.webdriver/index.test.js +47 -0
  233. package/test/evasions/sourceurl/_fixtures/test.html +35 -0
  234. package/test/evasions/sourceurl/index.test.js +62 -0
  235. package/test/evasions/user-agent-override/index.test.js +338 -0
  236. package/test/evasions/webgl.vendor/index.test.js +220 -0
  237. package/test/fixtures/dummy-with-service-worker.html +22 -0
  238. package/test/fixtures/dummy.html +11 -0
  239. package/test/fixtures/sw.js +1 -0
  240. package/test/fpscanner.test.ts +54 -0
  241. package/test/index.test.ts +51 -0
  242. package/test/service-worker.test.ts +112 -0
  243. package/test/stealth/_results/_thumbs/headful-chrome-stealth.js.png +0 -0
  244. package/test/stealth/_results/_thumbs/headful-chrome-vanilla.js.png +0 -0
  245. package/test/stealth/_results/_thumbs/headful-chromium-stealth.js.png +0 -0
  246. package/test/stealth/_results/_thumbs/headful-chromium-vanilla.js.png +0 -0
  247. package/test/stealth/_results/_thumbs/headless-chrome-stealth.js.png +0 -0
  248. package/test/stealth/_results/_thumbs/headless-chrome-vanilla.js.png +0 -0
  249. package/test/stealth/_results/_thumbs/headless-chromium-stealth.js.png +0 -0
  250. package/test/stealth/_results/_thumbs/headless-chromium-vanilla.js.png +0 -0
  251. package/test/stealth/_results/headful-chrome-stealth.js.png +0 -0
  252. package/test/stealth/_results/headful-chrome-vanilla.js.png +0 -0
  253. package/test/stealth/_results/headful-chromium-stealth.js.png +0 -0
  254. package/test/stealth/_results/headful-chromium-vanilla.js.png +0 -0
  255. package/test/stealth/_results/headless-chrome-stealth.js.png +0 -0
  256. package/test/stealth/_results/headless-chrome-vanilla.js.png +0 -0
  257. package/test/stealth/_results/headless-chromium-stealth.js.png +0 -0
  258. package/test/stealth/_results/headless-chromium-vanilla.js.png +0 -0
  259. package/test/stealth/headful-chrome-stealth.js +25 -0
  260. package/test/stealth/headful-chrome-vanilla.js +23 -0
  261. package/test/stealth/headful-chromium-stealth.js +22 -0
  262. package/test/stealth/headful-chromium-vanilla.js +20 -0
  263. package/test/stealth/headless-chrome-stealth.js +25 -0
  264. package/test/stealth/headless-chrome-vanilla.js +23 -0
  265. package/test/stealth/headless-chromium-stealth.js +22 -0
  266. package/test/stealth/headless-chromium-vanilla.js +20 -0
  267. package/test/util.js +82 -0
  268. package/tsconfig.json +10 -0
  269. package/tsconfig.tsbuildinfo +1 -0
  270. package/vitest.config.ts +28 -0
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/evasions/user-agent-override/index.js"],"names":[],"mappings":""}
@@ -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 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/evasions/user-agent-override/index.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,MAAO,SAAQ,oBAAoB;IACvC,YAAY,IAAI,GAAG,EAAE;QACnB,KAAK,CAAC,IAAI,CAAC,CAAC;QAEZ,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACzB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,sCAAsC,CAAC;IAChD,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAI,GAAG,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,QAAQ;QACV,OAAO;YACL,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,IAAI;SAChB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,IAAI;QACtB,kEAAkE;QAClE,IAAI,EAAE,GACJ,IAAI,CAAC,IAAI,CAAC,SAAS;YACnB,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;QAE3E,IACE,IAAI,CAAC,IAAI,CAAC,SAAS;YACnB,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;YACpB,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,yDAAyD;UACjF,CAAC;YACD,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,+BAA+B,CAAC,CAAC,CAAC,0DAA0D;QAC7H,CAAC;QAED,kCAAkC;QAClC,MAAM,SAAS,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;YACtC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;YAClC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7D,kDAAkD;QAClD,MAAM,YAAY,GAAG,CAAC,QAAQ,GAAG,KAAK,EAAE,EAAE;YACxC,IAAI,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC5B,OAAO,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;YAC5C,CAAC;iBAAM,IAAI,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAClC,OAAO,SAAS,CAAC;YACnB,CAAC;iBAAM,IAAI,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAChC,OAAO,OAAO,CAAC;YACjB,CAAC;iBAAM,CAAC;gBACN,OAAO,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;YACxC,CAAC;QACH,CAAC,CAAC;QAEF,qIAAqI;QACrI,MAAM,UAAU,GAAG,GAAG,EAAE;YACtB,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,qCAAqC;YAE3E,MAAM,KAAK,GAAG;gBACZ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACT,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACT,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACT,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACT,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACT,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;aACV,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;YACZ,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YAErC,MAAM,YAAY,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAC5C,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CACvB,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAElC,MAAM,uBAAuB,GAAG,EAAE,CAAC;YACnC,uBAAuB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG;gBAClC,KAAK,EAAE,YAAY;gBACnB,OAAO,EAAE,IAAI;aACd,CAAC;YACF,uBAAuB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG;gBAClC,KAAK,EAAE,UAAU;gBACjB,OAAO,EAAE,IAAI;aACd,CAAC;YACF,uBAAuB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG;gBAClC,KAAK,EAAE,eAAe;gBACtB,OAAO,EAAE,IAAI;aACd,CAAC;YAEF,OAAO,uBAAuB,CAAC;QACjC,CAAC,CAAC;QAEF,oBAAoB;QACpB,MAAM,mBAAmB,GAAG,GAAG,EAAE;YAC/B,IAAI,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC7B,OAAO,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;YACzC,CAAC;iBAAM,IAAI,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBACnC,OAAO,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;YACxC,CAAC;iBAAM,IAAI,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBACnC,OAAO,EAAE,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/C,CAAC;iBAAM,CAAC;gBACN,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC;QAEF,wEAAwE;QACxE,MAAM,gBAAgB,GAAG,GAAG,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAE3D,6CAA6C;QAC7C,MAAM,iBAAiB,GAAG,GAAG,EAAE,CAC7B,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAE1D,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAEhD,MAAM,QAAQ,GAAG;YACf,SAAS,EAAE,EAAE;YACb,QAAQ,EAAE,YAAY,EAAE;YACxB,iBAAiB,EAAE;gBACjB,MAAM,EAAE,UAAU,EAAE;gBACpB,WAAW,EAAE,SAAS;gBACtB,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC;gBAC5B,eAAe,EAAE,mBAAmB,EAAE;gBACtC,YAAY,EAAE,gBAAgB,EAAE;gBAChC,KAAK,EAAE,iBAAiB,EAAE;gBAC1B,MAAM,EAAE,UAAU,EAAE;aACrB;SACF,CAAC;QAEF,2DAA2D;QAC3D,2DAA2D;QAC3D,mEAAmE;QACnE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,QAAQ,CAAC,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,UAAU,CAAC;QAC3D,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,mDAAmD,EAAE;YAC9D,QAAQ;YACR,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC,CAAC;QAEH,MAAM,MAAM,GACV,OAAO,IAAI,CAAC,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;QACrE,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE,QAAQ,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,OAAO;QACxB,6BAA6B;QAC7B,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,sDAAsD;QACtD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,IAAI,IAAI;QACN,OAAO;YACL;gBACE,IAAI,EAAE,iBAAiB;gBACvB,KAAK,EAAE;oBACL,IAAI,EAAE,EAAE,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,UAAU,EAAE;iBAC3D;aACF;SACF,CAAC;IACJ,CAAC;CACF;AAED,MAAM,aAAa,GAAG,IAAI,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;AAC/C,MAAM,CAAC,OAAO,GAAG,aAAa,CAAC"}
@@ -0,0 +1,5 @@
1
+ {
2
+ "private": true,
3
+ "type": "module",
4
+ "main": "index.js"
5
+ }
@@ -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,17 @@
1
+ export default function _default(pluginConfig: any): Plugin;
2
+ /**
3
+ * Fix WebGL Vendor/Renderer being set to Google in headless mode
4
+ *
5
+ * Example data (Apple Retina MBP 13): {vendor: "Intel Inc.", renderer: "Intel(R) Iris(TM) Graphics 6100"}
6
+ *
7
+ * @param {Object} [opts] - Options
8
+ * @param {string} [opts.vendor] - The vendor string to use (default: `Intel Inc.`)
9
+ * @param {string} [opts.renderer] - The renderer string (default: `Intel Iris OpenGL Engine`)
10
+ */
11
+ declare class Plugin extends PuppeteerExtraPlugin {
12
+ constructor(opts?: {});
13
+ onPageCreated(page: any): Promise<void>;
14
+ }
15
+ import { PuppeteerExtraPlugin } from '@zorilla/puppeteer-extra-plugin';
16
+ export {};
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/evasions/webgl.vendor/index.js"],"names":[],"mappings":"AAsDA,4DAEC;AApDD;;;;;;;;GAQG;AACH;IACE,uBAEC;IAOD,wCA4BC;CACF;qCApDoC,iCAAiC"}
@@ -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 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/evasions/webgl.vendor/index.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAEvE,OAAO,SAAS,MAAM,wBAAwB,CAAC;AAE/C;;;;;;;;GAQG;AACH,MAAM,MAAO,SAAQ,oBAAoB;IACvC,YAAY,IAAI,GAAG,EAAE;QACnB,KAAK,CAAC,IAAI,CAAC,CAAC;IACd,CAAC;IAED,IAAI,IAAI;QACN,OAAO,+BAA+B,CAAC;IACzC,CAAC;IAED,yDAAyD;IACzD,KAAK,CAAC,aAAa,CAAC,IAAI;QACtB,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC,qBAAqB,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YAC1D,MAAM,wBAAwB,GAAG;gBAC/B,KAAK,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;oBAC3B,MAAM,KAAK,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC9B,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;oBAC5D,wBAAwB;oBACxB,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;wBACpB,OAAO,IAAI,CAAC,MAAM,IAAI,YAAY,CAAC,CAAC,mCAAmC;oBACzE,CAAC;oBACD,0BAA0B;oBAC1B,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;wBACpB,OAAO,IAAI,CAAC,QAAQ,IAAI,0BAA0B,CAAC,CAAC,0CAA0C;oBAChG,CAAC;oBACD,OAAO,MAAM,CAAC;gBAChB,CAAC;aACF,CAAC;YAEF,gDAAgD;YAChD,gGAAgG;YAChG,uHAAuH;YACvH,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE;gBACjC,KAAK,CAAC,gBAAgB,CAAC,GAAG,EAAE,QAAQ,EAAE,wBAAwB,CAAC,CAAC;YAClE,CAAC,CAAC;YACF,0GAA0G;YAC1G,QAAQ,CAAC,qBAAqB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;YAC1D,QAAQ,CAAC,sBAAsB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;QAC7D,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;CACF;AAED,MAAM,CAAC,OAAO,WAAW,YAAY;IACnC,OAAO,IAAI,MAAM,CAAC,YAAY,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,5 @@
1
+ {
2
+ "private": true,
3
+ "type": "module",
4
+ "main": "index.js"
5
+ }
@@ -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
+ ---
@@ -0,0 +1,13 @@
1
+ export default function _default(pluginConfig: any): Plugin;
2
+ /**
3
+ * Fix missing window.outerWidth/window.outerHeight in headless mode
4
+ * Will also set the viewport to match window size, unless specified by user
5
+ */
6
+ declare class Plugin extends PuppeteerExtraPlugin {
7
+ constructor(opts?: {});
8
+ onPageCreated(page: any): Promise<void>;
9
+ beforeLaunch(options: any): Promise<any>;
10
+ }
11
+ import { PuppeteerExtraPlugin } from '@zorilla/puppeteer-extra-plugin';
12
+ export {};
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/evasions/window.outerdimensions/index.js"],"names":[],"mappings":"AAuCA,4DAEC;AAvCD;;;GAGG;AACH;IACE,uBAEC;IAMD,wCAYC;IAED,yCAOC;CACF;qCArCoC,iCAAiC"}
@@ -0,0 +1,42 @@
1
+ import { PuppeteerExtraPlugin } from '@zorilla/puppeteer-extra-plugin';
2
+
3
+ /**
4
+ * Fix missing window.outerWidth/window.outerHeight in headless mode
5
+ * Will also set the viewport to match window size, unless specified by user
6
+ */
7
+ class Plugin extends PuppeteerExtraPlugin {
8
+ constructor(opts = {}) {
9
+ super(opts);
10
+ }
11
+
12
+ get name() {
13
+ return 'stealth/evasions/window.outerdimensions';
14
+ }
15
+
16
+ async onPageCreated(page) {
17
+ // Chrome returns undefined, Firefox false
18
+ await page.evaluateOnNewDocument(() => {
19
+ try {
20
+ if (window.outerWidth && window.outerHeight) {
21
+ return; // nothing to do here
22
+ }
23
+ const windowFrame = 85; // probably OS and WM dependent
24
+ window.outerWidth = window.innerWidth;
25
+ window.outerHeight = window.innerHeight + windowFrame;
26
+ } catch (_err) {}
27
+ });
28
+ }
29
+
30
+ async beforeLaunch(options) {
31
+ // Have viewport match window size, unless specified by user
32
+ // https://github.com/GoogleChrome/puppeteer/issues/3688
33
+ if (!('defaultViewport' in options)) {
34
+ options.defaultViewport = null;
35
+ }
36
+ return options;
37
+ }
38
+ }
39
+
40
+ export default function (pluginConfig) {
41
+ return new Plugin(pluginConfig);
42
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/evasions/window.outerdimensions/index.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAEvE;;;GAGG;AACH,MAAM,MAAO,SAAQ,oBAAoB;IACvC,YAAY,IAAI,GAAG,EAAE;QACnB,KAAK,CAAC,IAAI,CAAC,CAAC;IACd,CAAC;IAED,IAAI,IAAI;QACN,OAAO,yCAAyC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,IAAI;QACtB,0CAA0C;QAC1C,MAAM,IAAI,CAAC,qBAAqB,CAAC,GAAG,EAAE;YACpC,IAAI,CAAC;gBACH,IAAI,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;oBAC5C,OAAO,CAAC,qBAAqB;gBAC/B,CAAC;gBACD,MAAM,WAAW,GAAG,EAAE,CAAC,CAAC,+BAA+B;gBACvD,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;gBACtC,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,GAAG,WAAW,CAAC;YACxD,CAAC;YAAC,OAAO,IAAI,EAAE,CAAC,CAAA,CAAC;QACnB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,OAAO;QACxB,4DAA4D;QAC5D,wDAAwD;QACxD,IAAI,CAAC,CAAC,iBAAiB,IAAI,OAAO,CAAC,EAAE,CAAC;YACpC,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;QACjC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAED,MAAM,CAAC,OAAO,WAAW,YAAY;IACnC,OAAO,IAAI,MAAM,CAAC,YAAY,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,5 @@
1
+ {
2
+ "private": true,
3
+ "type": "module",
4
+ "main": "index.js"
5
+ }
@@ -0,0 +1,130 @@
1
+ import { PuppeteerExtraPlugin } from '@zorilla/puppeteer-extra-plugin';
2
+ import type * as Puppeteer from '@zorilla/puppeteer-extra-plugin/dist/puppeteer';
3
+ interface PluginOptions {
4
+ enabledEvasions?: Set<string>;
5
+ availableEvasions?: Set<string>;
6
+ [key: string]: unknown;
7
+ }
8
+ interface BrowserOptions {
9
+ [key: string]: unknown;
10
+ }
11
+ /**
12
+ * Stealth mode: Applies various techniques to make detection of headless puppeteer harder. 💯
13
+ *
14
+ * ### Purpose
15
+ * There are a couple of ways the use of puppeteer can easily be detected by a target website.
16
+ * The addition of `HeadlessChrome` to the user-agent being only the most obvious one.
17
+ *
18
+ * The goal of this plugin is to be the definite companion to puppeteer to avoid
19
+ * detection, applying new techniques as they surface.
20
+ *
21
+ * As this cat & mouse game is in it's infancy and fast-paced the plugin
22
+ * is kept as flexibile as possible, to support quick testing and iterations.
23
+ *
24
+ * ### Modularity
25
+ * This plugin uses `puppeteer-extra`'s dependency system to only require
26
+ * code mods for evasions that have been enabled, to keep things modular and efficient.
27
+ *
28
+ * The `stealth` plugin is a convenience wrapper that requires multiple [evasion techniques](./evasions/)
29
+ * automatically and comes with defaults. You could also bypass the main module and require
30
+ * specific evasion plugins yourself, if you whish to do so (as they're standalone `puppeteer-extra` plugins):
31
+ *
32
+ * ```es6
33
+ * // bypass main module and require a specific stealth plugin directly:
34
+ * puppeteer.use(require('@zorilla/puppeteer-extra-plugin-stealth/evasions/console.debug')())
35
+ * ```
36
+ *
37
+ * ### Contributing
38
+ * PRs are welcome, if you want to add a new evasion technique I suggest you
39
+ * look at the [template](./evasions/_template) to kickstart things.
40
+ *
41
+ * ### Kudos
42
+ * Thanks to [Evan Sangaline](https://intoli.com/blog/not-possible-to-block-chrome-headless/) and [Paul Irish](https://github.com/paulirish/headless-cat-n-mouse) for kickstarting the discussion!
43
+ *
44
+ * ---
45
+ *
46
+ * @todo
47
+ * - white-/blacklist with url globs (make this a generic plugin method?)
48
+ * - dynamic whitelist based on function evaluation
49
+ *
50
+ * @example
51
+ * const puppeteer = require('@zorilla/puppeteer-extra')
52
+ * // Enable stealth plugin with all evasions
53
+ * puppeteer.use(require('@zorilla/puppeteer-extra-plugin-stealth')())
54
+ *
55
+ *
56
+ * ;(async () => {
57
+ * // Launch the browser in headless mode and set up a page.
58
+ * const browser = await puppeteer.launch({ args: ['--no-sandbox'], headless: true })
59
+ * const page = await browser.newPage()
60
+ *
61
+ * // Navigate to the page that will perform the tests.
62
+ * const testUrl = 'https://intoli.com/blog/' +
63
+ * 'not-possible-to-block-chrome-headless/chrome-headless-test.html'
64
+ * await page.goto(testUrl)
65
+ *
66
+ * // Save a screenshot of the results.
67
+ * const screenshotPath = '/tmp/headless-test-result.png'
68
+ * await page.screenshot({path: screenshotPath})
69
+ * console.log('have a look at the screenshot:', screenshotPath)
70
+ *
71
+ * await browser.close()
72
+ * })()
73
+ *
74
+ * @param {Object} [opts] - Options
75
+ * @param {Set<string>} [opts.enabledEvasions] - Specify which evasions to use (by default all)
76
+ *
77
+ */
78
+ declare class StealthPlugin extends PuppeteerExtraPlugin {
79
+ constructor(opts?: PluginOptions);
80
+ get name(): string;
81
+ get defaults(): Required<PluginOptions>;
82
+ /**
83
+ * Requires evasion techniques dynamically based on configuration.
84
+ *
85
+ * @private
86
+ */
87
+ get dependencies(): Set<string>;
88
+ /**
89
+ * Get all available evasions.
90
+ *
91
+ * Please look into the [evasions directory](./evasions/) for an up to date list.
92
+ *
93
+ * @type {Set<string>} - A Set of all available evasions.
94
+ *
95
+ * @example
96
+ * const pluginStealth = require('@zorilla/puppeteer-extra-plugin-stealth')()
97
+ * console.log(pluginStealth.availableEvasions) // => Set { 'user-agent', 'console.debug' }
98
+ * puppeteer.use(pluginStealth)
99
+ */
100
+ get availableEvasions(): Set<string>;
101
+ /**
102
+ * Get all enabled evasions.
103
+ *
104
+ * Enabled evasions can be configured either through `opts` or by modifying this property.
105
+ *
106
+ * @type {Set<string>} - A Set of all enabled evasions.
107
+ *
108
+ * @example
109
+ * // Remove specific evasion from enabled ones dynamically
110
+ * const pluginStealth = require('@zorilla/puppeteer-extra-plugin-stealth')()
111
+ * pluginStealth.enabledEvasions.delete('console.debug')
112
+ * puppeteer.use(pluginStealth)
113
+ */
114
+ get enabledEvasions(): Set<string>;
115
+ /**
116
+ * @private
117
+ */
118
+ set enabledEvasions(evasions: Set<string>);
119
+ onBrowser(browser: Puppeteer.Browser, _opts: BrowserOptions): Promise<void>;
120
+ }
121
+ /**
122
+ * Default export, PuppeteerExtraStealthPlugin
123
+ *
124
+ * @param {Object} [opts] - Options
125
+ * @param {Set<string>} [opts.enabledEvasions] - Specify which evasions to use (by default all)
126
+ */
127
+ declare const _default: (opts?: PluginOptions) => StealthPlugin;
128
+ export default _default;
129
+ export { StealthPlugin };
130
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,KAAK,SAAS,MAAM,gDAAgD,CAAC;AAEjF,UAAU,aAAa;IACrB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,UAAU,cAAc;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH,cAAM,aAAc,SAAQ,oBAAoB;gBAClC,IAAI,GAAE,aAAkB;IAIpC,IAAa,IAAI,IAAI,MAAM,CAE1B;IAED,IAAa,QAAQ,IAAI,QAAQ,CAAC,aAAa,CAAC,CAwB/C;IAED;;;;OAIG;IACH,IAAa,YAAY,IAAI,GAAG,CAAC,MAAM,CAAC,CAGvC;IAED;;;;;;;;;;;OAWG;IACH,IAAI,iBAAiB,IAAI,GAAG,CAAC,MAAM,CAAC,CAEnC;IAED;;;;;;;;;;;;OAYG;IACH,IAAI,eAAe,IAAI,GAAG,CAAC,MAAM,CAAC,CAEjC;IAED;;OAEG;IACH,IAAI,eAAe,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,EAExC;IAEc,SAAS,CACtB,OAAO,EAAE,SAAS,CAAC,OAAO,EAC1B,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,IAAI,CAAC;CAOjB;AAED;;;;;GAKG;yBACa,OAAO,aAAa,KAAG,aAAa;AAApD,wBAAgF;AAGhF,OAAO,EAAE,aAAa,EAAE,CAAC"}