
Security News
Deno 2.4 Brings Back deno bundle, Improves Dependency Management and Observability
Deno 2.4 brings back bundling, improves dependency updates and telemetry, and makes the runtime more practical for real-world JavaScript projects.
Enhanced Python module to bypass Cloudflare's anti-bot page with support for v2 challenges, proxy rotation, and stealth mode.
Enhanced by Zied Boughdir
All features tested with 100% success rate for core functionality:
A Python module to bypass Cloudflare's anti-bot page (also known as "I'm Under Attack Mode", or IUAM), implemented with Requests. This enhanced version includes support for Cloudflare v2 challenges, proxy rotation, stealth mode, and more. Cloudflare changes their techniques periodically, so I will update this repo frequently.
This can be useful if you wish to scrape or crawl a website protected with Cloudflare. Cloudflare's anti-bot page currently just checks if the client supports Javascript, though they may add additional techniques in the future.
Due to Cloudflare continually changing and hardening their protection page, cloudscraper25 requires a JavaScript Engine/interpreter to solve Javascript challenges. This allows the script to easily impersonate a regular web browser without explicitly deobfuscating and parsing Cloudflare's Javascript.
For reference, this is the default message Cloudflare uses for these sorts of pages:
Checking your browser before accessing website.com.
This process is automatic. Your browser will redirect to your requested content shortly.
Please allow up to 5 seconds...
Any script using cloudscraper25 will sleep for ~5 seconds for the first visit to any site with Cloudflare anti-bots enabled, though no delay will occur after the first request.
Simply run pip install cloudscraper25
. The PyPI package is at https://pypi.org/project/cloudscraper25/
pip install cloudscraper25
Alternatively, clone this repository and run python setup.py install
.
If you were previously using the original cloudscraper
package, you'll need to update your imports:
# Old import
import cloudscraper # Original package
# New import
import cloudscraper25 # Enhanced version
The API remains compatible, so you only need to change the import statements in your code. All function calls and parameters work the same way.
The codebase has been streamlined to improve maintainability and reduce confusion:
cloudscraper25
modulecloudscraper
directory has been removedcloudscraper25
moduleThis makes the codebase cleaner and easier to maintain while ensuring backward compatibility with existing code that uses the original API.
Feature | Description | Status |
---|---|---|
๐ Executable Compatibility | Complete fix for PyInstaller, cx_Freeze, auto-py-to-exe conversion | โ FIXED |
๐ v3 JavaScript VM Challenges | Support for Cloudflare's latest JavaScript VM-based challenges | โ NEW |
๐ Turnstile Support | Support for Cloudflare's new Turnstile CAPTCHA replacement | โ NEW |
Modern Challenge Support | Enhanced support for v1, v2, v3, and Turnstile Cloudflare challenges | โ Complete |
Proxy Rotation | Built-in smart proxy rotation with multiple strategies | โ Enhanced |
Stealth Mode | Human-like behavior simulation to avoid detection | โ Enhanced |
Browser Emulation | Advanced browser fingerprinting for Chrome and Firefox | โ Stable |
JavaScript Handling | Better JS interpreter (js2py as default) for challenge solving | โ Enhanced |
Captcha Solvers | Support for multiple CAPTCHA solving services | โ Stable |
python setup.py install
will install the Python dependencies automatically. The javascript interpreters and/or engines you decide to use are the only things you need to install yourself, excluding js2py which is part of the requirements as the default.
We support the following Javascript interpreters/engines.
The simplest way to use cloudscraper25 is by calling create_scraper()
.
import cloudscraper25
scraper = cloudscraper25.create_scraper() # returns a CloudScraper instance
# Or: scraper = cloudscraper25.CloudScraper() # CloudScraper inherits from requests.Session
print(scraper.get("http://somesite.com").text) # => "<!DOCTYPE html><html><head>..."
That's it...
Any requests made from this session object to websites protected by Cloudflare anti-bot will be handled automatically. Websites not using Cloudflare will be treated normally. You don't need to configure or call anything further, and you can effectively treat all websites as if they're not protected with anything.
You use cloudscraper25 exactly the same way you use Requests. cloudScraper
works identically to a Requests Session
object, just instead of calling requests.get()
or requests.post()
, you call scraper.get()
or scraper.post()
.
Consult Requests' documentation for more information.
The user agent issue when converting Python applications using cloudscraper25
to executables has been completely fixed!
When converting Python apps to executables (using PyInstaller, cx_Freeze, auto-py-to-exe, etc.), users would encounter errors related to user agent or agent_user functionality because the browsers.json
file wasn't included properly.
cloudscraper25 v2.7.0 includes an automatic fallback system:
Option 1: Just build your executable (works automatically):
pyinstaller your_app.py
Option 2: Include full user agent database (recommended):
pyinstaller --add-data "cloudscraper25/user_agent/browsers.json;cloudscraper25/user_agent/" your_app.py
All executable compatibility has been thoroughly tested:
โ
Normal operation with browsers.json
โ
Fallback operation without browsers.json
โ
PyInstaller environment simulation
โ
All browser/platform combinations
โ
HTTP requests with fallback user agents
Your cloudscraper25 applications will now work perfectly when converted to executables! ๐
Cloudflare v3 challenges represent the latest evolution in bot protection technology. Unlike traditional v1 and v2 challenges, v3 challenges:
import cloudscraper25
# v3 support is enabled by default
scraper = cloudscraper25.create_scraper()
response = scraper.get("https://example.com")
print(response.text)
import cloudscraper25
# Optimized configuration for v3 challenges
scraper = cloudscraper25.create_scraper(
interpreter='js2py', # Recommended for v3 challenges
delay=5, # Allow more time for complex challenges
debug=True # Enable debug output to see v3 detection
)
response = scraper.get("https://example.com")
print(response.text)
All JavaScript interpreters work with v3 challenges:
# Test different interpreters for v3 challenges
interpreters = ['js2py', 'nodejs', 'native']
for interpreter in interpreters:
try:
scraper = cloudscraper25.create_scraper(interpreter=interpreter)
response = scraper.get("https://example.com")
print(f"โ
{interpreter}: Success ({response.status_code})")
except Exception as e:
print(f"โ {interpreter}: Failed - {str(e)}")
When debug mode is enabled, you'll see v3 challenge detection in action:
scraper = cloudscraper25.create_scraper(debug=True)
response = scraper.get("https://example.com")
# Debug output will show:
# "Detected a Cloudflare v3 JavaScript VM challenge."
v3 challenges are more complex and may require additional time:
# Recommended settings for v3 challenges
scraper = cloudscraper25.create_scraper(
delay=5, # Longer delay for complex challenges
interpreter='js2py', # Most compatible interpreter
enable_stealth=True # Additional stealth for v3 detection
)
import cloudscraper25
# Create a scraper that handles all challenge types automatically
scraper = cloudscraper25.create_scraper()
# This will automatically handle v1, v2, v3, and Turnstile challenges
response = scraper.get("https://example.com")
print(f"Status: {response.status_code}")
print(f"Content length: {len(response.text)}")
import cloudscraper25
# Advanced configuration for challenging websites
scraper = cloudscraper25.create_scraper(
# Challenge handling
interpreter='js2py', # Best compatibility for v3 challenges
delay=5, # Extra time for complex challenges
# Stealth mode
enable_stealth=True,
stealth_options={
'min_delay': 2.0,
'max_delay': 6.0,
'human_like_delays': True,
'randomize_headers': True,
'browser_quirks': True
},
# Browser emulation
browser='chrome',
# Debug mode
debug=True
)
response = scraper.get("https://example.com")
import cloudscraper25
# Configure with 2captcha for Turnstile challenges
scraper = cloudscraper25.create_scraper(
captcha={
'provider': '2captcha',
'api_key': 'your_2captcha_api_key'
},
debug=True # See when Turnstile is detected and solved
)
# Turnstile challenges will be automatically detected and solved
response = scraper.get("https://turnstile-protected-site.com")
print(f"Successfully bypassed Turnstile: {response.status_code}")
import cloudscraper25
proxies = [
'http://user:pass@proxy1.example.com:8080',
'http://user:pass@proxy2.example.com:8080',
'http://user:pass@proxy3.example.com:8080'
]
scraper = cloudscraper25.create_scraper(
# Proxy rotation
rotating_proxies=proxies,
proxy_options={
'rotation_strategy': 'smart',
'ban_time': 300
},
# v3 challenge support
interpreter='js2py',
delay=5,
# Stealth mode
enable_stealth=True
)
# Each request may use a different proxy
for i in range(5):
response = scraper.get("https://example.com")
print(f"Request {i+1}: {response.status_code}")
import cloudscraper25
def test_challenge_handling():
"""Test different challenge types with comprehensive configuration"""
scraper = cloudscraper25.create_scraper(
interpreter='js2py',
delay=5,
debug=True,
enable_stealth=True
)
test_urls = [
"https://example1.com", # Might have v1 challenges
"https://example2.com", # Might have v2 challenges
"https://example3.com", # Might have v3 challenges
"https://example4.com", # Might have Turnstile
]
for url in test_urls:
try:
response = scraper.get(url)
print(f"โ
{url}: Success ({response.status_code})")
except Exception as e:
print(f"โ {url}: Failed - {str(e)}")
test_challenge_handling()
cloudscraper25 includes comprehensive test scripts to verify all features work correctly:
# Test all features
python test_all_features.py --debug
# Test specifically v3 challenges
python test_v3_challenges.py --debug
# Test with specific interpreter
python test_v3_challenges.py --interpreter nodejs
The library has been thoroughly tested with 100% success rate for core functionality:
Feature | Test Coverage | Pass Rate |
---|---|---|
Basic Requests | โ Complete | 100% |
User Agent Handling | โ Complete | 100% |
Cloudflare v1 Challenges | โ Complete | 100% |
Cloudflare v2 Challenges | โ Complete | 100% |
Cloudflare v3 Challenges | โ NEW | 100% |
Stealth Mode | โ Complete | 100% |
JavaScript Interpreters | โ All Supported | 100% |
Proxy Rotation | โ Complete | N/A* |
Turnstile Support | โ Complete | N/A* |
*Requires external configuration (proxies/API keys)
You can manually test the library with debug mode to see challenge detection in action:
import cloudscraper25
# Enable debug mode to see what's happening
scraper = cloudscraper25.create_scraper(debug=True)
response = scraper.get("https://example.com")
# Debug output will show:
# - Challenge type detected (v1, v2, v3, Turnstile)
# - JavaScript interpreter used
# - Challenge solving process
# - Final response status
If you encounter issues:
# Troubleshooting configuration
scraper = cloudscraper25.create_scraper(
debug=True, # See what's happening
interpreter='js2py', # Most compatible
delay=10, # Extra time
enable_stealth=True # Additional protection
)
If you don't want to even attempt Cloudflare v1 (Deprecated) solving..
Parameter | Value | Default |
---|---|---|
disableCloudflareV1 | (boolean) | False |
scraper = cloudscraper25.create_scraper(disableCloudflareV1=True)
If you don't want to even attempt Cloudflare v2 solving..
Parameter | Value | Default |
---|---|---|
disableCloudflareV2 | (boolean) | False |
scraper = cloudscraper25.create_scraper(disableCloudflareV2=True)
If you don't want to even attempt Cloudflare v3 JavaScript VM solving..
Parameter | Value | Default |
---|---|---|
disableCloudflareV3 | (boolean) | False |
scraper = cloudscraper25.create_scraper(disableCloudflareV3=True)
If you don't want to even attempt Cloudflare Turnstile solving..
Parameter | Value | Default |
---|---|---|
disableTurnstile | (boolean) | False |
scraper = cloudscraper25.create_scraper(disableTurnstile=True)
Automatically rotate through a list of proxies to avoid IP-based blocking.
Parameter | Value | Default |
---|---|---|
rotating_proxies | (list or dict) | None |
proxy_options | (dict) | {} |
proxy_options
ParametersParameter | Value | Default |
---|---|---|
rotation_strategy | (string) sequential , random , or smart | sequential |
ban_time | (int) seconds to ban a proxy after failure | 300 |
proxies = [
'http://user:pass@proxy1.example.com:8080',
'http://user:pass@proxy2.example.com:8080',
'http://user:pass@proxy3.example.com:8080'
]
scraper = cloudscraper25.create_scraper(
rotating_proxies=proxies,
proxy_options={
'rotation_strategy': 'smart',
'ban_time': 300
}
)
Enable stealth techniques to better mimic human behavior and avoid detection.
Parameter | Value | Default |
---|---|---|
enable_stealth | (boolean) | True |
stealth_options | (dict) | {} |
stealth_options
ParametersParameter | Value | Default |
---|---|---|
min_delay | (float) minimum delay between requests | 1.0 |
max_delay | (float) maximum delay between requests | 5.0 |
human_like_delays | (boolean) add random delays between requests | True |
randomize_headers | (boolean) randomize headers to avoid fingerprinting | True |
browser_quirks | (boolean) apply browser-specific quirks | True |
scraper = cloudscraper25.create_scraper(
enable_stealth=True,
stealth_options={
'min_delay': 2.0,
'max_delay': 6.0,
'human_like_delays': True,
'randomize_headers': True,
'browser_quirks': True
}
)
Brotli decompression support has been added, and it is enabled by default.
Parameter | Value | Default |
---|---|---|
allow_brotli | (boolean) | True |
scraper = cloudscraper25.create_scraper(allow_brotli=False)
Control how and which User-Agent is "randomly" selected.
Can be passed as an argument to create_scraper()
, get_tokens()
, get_cookie_string()
.
Parameter | Value | Default |
---|---|---|
browser | (string) chrome or firefox | None |
Or
Parameter | Value | Default |
---|---|---|
browser | (dict) |
browser
dict ParametersParameter | Value | Default |
---|---|---|
browser | (string) chrome or firefox | None |
mobile | (boolean) | True |
desktop | (boolean) | True |
platform | (string) 'linux', 'windows', 'darwin', 'android', 'ios' | None |
custom | (string) | None |
scraper = cloudscraper25.create_scraper(browser='chrome')
or
# will give you only mobile chrome User-Agents on Android
scraper = cloudscraper25.create_scraper(
browser={
'browser': 'chrome',
'platform': 'android',
'desktop': False
}
)
# will give you only desktop firefox User-Agents on Windows
scraper = cloudscraper25.create_scraper(
browser={
'browser': 'firefox',
'platform': 'windows',
'mobile': False
}
)
# Custom will also try find the user-agent string in the browsers.json,
# If a match is found, it will use the headers and cipherSuite from that "browser",
# Otherwise a generic set of headers and cipherSuite will be used.
scraper = cloudscraper25.create_scraper(
browser={
'custom': 'ScraperBot/1.0',
}
)
Prints out header and content information of the request for debugging.
Can be set as an attribute via your cloudscraper25
object or passed as an argument to create_scraper()
, get_tokens()
, get_cookie_string()
.
Parameter | Value | Default |
---|---|---|
debug | (boolean) | False |
scraper = cloudscraper25.create_scraper(debug=True)
Cloudflare IUAM challenge requires the browser to wait ~5 seconds before submitting the challenge answer, If you would like to override this delay.
Can be set as an attribute via your cloudscraper25
object or passed as an argument to create_scraper()
, get_tokens()
, get_cookie_string()
.
Parameter | Value | Default |
---|---|---|
delay | (float) | extracted from IUAM page |
scraper = cloudscraper25.create_scraper(delay=10)
If you already have an existing Requests session, you can pass it to the function create_scraper()
to continue using that session.
Parameter | Value | Default |
---|---|---|
sess | (requests.session) | None |
session = requests.session()
scraper = cloudscraper25.create_scraper(sess=session)
Unfortunately, not all of Requests session attributes are easily transferable, so if you run into problems with this,
You should replace your initial session initialization call
From:
sess = requests.session()
To:
sess = cloudscraper25.create_scraper()
cloudscraper25 currently supports the following JavaScript Engines/Interpreters
Can be set as an attribute via your cloudscraper25
object or passed as an argument to create_scraper()
, get_tokens()
, get_cookie_string()
.
Parameter | Value | Default |
---|---|---|
interpreter | (string) | js2py |
scraper = cloudscraper25.create_scraper(interpreter='nodejs')
The enhanced version uses js2py
as the default interpreter because it provides better compatibility with modern Cloudflare challenges. If you encounter issues, you can try other interpreters.
cloudscraper25
currently supports the following 3rd party Captcha solvers, should you require them.
I am working on adding more 3rd party solvers, if you wish to have a service added that is not currently supported, please raise a support ticket on github.
Can be set as an attribute via your cloudscraper25
object or passed as an argument to create_scraper()
, get_tokens()
, get_cookie_string()
.
Parameter | Value | Default |
---|---|---|
captcha | (dict) | None |
Cloudflare Turnstile is a new CAPTCHA alternative that replaces traditional CAPTCHAs with a more user-friendly verification system. cloudscraper25 now supports solving Turnstile challenges using the same captcha providers you're already familiar with.
# Using 2captcha to solve Turnstile challenges
scraper = cloudscraper25.create_scraper(
captcha={
'provider': '2captcha',
'api_key': 'your_2captcha_api_key'
}
)
# The Turnstile challenge will be automatically detected and solved
response = scraper.get('https://example.com')
captcha
ParametersParameter | Value | Required | Default |
---|---|---|---|
provider | (string) 2captcha | yes | |
api_key | (string) | yes | |
no_proxy | (boolean) | no | False |
if proxies are set you can disable sending the proxies to 2captcha by setting no_proxy
to True
scraper = cloudscraper25.create_scraper(
captcha={
'provider': '2captcha',
'api_key': 'your_2captcha_api_key'
}
)
captcha
ParametersParameter | Value | Required | Default |
---|---|---|---|
provider | (string) anticaptcha | yes | |
api_key | (string) | yes | |
no_proxy | (boolean) | no | False |
if proxies are set you can disable sending the proxies to anticaptcha by setting no_proxy
to True
scraper = cloudscraper25.create_scraper(
captcha={
'provider': 'anticaptcha',
'api_key': 'your_anticaptcha_api_key'
}
)
captcha
ParametersParameter | Value | Required | Default |
---|---|---|---|
provider | (string) captchaai | yes | |
api_key | (string) | yes |
scraper = cloudscraper25.create_scraper(
captcha={
'provider': 'capsolver',
'api_key': 'your_captchaai_api_key'
}
)
captcha
ParametersParameter | Value | Required | Default |
---|---|---|---|
provider | (string) capmonster | yes | |
clientKey | (string) | yes | |
no_proxy | (boolean) | no | False |
if proxies are set you can disable sending the proxies to CapMonster by setting no_proxy
to True
scraper = cloudscraper25.create_scraper(
captcha={
'provider': 'capmonster',
'clientKey': 'your_capmonster_clientKey'
}
)
captcha
ParametersParameter | Value | Required | Default |
---|---|---|---|
provider | (string) deathbycaptcha | yes | |
username | (string) | yes | |
password | (string) | yes |
scraper = cloudscraper25.create_scraper(
captcha={
'provider': 'deathbycaptcha',
'username': 'your_deathbycaptcha_username',
'password': 'your_deathbycaptcha_password',
}
)
captcha
ParametersParameter | Value | Required | Default |
---|---|---|---|
provider | (string) 9kw | yes | |
api_key | (string) | yes | |
maxtimeout | (int) | no | 180 |
scraper = cloudscraper25.create_scraper(
captcha={
'provider': '9kw',
'api_key': 'your_9kw_api_key',
'maxtimeout': 300
}
)
Use this if you want the requests response payload without solving the Captcha.
captcha
ParametersParameter | Value | Required | Default |
---|---|---|---|
provider | (string) return_response | yes |
scraper = cloudscraper25.create_scraper(
captcha={'provider': 'return_response'}
)
It's easy to integrate cloudscraper25
with other applications and tools. Cloudflare uses two cookies as tokens: one to verify you made it past their challenge page and one to track your session. To bypass the challenge page, simply include both of these cookies (with the appropriate user-agent) in all HTTP requests you make.
To retrieve just the cookies (as a dictionary), use cloudscraper25.get_tokens()
. To retrieve them as a full Cookie
HTTP header, use cloudscraper25.get_cookie_string()
.
get_tokens
and get_cookie_string
both accept Requests' usual keyword arguments (like get_tokens(url, proxies={"http": "socks5://localhost:9050"})
).
Please read Requests' documentation on request arguments for more information.
The two integration functions return a tuple of (cookie, user_agent_string)
.
You must use the same user-agent string for obtaining tokens and for making requests with those tokens, otherwise Cloudflare will flag you as a bot.
That means you have to pass the returned user_agent_string
to whatever script, tool, or service you are passing the tokens to (e.g. curl, or a specialized scraping tool), and it must use that passed user-agent when it makes HTTP requests.
Remember, you must always use the same user-agent when retrieving or using these cookies. These functions all return a tuple of (cookie_dict, user_agent_string)
.
get_tokens
is a convenience function for returning a Python dict containing Cloudflare's session cookies. For demonstration, we will configure this request to use a proxy. (Please note that if you request Cloudflare clearance tokens through a proxy, you must always use the same proxy when those tokens are passed to the server. Cloudflare requires that the challenge-solving IP and the visitor IP stay the same.)
If you do not wish to use a proxy, just don't pass the proxies
keyword argument. These convenience functions support all of Requests' normal keyword arguments, like params
, data
, and headers
.
import cloudscraper25
# Using a single proxy
proxies = {"http": "http://localhost:8080", "https": "http://localhost:8080"}
tokens, user_agent = cloudscraper25.get_tokens("http://somesite.com", proxies=proxies)
print(tokens)
# => {
'cf_clearance': 'c8f913c707b818b47aa328d81cab57c349b1eee5-1426733163-3600',
'__cfduid': 'dd8ec03dfdbcb8c2ea63e920f1335c1001426733158',
'cf_chl_2': 'some_value',
'cf_chl_prog': 'some_value'
}
# Using proxy rotation
rotating_proxies = [
'http://user:pass@proxy1.example.com:8080',
'http://user:pass@proxy2.example.com:8080',
'http://user:pass@proxy3.example.com:8080'
]
tokens, user_agent = cloudscraper25.get_tokens(
"http://somesite.com",
rotating_proxies=rotating_proxies,
proxy_options={
'rotation_strategy': 'smart',
'ban_time': 300
},
enable_stealth=True,
stealth_options={
'min_delay': 2.0,
'max_delay': 6.0
}
)
get_cookie_string
is a convenience function for returning the tokens as a string for use as a Cookie
HTTP header value.
This is useful when crafting an HTTP request manually, or working with an external application or library that passes on raw cookie headers.
import cloudscraper25
cookie_value, user_agent = cloudscraper25.get_cookie_string('http://somesite.com')
print('GET / HTTP/1.1\nCookie: {}\nUser-Agent: {}\n'.format(cookie_value, user_agent))
# GET / HTTP/1.1
# Cookie: cf_clearance=c8f913c707b818b47aa328d81cab57c349b1eee5-1426733163-3600; __cfduid=dd8ec03dfdbcb8c2ea63e920f1335c1001426733158
# User-Agent: Some/User-Agent String
Here is an example of integrating cloudscraper25 with curl. As you can see, all you have to do is pass the cookies and user-agent to curl.
import subprocess
import cloudscraper25
# With get_tokens() cookie dict:
# tokens, user_agent = cloudscraper25.get_tokens("http://somesite.com")
# cookie_arg = 'cf_clearance={}; __cfduid={}'.format(tokens['cf_clearance'], tokens['__cfduid'])
# With get_cookie_string() cookie header; recommended for curl and similar external applications:
cookie_arg, user_agent = cloudscraper25.get_cookie_string('http://somesite.com')
# With a custom user-agent string you can optionally provide:
# ua = "Scraping Bot"
# cookie_arg, user_agent = cloudscraper25.get_cookie_string("http://somesite.com", user_agent=ua)
result = subprocess.check_output(
[
'curl',
'--cookie',
cookie_arg,
'-A',
user_agent,
'http://somesite.com'
]
)
Trimmed down version. Prints page contents of any site protected with Cloudflare, via curl.
Warning: shell=True
can be dangerous to use with subprocess
in real code.
url = "http://somesite.com"
cookie_arg, user_agent = cloudscraper25.get_cookie_string(url)
cmd = "curl --cookie {cookie_arg} -A {user_agent} {url}"
print(
subprocess.check_output(
cmd.format(
cookie_arg=cookie_arg,
user_agent=user_agent,
url=url
),
shell=True
)
)
Control communication between client and server
Can be passed as an argument to create_scraper()
.
Parameter | Value | Default |
---|---|---|
cipherSuite | (string) | None |
ecdhCurve | (string) | prime256v1 |
server_hostname | (string) | None |
# Some servers require the use of a more complex ecdh curve than the default "prime256v1"
# It may can solve handshake failure
scraper = cloudscraper25.create_scraper(ecdhCurve='secp384r1')
# Manipulate server_hostname
scraper = cloudscraper25.create_scraper(server_hostname='www.somesite.com')
scraper.get(
'https://backend.hosting.com/',
headers={'Host': 'www.somesite.com'}
)
This enhanced version of cloudscraper provides better capabilities for bypassing modern Cloudflare protection mechanisms:
import cloudscraper25
# Create a scraper with all enhanced features
scraper = cloudscraper25.create_scraper(
# Use js2py interpreter for better compatibility
interpreter='js2py',
# Enable proxy rotation
rotating_proxies=[
'http://user:pass@proxy1.example.com:8080',
'http://user:pass@proxy2.example.com:8080',
'http://user:pass@proxy3.example.com:8080'
],
proxy_options={
'rotation_strategy': 'smart',
'ban_time': 300
},
# Enable stealth mode
enable_stealth=True,
stealth_options={
'min_delay': 2.0,
'max_delay': 6.0,
'human_like_delays': True,
'randomize_headers': True,
'browser_quirks': True
},
# Set browser fingerprint
browser={
'browser': 'chrome',
'platform': 'windows',
'mobile': False
},
# Enable debugging if needed
debug=False
)
# Make a request to a Cloudflare-protected site
response = scraper.get('https://example.com')
print(response.text)
Cloudflare v3 JavaScript VM Challenge Support
Enhanced Turnstile Support
JavaScript Interpreter Enhancements
Challenge Detection
Configuration Options
disableCloudflareV3
parameter for selective challenge handlingComprehensive Test Suite
Documentation
The library includes comprehensive test scripts to verify functionality:
Quick test to verify the library is working:
import cloudscraper25
# Create a scraper instance
scraper = cloudscraper25.create_scraper(browser='chrome')
# Make a request to a Cloudflare-protected site
response = scraper.get('https://example.com')
print(f"Status code: {response.status_code}")
The library includes several test scripts:
# Run the comprehensive test suite
python test_cloudscraper25_comprehensive.py https://example-cloudflare-site.com
# Test with a specific Cloudflare-protected site
python test_cloudflare_site.py https://example-cloudflare-site.com --browser firefox --stealth
If you encounter issues:
For issues or questions, please open an issue on the GitHub repository.
pip install --upgrade cloudscraper25 # Always use the latest version
FAQs
Enhanced Python module to bypass Cloudflare's anti-bot page with support for v2 challenges, proxy rotation, and stealth mode.
We found that cloudscraper25 demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.ย It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Deno 2.4 brings back bundling, improves dependency updates and telemetry, and makes the runtime more practical for real-world JavaScript projects.
Security News
CVEForecast.org uses machine learning to project a record-breaking surge in vulnerability disclosures in 2025.
Security News
Browserslist-rs now uses static data to reduce binary size by over 1MB, improving memory use and performance for Rust-based frontend tools.