0
# Window and Frame Evasions
1
2
Evasion techniques that fix window dimension and iframe-related detection methods. These evasions address inconsistencies in window properties and iframe behavior that can reveal headless browser automation.
3
4
## Capabilities
5
6
### Window Outer Dimensions Evasion
7
8
Fixes missing `window.outerWidth` and `window.outerHeight` properties in headless mode.
9
10
```javascript { .api }
11
// Evasion name: 'window.outerdimensions'
12
// Fixes: window.outerWidth, window.outerHeight, and viewport consistency
13
```
14
15
This evasion:
16
- Sets realistic `window.outerWidth` and `window.outerHeight` values in headless mode
17
- Ensures outer dimensions are larger than inner dimensions (like real browsers)
18
- Automatically adjusts viewport to match window dimensions unless specified by user
19
- Prevents detection through missing or inconsistent window dimension properties
20
21
**Detection Method Prevented:**
22
```javascript
23
// This detection method will be fooled:
24
if (window.outerWidth === 0 || window.outerHeight === 0) {
25
// Would detect headless mode (missing outer dimensions)
26
} else if (window.outerWidth <= window.innerWidth) {
27
// Would detect unusual dimension relationship
28
} else {
29
// Assumes normal browser with proper window chrome
30
}
31
```
32
33
**Usage Examples:**
34
35
```javascript
36
const puppeteer = require('puppeteer-extra');
37
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
38
39
// Enable window dimensions evasion
40
const windowStealth = StealthPlugin({
41
enabledEvasions: new Set(['window.outerdimensions'])
42
});
43
44
puppeteer.use(windowStealth);
45
46
const browser = await puppeteer.launch({ headless: true });
47
const page = await browser.newPage();
48
49
// Window dimensions will now be realistic
50
await page.evaluate(() => {
51
console.log('Inner:', window.innerWidth, 'x', window.innerHeight);
52
console.log('Outer:', window.outerWidth, 'x', window.outerHeight);
53
54
// Outer dimensions will be larger than inner (accounting for browser chrome)
55
console.log('Has window chrome:', window.outerWidth > window.innerWidth);
56
// Returns: true (like a real browser)
57
});
58
```
59
60
### Iframe Content Window Evasion
61
62
Fixes iframe detection issues, particularly with `srcdoc` powered iframes.
63
64
```javascript { .api }
65
// Evasion name: 'iframe.contentWindow'
66
// Fixes: iframe.contentWindow.chrome detection and related iframe issues
67
```
68
69
This evasion:
70
- Prevents detection through iframe content window properties
71
- Fixes Chrome object availability in iframe contexts
72
- Addresses Chromium bugs with `srcdoc` iframes
73
- Ensures consistent behavior across iframe boundaries
74
75
**Detection Method Prevented:**
76
```javascript
77
// This detection method will be fooled:
78
const iframe = document.createElement('iframe');
79
iframe.srcdoc = '<html><body></body></html>';
80
document.body.appendChild(iframe);
81
82
iframe.onload = () => {
83
if (iframe.contentWindow.chrome) {
84
// Assumes real Chrome browser
85
} else {
86
// Would detect headless/automation through missing Chrome object in iframe
87
}
88
};
89
```
90
91
**Implementation Details:**
92
93
The iframe content window evasion:
94
1. **Monitors Iframe Creation**: Watches for new iframe elements
95
2. **Patches Content Windows**: Applies stealth modifications to iframe content windows
96
3. **Handles srcdoc Iframes**: Specifically addresses Chromium bug with srcdoc-powered iframes
97
4. **Maintains Consistency**: Ensures Chrome objects are available across frame boundaries
98
5. **Prevents Leakage**: Stops detection methods that rely on iframe property differences
99
100
**Usage Examples:**
101
102
```javascript
103
const puppeteer = require('puppeteer-extra');
104
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
105
106
// Enable iframe evasion along with Chrome API evasions
107
const iframeStealth = StealthPlugin({
108
enabledEvasions: new Set([
109
'iframe.contentWindow',
110
'chrome.runtime',
111
'chrome.app'
112
])
113
});
114
115
puppeteer.use(iframeStealth);
116
117
const browser = await puppeteer.launch();
118
const page = await browser.newPage();
119
120
// Test iframe behavior
121
await page.evaluate(() => {
122
const iframe = document.createElement('iframe');
123
iframe.srcdoc = `
124
<html>
125
<body>
126
<script>
127
// This will now work properly without detection
128
console.log('Chrome in iframe:', typeof chrome !== 'undefined');
129
console.log('Chrome runtime:', typeof chrome?.runtime !== 'undefined');
130
</script>
131
</body>
132
</html>
133
`;
134
135
document.body.appendChild(iframe);
136
137
return new Promise(resolve => {
138
iframe.onload = () => {
139
// iframe content window now has proper Chrome objects
140
resolve(typeof iframe.contentWindow.chrome !== 'undefined');
141
};
142
});
143
});
144
```
145
146
## Window Dimension Management
147
148
### Automatic Viewport Adjustment
149
150
The window outer dimensions evasion automatically adjusts the browser viewport to create realistic dimension relationships:
151
152
```javascript
153
// The evasion automatically calculates appropriate dimensions
154
// Inner dimensions: Set by user or browser defaults
155
// Outer dimensions: Inner + realistic browser chrome size
156
157
const chromeSize = 85; // Typical browser chrome height
158
const outerWidth = innerWidth + 16; // Small width addition for scrollbars
159
const outerHeight = innerHeight + chromeSize; // Browser chrome height
160
```
161
162
### Custom Viewport Handling
163
164
If you set a custom viewport, the evasion respects your settings:
165
166
```javascript
167
const browser = await puppeteer.launch();
168
const page = await browser.newPage();
169
170
// Set custom viewport - evasion will adjust outer dimensions accordingly
171
await page.setViewport({ width: 1366, height: 768 });
172
173
// Outer dimensions will be calculated based on this viewport
174
// outerWidth: ~1382, outerHeight: ~853
175
```
176
177
## Cross-Frame Consistency
178
179
Both window and iframe evasions ensure consistency across different execution contexts:
180
181
### Main Frame vs Iframe
182
183
```javascript
184
// Main frame and all iframes will have consistent Chrome object availability
185
await page.evaluate(() => {
186
// Main frame
187
console.log('Main chrome:', typeof chrome);
188
189
const iframe = document.createElement('iframe');
190
iframe.srcdoc = '<script>parent.postMessage(typeof chrome, "*")</script>';
191
192
window.addEventListener('message', (e) => {
193
console.log('Iframe chrome:', e.data);
194
// Both will show 'object' if Chrome evasions are enabled
195
});
196
197
document.body.appendChild(iframe);
198
});
199
```
200
201
### Multiple Windows
202
203
Window evasions apply to all windows opened from the page:
204
205
```javascript
206
await page.evaluate(() => {
207
const newWindow = window.open('about:blank');
208
209
// New window will also have proper outer dimensions
210
setTimeout(() => {
211
console.log('New window outer:', newWindow.outerWidth, newWindow.outerHeight);
212
console.log('New window chrome:', typeof newWindow.chrome);
213
newWindow.close();
214
}, 100);
215
});
216
```
217
218
## Browser Compatibility
219
220
Window and frame evasions are designed for:
221
- **Chrome/Chromium**: Primary target with specific bug fixes
222
- **Headless Mode**: Specifically addresses headless-mode limitations
223
- **Cross-Platform**: Works consistently across Windows, macOS, and Linux
224
- **Multiple Versions**: Handles different Chrome/Chromium version behaviors
225
226
## Advanced Usage Patterns
227
228
### Selective Window Evasions
229
230
```javascript
231
// Only fix window dimensions, not iframe behavior
232
const windowOnly = StealthPlugin({
233
enabledEvasions: new Set(['window.outerdimensions'])
234
});
235
236
// Only fix iframe behavior, keep original window dimensions
237
const iframeOnly = StealthPlugin({
238
enabledEvasions: new Set(['iframe.contentWindow', 'chrome.runtime'])
239
});
240
```
241
242
### Integration with Other Evasions
243
244
Window and frame evasions work best when combined with related evasions:
245
246
```javascript
247
// Comprehensive window/frame protection
248
const windowFrameStealth = StealthPlugin({
249
enabledEvasions: new Set([
250
'window.outerdimensions', // Fix window dimensions
251
'iframe.contentWindow', // Fix iframe behavior
252
'chrome.runtime', // Provide Chrome objects in iframes
253
'chrome.app', // Complete Chrome API simulation
254
'navigator.webdriver' // Remove automation indicators
255
])
256
});
257
```