0
# Challenge Handling
1
2
Comprehensive support for all Cloudflare challenge types including legacy v1, modern v2, advanced v3 JavaScript VM challenges, and Turnstile CAPTCHA alternatives. CloudScraper automatically detects and solves these challenges transparently.
3
4
## Capabilities
5
6
### Cloudflare v1 (Legacy) Challenges
7
8
Handler for legacy Cloudflare v1 challenges that use simple JavaScript validation and timing delays.
9
10
```python { .api }
11
class Cloudflare:
12
def __init__(self, cloudscraper):
13
"""Initialize v1 challenge handler."""
14
15
@staticmethod
16
def is_Challenge_Request(resp) -> bool:
17
"""
18
Detect if response contains a v1 challenge.
19
20
Parameters:
21
- resp: requests.Response object
22
23
Returns:
24
bool: True if v1 challenge detected
25
"""
26
27
@staticmethod
28
def is_IUAM_Challenge(resp) -> bool:
29
"""
30
Detect IUAM (I'm Under Attack Mode) challenge.
31
32
Parameters:
33
- resp: requests.Response object
34
35
Returns:
36
bool: True if IUAM challenge detected
37
"""
38
39
def Challenge_Response(self, resp, **kwargs):
40
"""
41
Handle v1 challenge solving.
42
43
Parameters:
44
- resp: requests.Response containing challenge
45
- **kwargs: request parameters
46
47
Returns:
48
requests.Response with solved challenge
49
50
Raises:
51
- CloudflareIUAMError: If challenge parameters cannot be extracted
52
- CloudflareSolveError: If challenge solving fails
53
"""
54
```
55
56
#### Usage Examples
57
58
```python
59
# v1 challenges are handled automatically
60
scraper = cloudscraper.create_scraper()
61
response = scraper.get('https://legacy-protected-site.com')
62
63
# Disable v1 handling if needed
64
scraper = cloudscraper.create_scraper(disableCloudflareV1=True)
65
66
# Manual v1 detection (normally not needed)
67
if cloudscraper.Cloudflare.is_Challenge_Request(response):
68
print("v1 challenge detected")
69
```
70
71
### Cloudflare v2 Challenges
72
73
Handler for modern Cloudflare v2 challenges that include JavaScript execution and CAPTCHA verification.
74
75
```python { .api }
76
class CloudflareV2:
77
def __init__(self, cloudscraper):
78
"""Initialize v2 challenge handler."""
79
80
@staticmethod
81
def is_V2_Challenge(resp) -> bool:
82
"""
83
Detect v2 JavaScript challenge.
84
85
Parameters:
86
- resp: requests.Response object
87
88
Returns:
89
bool: True if v2 JS challenge detected
90
"""
91
92
@staticmethod
93
def is_V2_Captcha_Challenge(resp) -> bool:
94
"""
95
Detect v2 CAPTCHA challenge.
96
97
Parameters:
98
- resp: requests.Response object
99
100
Returns:
101
bool: True if v2 CAPTCHA challenge detected
102
"""
103
104
def handle_V2_Challenge(self, resp, **kwargs):
105
"""
106
Handle v2 JavaScript challenge.
107
108
Parameters:
109
- resp: requests.Response containing challenge
110
- **kwargs: request parameters
111
112
Returns:
113
requests.Response with solved challenge
114
115
Raises:
116
- CloudflareChallengeError: If challenge cannot be solved
117
"""
118
119
def handle_V2_Captcha_Challenge(self, resp, **kwargs):
120
"""
121
Handle v2 CAPTCHA challenge.
122
123
Parameters:
124
- resp: requests.Response containing challenge
125
- **kwargs: request parameters
126
127
Returns:
128
requests.Response with solved challenge
129
130
Raises:
131
- CloudflareCaptchaError: If CAPTCHA cannot be solved
132
- CloudflareCaptchaProvider: If no CAPTCHA solver configured
133
"""
134
135
def extract_challenge_data(self, resp) -> dict:
136
"""
137
Extract v2 challenge parameters from response.
138
139
Parameters:
140
- resp: requests.Response containing challenge
141
142
Returns:
143
dict: Challenge parameters and JavaScript code
144
145
Raises:
146
- CloudflareChallengeError: If challenge data cannot be extracted
147
"""
148
149
def generate_challenge_payload(self, challenge_data, resp) -> dict:
150
"""
151
Generate payload for v2 challenge submission.
152
153
Parameters:
154
- challenge_data: dict, extracted challenge parameters
155
- resp: requests.Response, original challenge response
156
157
Returns:
158
dict: Challenge solution payload
159
"""
160
```
161
162
#### Usage Examples
163
164
```python
165
# v2 challenges handled automatically
166
scraper = cloudscraper.create_scraper()
167
response = scraper.get('https://v2-protected-site.com')
168
169
# With CAPTCHA solver for v2 CAPTCHA challenges
170
scraper = cloudscraper.create_scraper(
171
captcha={
172
'provider': '2captcha',
173
'api_key': 'your_api_key'
174
}
175
)
176
177
# Disable v2 handling
178
scraper = cloudscraper.create_scraper(disableCloudflareV2=True)
179
```
180
181
### Cloudflare v3 JavaScript VM Challenges
182
183
Handler for advanced Cloudflare v3 challenges that execute JavaScript in a virtual machine environment for enhanced security.
184
185
```python { .api }
186
class CloudflareV3:
187
def __init__(self, cloudscraper):
188
"""Initialize v3 challenge handler."""
189
190
@staticmethod
191
def is_V3_Challenge(resp) -> bool:
192
"""
193
Detect v3 JavaScript VM challenge.
194
195
Parameters:
196
- resp: requests.Response object
197
198
Returns:
199
bool: True if v3 challenge detected
200
"""
201
202
def extract_v3_challenge_data(self, resp) -> dict:
203
"""
204
Extract v3 challenge parameters from response.
205
206
Parameters:
207
- resp: requests.Response containing challenge
208
209
Returns:
210
dict: Challenge parameters and data
211
212
Raises:
213
- CloudflareV3Error: If challenge data cannot be extracted
214
"""
215
216
def handle_V3_Challenge(self, resp, **kwargs):
217
"""
218
Handle v3 JavaScript VM challenge.
219
220
Parameters:
221
- resp: requests.Response containing challenge
222
- **kwargs: request parameters
223
224
Returns:
225
requests.Response with solved challenge
226
227
Raises:
228
- CloudflareV3Error: If challenge cannot be solved
229
"""
230
231
def execute_vm_challenge(self, challenge_data, domain) -> str:
232
"""
233
Execute JavaScript VM challenge code.
234
235
Parameters:
236
- challenge_data: dict, extracted challenge parameters
237
- domain: str, target domain for challenge
238
239
Returns:
240
str: Challenge solution result
241
242
Raises:
243
- CloudflareV3Error: If VM execution fails
244
"""
245
246
def generate_fallback_response(self, challenge_data) -> str:
247
"""
248
Generate fallback response when VM execution fails.
249
250
Parameters:
251
- challenge_data: dict, challenge parameters
252
253
Returns:
254
str: Fallback challenge response
255
"""
256
257
def generate_v3_challenge_payload(self, challenge_data, resp, challenge_answer) -> dict:
258
"""
259
Generate payload for v3 challenge submission.
260
261
Parameters:
262
- challenge_data: dict, extracted challenge parameters
263
- resp: requests.Response, original challenge response
264
- challenge_answer: str, computed challenge solution
265
266
Returns:
267
dict: Challenge solution payload
268
"""
269
```
270
271
#### Usage Examples
272
273
```python
274
# v3 challenges handled automatically
275
scraper = cloudscraper.create_scraper()
276
response = scraper.get('https://v3-protected-site.com')
277
278
# Optimized for v3 challenges
279
scraper = cloudscraper.create_scraper(
280
interpreter='js2py', # Recommended for v3
281
delay=5, # Allow more time for complex challenges
282
debug=True # See v3 detection
283
)
284
285
# Disable v3 handling
286
scraper = cloudscraper.create_scraper(disableCloudflareV3=True)
287
```
288
289
### Cloudflare Turnstile Challenges
290
291
Handler for Cloudflare Turnstile challenges, which are CAPTCHA alternatives that provide user-friendly verification.
292
293
```python { .api }
294
class CloudflareTurnstile:
295
def __init__(self, cloudscraper):
296
"""Initialize Turnstile challenge handler."""
297
298
@staticmethod
299
def is_Turnstile_Challenge(resp) -> bool:
300
"""
301
Detect Turnstile challenge.
302
303
Parameters:
304
- resp: requests.Response object
305
306
Returns:
307
bool: True if Turnstile challenge detected
308
"""
309
310
def extract_turnstile_data(self, resp) -> dict:
311
"""
312
Extract Turnstile challenge parameters.
313
314
Parameters:
315
- resp: requests.Response containing challenge
316
317
Returns:
318
dict: Turnstile site key and parameters
319
320
Raises:
321
- CloudflareTurnstileError: If Turnstile data cannot be extracted
322
"""
323
324
def handle_Turnstile_Challenge(self, resp, **kwargs):
325
"""
326
Handle Turnstile challenge solving.
327
328
Parameters:
329
- resp: requests.Response containing challenge
330
- **kwargs: request parameters
331
332
Returns:
333
requests.Response with solved challenge
334
335
Raises:
336
- CloudflareTurnstileError: If Turnstile cannot be solved
337
- CloudflareCaptchaProvider: If no CAPTCHA solver configured
338
"""
339
```
340
341
#### Usage Examples
342
343
```python
344
# Turnstile challenges handled automatically with CAPTCHA solver
345
scraper = cloudscraper.create_scraper(
346
captcha={
347
'provider': '2captcha',
348
'api_key': 'your_api_key'
349
}
350
)
351
response = scraper.get('https://turnstile-protected-site.com')
352
353
# Different CAPTCHA providers work with Turnstile
354
providers = ['2captcha', 'anticaptcha', 'capsolver', 'capmonster']
355
for provider in providers:
356
scraper = cloudscraper.create_scraper(
357
captcha={'provider': provider, 'api_key': 'key'}
358
)
359
360
# Disable Turnstile handling
361
scraper = cloudscraper.create_scraper(disableTurnstile=True)
362
```
363
364
## Challenge Detection and Priority
365
366
CloudScraper automatically detects and handles challenges in priority order:
367
368
1. **Turnstile challenges** (highest priority)
369
2. **v3 JavaScript VM challenges**
370
3. **v2 JavaScript and CAPTCHA challenges**
371
4. **v1 legacy challenges** (lowest priority)
372
373
```python
374
# All challenge types enabled by default
375
scraper = cloudscraper.create_scraper()
376
377
# Selective challenge handling
378
scraper = cloudscraper.create_scraper(
379
disableCloudflareV1=True, # Skip legacy challenges
380
disableCloudflareV2=False, # Handle v2 challenges
381
disableCloudflareV3=False, # Handle v3 challenges
382
disableTurnstile=False # Handle Turnstile
383
)
384
```
385
386
## Challenge Solving Configuration
387
388
### JavaScript Interpreter Selection
389
390
Different interpreters work better with different challenge types:
391
392
```python
393
# Recommended interpreters by challenge type
394
interpreters = {
395
'v1': ['js2py', 'nodejs', 'native'],
396
'v2': ['js2py', 'nodejs', 'v8'],
397
'v3': ['js2py', 'nodejs'], # js2py recommended for v3
398
'turnstile': ['any'] # Uses CAPTCHA solver, not interpreter
399
}
400
401
# Configure interpreter
402
scraper = cloudscraper.create_scraper(interpreter='js2py')
403
```
404
405
### Challenge Timing
406
407
Configure delays and timeouts for challenge solving:
408
409
```python
410
# Custom challenge timing
411
scraper = cloudscraper.create_scraper(
412
delay=5, # Wait 5 seconds before submitting solution
413
solveDepth=3 # Maximum challenge solving attempts
414
)
415
```
416
417
### Debug Mode for Challenges
418
419
Enable debug output to see challenge detection and solving:
420
421
```python
422
scraper = cloudscraper.create_scraper(debug=True)
423
response = scraper.get('https://protected-site.com')
424
425
# Debug output shows:
426
# "Detected a Cloudflare v3 JavaScript VM challenge."
427
# "Solving challenge with js2py interpreter..."
428
# "Challenge solved successfully"
429
```
430
431
## Error Handling
432
433
Challenge handling can raise specific exceptions:
434
435
```python
436
try:
437
scraper = cloudscraper.create_scraper()
438
response = scraper.get('https://protected-site.com')
439
except cloudscraper.CloudflareLoopProtection:
440
print("Too many challenge attempts - infinite loop detected")
441
except cloudscraper.CloudflareV3Error:
442
print("v3 JavaScript VM challenge failed")
443
except cloudscraper.CloudflareTurnstileError:
444
print("Turnstile challenge failed")
445
except cloudscraper.CloudflareCaptchaProvider:
446
print("CAPTCHA challenge detected but no solver configured")
447
except cloudscraper.CloudflareSolveError:
448
print("General challenge solving error")
449
```
450
451
## Advanced Challenge Handling
452
453
### Custom Challenge Detection
454
455
For advanced users who need to detect challenges manually:
456
457
```python
458
response = scraper.get('https://example.com')
459
460
# Manual challenge detection
461
if cloudscraper.CloudflareTurnstile.is_Turnstile_Challenge(response):
462
print("Turnstile detected")
463
elif cloudscraper.CloudflareV3.is_V3_Challenge(response):
464
print("v3 challenge detected")
465
elif cloudscraper.CloudflareV2.is_V2_Challenge(response):
466
print("v2 JS challenge detected")
467
elif cloudscraper.CloudflareV2.is_V2_Captcha_Challenge(response):
468
print("v2 CAPTCHA challenge detected")
469
elif cloudscraper.Cloudflare.is_Challenge_Request(response):
470
print("v1 challenge detected")
471
```
472
473
### Challenge Hooks
474
475
Use request hooks to monitor challenge solving:
476
477
```python
478
def pre_challenge_hook(scraper, method, url, *args, **kwargs):
479
print(f"About to solve challenge for {url}")
480
return method, url, args, kwargs
481
482
def post_challenge_hook(scraper, response):
483
if response.status_code == 200:
484
print("Challenge solved successfully")
485
return response
486
487
scraper = cloudscraper.create_scraper(
488
requestPreHook=pre_challenge_hook,
489
requestPostHook=post_challenge_hook
490
)
491
```