@@ -14,15 +14,30 @@ dotnet add package ManagedCode.Playwright.Stealth
1414using Microsoft .Playwright ;
1515using ManagedCode .Playwright .Stealth ;
1616
17+ using var playwright = await Playwright .CreateAsync ();
18+
19+ // One-call launch with stealth args + context pre-configured:
20+ var (browser , context ) = await playwright .Chromium .LaunchStealthAsync ();
21+
22+ var page = await context .NewPageAsync ();
23+ await page .GotoAsync (" https://www.browserscan.net/bot-detection" );
24+ ```
25+
26+ ## Manual Setup
27+
28+ If you need more control over launch options:
29+
30+ ``` csharp
1731using var playwright = await Playwright .CreateAsync ();
1832await using var browser = await playwright .Chromium .LaunchAsync (new BrowserTypeLaunchOptions
1933{
20- Headless = true
34+ Headless = true ,
35+ Args = PlaywrightStealthExtensions .StealthArgs // recommended Chrome flags
2136 });
2237
2338var context = await browser .NewContextAsync ();
2439
25- // Apply ManagedCode.Playwright.Stealth before creating pages.
40+ // Apply stealth before creating pages.
2641await context .ApplyStealthAsync ();
2742
2843var page = await context .NewPageAsync ();
@@ -35,25 +50,21 @@ await page.GotoAsync("https://www.browserscan.net/bot-detection");
3550var config = new StealthConfig
3651{
3752 NavigatorHardwareConcurrency = 8 ,
38- NavigatorLanguages = true ,
53+ NavigatorDeviceMemory = 16 ,
54+ NavigatorMaxTouchPoints = 1 ,
3955 NavigatorUserAgentValue = " Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" ,
40- WebglVendor = true
56+ Vendor = " Intel Inc." ,
57+ Renderer = " Intel Iris OpenGL Engine"
4158};
4259
43- // Apply ManagedCode.Playwright.Stealth with a custom config.
4460await context .ApplyStealthAsync (config );
4561```
4662
47- ## Usage Variants (C#/.NET)
48-
4963Apply stealth on a page (if you already have a page instance):
5064
5165``` csharp
5266var page = await context .NewPageAsync ();
53-
54- // Apply ManagedCode.Playwright.Stealth to an existing page.
5567await page .ApplyStealthAsync ();
56-
5768await page .GotoAsync (" https://www.browserscan.net/bot-detection" );
5869```
5970
@@ -64,82 +75,140 @@ var config = new StealthConfig
6475{
6576 WebDriver = false ,
6677 WebglVendor = false ,
67- NavigatorLanguages = false ,
68- NavigatorPlugins = false ,
69- ChromeRuntime = false
78+ CanvasFingerprint = false ,
79+ AudioContext = false ,
80+ PerformanceJitter = false
7081};
7182
72- // Apply ManagedCode.Playwright.Stealth with selective patches disabled.
7383await context .ApplyStealthAsync (config );
7484```
7585
76- Customize platform, vendor, and WebGL identity:
86+ ## Patched Signals
87+
88+ The default configuration patches ** 31 detection vectors** across these categories:
89+
90+ ### Navigator Properties
91+ | Patch | Description | Config |
92+ | -------| -------------| --------|
93+ | ` navigator.webdriver ` | Returns ` false ` instead of ` true ` | ` WebDriver ` |
94+ | ` navigator.plugins ` / ` mimeTypes ` | Fake plugin array (Chrome PDF Plugin, etc.) | ` NavigatorPlugins ` |
95+ | ` navigator.languages ` | Configurable language array | ` NavigatorLanguages ` |
96+ | ` navigator.userAgent ` | Strips headless markers from UA string | ` NavigatorUserAgent ` |
97+ | ` navigator.vendor ` | Returns "Google Inc." | ` NavigatorVendor ` |
98+ | ` navigator.platform ` | Configurable platform string | ` NavigatorPlatform ` |
99+ | ` navigator.hardwareConcurrency ` | Configurable CPU core count (default: 4) | ` NavigatorHardwareConcurrency ` |
100+ | ` navigator.deviceMemory ` | Configurable device memory in GB (default: 8) | ` NavigatorDeviceMemory ` |
101+ | ` navigator.connection ` | Full NetworkInformation API mock (4g, 10 Mbps) | ` NavigatorConnection ` |
102+ | ` navigator.permissions ` | Normalizes Notification permission state | ` NavigatorPermissions ` |
103+ | ` navigator.maxTouchPoints ` | Configurable touch point count (default: 1) | ` NavigatorMaxTouchPoints ` |
104+ | ` navigator.pdfViewerEnabled ` | Returns ` true ` | ` NavigatorPdfViewer ` |
105+
106+ ### Chrome APIs
107+ | Patch | Description | Config |
108+ | -------| -------------| --------|
109+ | ` window.chrome ` / ` chrome.runtime ` | Full Chrome extension API mock | ` ChromeRuntime ` |
110+ | ` chrome.app ` | Chrome App API mock | ` ChromeApp ` |
111+ | ` chrome.csi ` | Chrome CSI timing mock | ` ChromeCsi ` |
112+ | ` chrome.loadTimes ` | Chrome load times mock | ` ChromeLoadTimes ` |
113+
114+ ### Graphics & Rendering
115+ | Patch | Description | Config |
116+ | -------| -------------| --------|
117+ | WebGL vendor/renderer | Spoofs UNMASKED and standard WebGL params; hides ANGLE/SwiftShader | ` WebglVendor ` |
118+ | Canvas fingerprint | Adds session-stable noise to canvas rendering | ` CanvasFingerprint ` |
119+ | Broken image dimensions | Fixes 16x16 headless artifact to 0x0 | ` BrokenImage ` |
120+
121+ ### Audio & Media
122+ | Patch | Description | Config |
123+ | -------| -------------| --------|
124+ | AudioContext fingerprint | Adds noise to audio frequency/channel data | ` AudioContext ` |
125+ | Media codecs | Correct codec support responses | ` MediaCodecs ` |
126+ | Speech synthesis | Mock voice list for ` getVoices() ` | ` SpeechSynthesis ` |
127+
128+ ### Window & Screen
129+ | Patch | Description | Config |
130+ | -------| -------------| --------|
131+ | ` window.outerWidth/Height ` | Realistic outer dimensions | ` OuterDimensions ` |
132+ | ` screen.* ` dimensions | Consistent screen width/height/colorDepth | ` ScreenDimensions ` |
133+
134+ ### Anti-Detection & Timing
135+ | Patch | Description | Config |
136+ | -------| -------------| --------|
137+ | CDP detection | Masks Chrome DevTools Protocol traces | ` CdpDetection ` |
138+ | Automation properties | Removes ` cdc_* ` , ` $cdc_* ` , ` domAutomationController ` | ` AutomationProperties ` |
139+ | Performance jitter | Adds realistic timing noise to ` performance.now() ` and ` requestAnimationFrame ` | ` PerformanceJitter ` |
140+
141+ ### DOM & Internals
142+ | Patch | Description | Config |
143+ | -------| -------------| --------|
144+ | iframe ` contentWindow ` | Fixes iframe proxy behavior | ` IframeContentWindow ` |
145+ | Hairline detection | Fixes Modernizr ` offsetHeight ` check | ` Hairline ` |
146+
147+ ## Public API
148+
149+ ### Extension Methods
77150
78151``` csharp
79- var config = new StealthConfig
80- {
81- NavigatorPlatformValue = " Win32" ,
82- NavigatorVendorValue = " Google Inc." ,
83- NavigatorUserAgentValue = " Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" ,
84- Vendor = " Intel Inc." ,
85- Renderer = " Intel Iris OpenGL Engine" ,
86- Languages = new [] { " en-US" , " en" },
87- NavigatorHardwareConcurrency = 8
88- };
152+ // Apply to browser context (recommended)
153+ await context .ApplyStealthAsync ();
154+ await context .ApplyStealthAsync (customConfig );
89155
90- // Apply ManagedCode.Playwright.Stealth with explicit platform and WebGL identity.
91- await context .ApplyStealthAsync (config );
156+ // Apply to individual page
157+ await page .ApplyStealthAsync ();
158+ await page .ApplyStealthAsync (customConfig );
159+
160+ // One-call launch with stealth pre-configured
161+ var (browser , context ) = await playwright .Chromium .LaunchStealthAsync ();
162+ var (browser , context ) = await playwright .Chromium .LaunchStealthAsync (config , launchOptions , contextOptions );
92163```
93164
94- Run on insecure origins (affects ` chrome.runtime ` behavior):
165+ ### Stealth Chrome Arguments
95166
96167``` csharp
97- var config = new StealthConfig
98- {
99- RunOnInsecureOrigins = true
100- };
101-
102- // Apply ManagedCode.Playwright.Stealth on insecure origins.
103- await context .ApplyStealthAsync (config );
168+ // Access recommended Chrome args for manual launch setup
169+ string [] args = PlaywrightStealthExtensions .StealthArgs ;
104170```
105171
106- ## Patched Signals
172+ ## Configuration Reference
107173
108- The default configuration applies patches for:
109-
110- - ` navigator.webdriver `
111- - ` navigator.plugins ` and ` navigator.mimeTypes `
112- - ` navigator.languages `
113- - ` navigator.userAgent `
114- - ` navigator.vendor `
115- - ` navigator.platform `
116- - ` navigator.hardwareConcurrency `
117- - ` window.chrome ` / ` chrome.runtime ` / related Chrome APIs
118- - WebGL vendor/renderer
119- - ` window.outerWidth ` / ` window.outerHeight `
120- - media codecs and hairline fixes
121- - iframe ` contentWindow ` quirks
174+ ### Toggle Options (bool)
122175
123- ## Configuration Reference
176+ ` WebDriver ` , ` WebglVendor ` , ` ChromeApp ` , ` ChromeCsi ` , ` ChromeLoadTimes ` , ` ChromeRuntime ` ,
177+ ` IframeContentWindow ` , ` MediaCodecs ` , ` Hairline ` , ` OuterDimensions ` ,
178+ ` NavigatorLanguages ` , ` NavigatorPermissions ` , ` NavigatorPlatform ` , ` NavigatorPlugins ` ,
179+ ` NavigatorUserAgent ` , ` NavigatorVendor ` , ` NavigatorConnection ` , ` NavigatorPdfViewer ` ,
180+ ` BrokenImage ` , ` SpeechSynthesis ` , ` ScreenDimensions ` ,
181+ ` CdpDetection ` , ` AutomationProperties ` , ` CanvasFingerprint ` , ` PerformanceJitter ` , ` AudioContext `
182+
183+ ### Numeric Options (int)
184+
185+ - ` NavigatorHardwareConcurrency ` (default: 4, set 0 to disable)
186+ - ` NavigatorDeviceMemory ` (default: 8, set 0 to disable)
187+ - ` NavigatorMaxTouchPoints ` (default: 1, set -1 to disable)
124188
125- Common options in ` StealthConfig ` :
189+ ### String Options
126190
127- - ` WebDriver ` , ` WebglVendor ` , ` ChromeApp ` , ` ChromeCsi ` , ` ChromeLoadTimes ` , ` ChromeRuntime `
128- - ` IframeContentWindow ` , ` MediaCodecs ` , ` Hairline ` , ` OuterDimensions `
129- - ` NavigatorLanguages ` , ` NavigatorPermissions ` , ` NavigatorPlatform ` , ` NavigatorPlugins ` , ` NavigatorUserAgent ` , ` NavigatorVendor `
130- - ` NavigatorHardwareConcurrency ` , ` NavigatorUserAgentValue ` , ` NavigatorPlatformValue ` , ` NavigatorVendorValue `
131- - ` Vendor ` , ` Renderer ` , ` Languages ` , ` RunOnInsecureOrigins `
191+ - ` NavigatorUserAgentValue ` - Custom user agent string
192+ - ` NavigatorPlatformValue ` - Custom platform (e.g., "Win32")
193+ - ` NavigatorVendorValue ` - Vendor name (default: "Google Inc.")
194+ - ` Vendor ` - WebGL vendor (default: "Intel Inc.")
195+ - ` Renderer ` - WebGL renderer (default: "Intel Iris OpenGL Engine")
196+ - ` Languages ` - Language array (default: ` ["en-US", "en"] ` )
197+ - ` RunOnInsecureOrigins ` - Allow stealth on http:// origins
132198
133199## Testing
134200
135- Integration tests target these bot-detection sites:
201+ Integration tests target ** 9 bot-detection sites** :
136202
137203- https://www.browserscan.net/bot-detection
138204- https://bot.sannysoft.com/
139205- https://www.intoli.com/blog/not-possible-to-block-chrome-headless/chrome-headless-test.html
140206- https://fingerprint.com/demo
141207- https://arh.antoinevastel.com/bots/areyouheadless/
142208- https://pixelscan.net/bot-check
209+ - https://bot.incolumitas.com/
210+ - https://abrahamjuliot.github.io/creepjs/
211+ - https://deviceandbrowserinfo.com/info_device
143212
144213These sites can change at any time. If a site changes, update the corresponding test assertions.
145214
0 commit comments