0
# Navigator Evasions
1
2
Evasion techniques that modify navigator properties to hide headless browser indicators. These techniques fix various navigator object properties that can reveal automation and make the browser appear more like a regular user's browser.
3
4
## Capabilities
5
6
### Navigator WebDriver Evasion
7
8
Removes or fixes the `navigator.webdriver` property that explicitly indicates automation.
9
10
```javascript { .api }
11
// Evasion name: 'navigator.webdriver'
12
// Fixes: navigator.webdriver property detection
13
// Launch args: Adds --disable-blink-features=AutomationControlled
14
```
15
16
This evasion:
17
- Deletes the `navigator.webdriver` property in older Chrome versions
18
- Handles different Chrome version behaviors (pre/post Chrome 88 and 89)
19
- Adds `--disable-blink-features=AutomationControlled` launch argument
20
- Prevents the most common automation detection method
21
22
**Detection Method Prevented:**
23
```javascript
24
// This detection method will be fooled:
25
if (navigator.webdriver) {
26
// Detects automation - webdriver property exists
27
} else {
28
// Assumes regular browser
29
}
30
```
31
32
### Navigator Languages Evasion
33
34
Fixes the `navigator.languages` array to match the Accept-Language header.
35
36
```javascript { .api }
37
// Evasion name: 'navigator.languages'
38
// Fixes: Inconsistency between navigator.languages and Accept-Language header
39
```
40
41
This evasion:
42
- Ensures `navigator.languages` matches the Accept-Language header
43
- Provides consistent language reporting across different browser APIs
44
- Prevents detection through language inconsistencies
45
46
**Detection Method Prevented:**
47
```javascript
48
// This detection method will be fooled:
49
const languages = navigator.languages;
50
const acceptLanguage = /* from HTTP headers */;
51
if (languages.join(',') !== acceptLanguage) {
52
// Detects inconsistency indicating automation
53
}
54
```
55
56
### Navigator Hardware Concurrency Evasion
57
58
Fixes hardware concurrency reporting to match typical user systems.
59
60
```javascript { .api }
61
// Evasion name: 'navigator.hardwareConcurrency'
62
// Fixes: navigator.hardwareConcurrency to report realistic CPU core count
63
```
64
65
This evasion:
66
- Reports a realistic number of CPU cores
67
- Prevents detection through unusual hardware concurrency values
68
- Matches typical desktop/laptop configurations
69
70
**Detection Method Prevented:**
71
```javascript
72
// This detection method will be fooled:
73
if (navigator.hardwareConcurrency === 1 || navigator.hardwareConcurrency > 16) {
74
// Detects unusual hardware suggesting automation environment
75
}
76
```
77
78
### Navigator Permissions Evasion
79
80
Fixes permission API behavior, particularly for notifications.
81
82
```javascript { .api }
83
// Evasion name: 'navigator.permissions'
84
// Fixes: Notification.permission and navigator.permissions.query() behavior
85
```
86
87
This evasion:
88
- Fixes `Notification.permission` behavior in headless mode
89
- Ensures `navigator.permissions.query()` returns expected results
90
- Addresses Chromium bug with notification permissions in headless mode
91
92
**Detection Method Prevented:**
93
```javascript
94
// This detection method will be fooled:
95
navigator.permissions.query({name: 'notifications'}).then(result => {
96
if (result.state !== Notification.permission) {
97
// Detects permission API inconsistency
98
}
99
});
100
```
101
102
### Navigator Plugins Evasion
103
104
Mocks browser plugins to simulate a regular browser environment.
105
106
```javascript { .api }
107
// Evasion name: 'navigator.plugins'
108
// Fixes: Empty navigator.plugins array in headless mode
109
```
110
111
This evasion:
112
- Creates realistic `navigator.plugins` array with common plugins
113
- Includes typical plugins like Chrome PDF Viewer, Flash, etc.
114
- Provides proper plugin objects with realistic properties
115
- Implements plugin detection methods used by websites
116
117
**Detection Method Prevented:**
118
```javascript
119
// This detection method will be fooled:
120
if (navigator.plugins.length === 0) {
121
// Detects headless browser with no plugins
122
} else {
123
// Assumes regular browser with plugins
124
}
125
```
126
127
### Navigator Vendor Evasion
128
129
Allows customization of the `navigator.vendor` property which is fixed in Puppeteer by default.
130
131
```javascript { .api }
132
/**
133
* Navigator vendor evasion plugin
134
* @param opts - Configuration options
135
* @param opts.vendor - The vendor string to use (default: 'Google Inc.')
136
* @returns Plugin instance
137
*/
138
function NavigatorVendorPlugin(opts?: {
139
vendor?: string;
140
}): Plugin;
141
142
// Evasion name: 'navigator.vendor'
143
// Fixes: Fixed navigator.vendor property in headless mode
144
// Configuration: Accepts custom vendor string
145
```
146
147
This evasion:
148
- Overrides the fixed `navigator.vendor` property
149
- Allows setting custom vendor string (default: 'Google Inc.')
150
- Uses stealth utilities to replace the property undetectably
151
- Can be used to mimic different browser vendors
152
153
**Configuration Options:**
154
```javascript
155
// Use default vendor (Google Inc.)
156
const vendorPlugin = NavigatorVendorPlugin();
157
158
// Use custom vendor
159
const appleVendor = NavigatorVendorPlugin({
160
vendor: 'Apple Computer, Inc.'
161
});
162
```
163
164
**Detection Method Prevented:**
165
```javascript
166
// This detection method will be fooled:
167
if (navigator.vendor === 'Google Inc.' && /* other headless indicators */) {
168
// Might detect specific headless patterns
169
} else {
170
// Custom vendor helps avoid detection patterns
171
}
172
```
173
174
**Usage Examples:**
175
176
```javascript
177
const puppeteer = require('puppeteer-extra');
178
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
179
180
// Enable only navigator-related evasions
181
const navigatorStealth = StealthPlugin({
182
enabledEvasions: new Set([
183
'navigator.webdriver',
184
'navigator.languages',
185
'navigator.hardwareConcurrency',
186
'navigator.permissions',
187
'navigator.plugins',
188
'navigator.vendor'
189
])
190
});
191
192
puppeteer.use(navigatorStealth);
193
194
const browser = await puppeteer.launch();
195
const page = await browser.newPage();
196
197
// Navigator properties will now appear normal
198
await page.evaluate(() => {
199
console.log(navigator.webdriver); // undefined (not true)
200
console.log(navigator.languages); // ['en-US', 'en']
201
console.log(navigator.hardwareConcurrency); // 4 (realistic number)
202
console.log(navigator.plugins.length); // > 0 (has plugins)
203
console.log(navigator.vendor); // 'Google Inc.' (customizable)
204
205
// Permissions work normally
206
return navigator.permissions.query({name: 'notifications'});
207
});
208
```
209
210
## Configuration Interaction
211
212
Navigator evasions work together with other plugin components:
213
214
### User Agent Override Integration
215
216
The `navigator.languages` evasion coordinates with `user-agent-override` to ensure:
217
- Accept-Language header matches navigator.languages
218
- User agent string is consistent with reported languages
219
- Platform information aligns across different APIs
220
221
### Launch Arguments
222
223
The `navigator.webdriver` evasion adds launch arguments:
224
- `--disable-blink-features=AutomationControlled`
225
- May add Chrome policy warning (can be disabled with system policies)
226
227
## Implementation Details
228
229
Each navigator evasion:
230
231
1. **Runtime Injection**: Uses `page.evaluateOnNewDocument()` for immediate execution
232
2. **Property Modification**: Uses stealth utilities to modify properties undetectably
233
3. **Cross-Frame Support**: Works across iframes and new windows
234
4. **Version Compatibility**: Handles different Chrome/Chromium versions appropriately
235
5. **Realistic Data**: Provides believable values that match real user environments
236
237
## Browser Compatibility
238
239
Navigator evasions are designed for:
240
- **Chrome/Chromium**: Primary target with version-specific handling
241
- **Puppeteer**: Full compatibility with all Puppeteer versions
242
- **Playwright**: Compatible with playwright-extra
243
- **Cross-Platform**: Works on Windows, macOS, and Linux
244
245
## Advanced Usage
246
247
### Custom Plugin Configuration
248
249
```javascript
250
// Enable specific navigator evasions with custom values
251
const customNavigator = StealthPlugin({
252
enabledEvasions: new Set(['navigator.webdriver', 'navigator.plugins', 'navigator.vendor'])
253
});
254
255
// For individual evasion plugins with custom options:
256
const customVendor = require('puppeteer-extra-plugin-stealth/evasions/navigator.vendor');
257
puppeteer.use(customVendor({ vendor: 'Apple Computer, Inc.' }));
258
```
259
260
### Debugging Navigator Properties
261
262
```javascript
263
// Check which navigator properties are being modified
264
await page.evaluate(() => {
265
const props = [
266
'webdriver', 'languages', 'hardwareConcurrency',
267
'permissions', 'plugins', 'vendor'
268
];
269
270
return props.map(prop => ({
271
property: prop,
272
value: navigator[prop],
273
type: typeof navigator[prop]
274
}));
275
});
276
```