├── LICENSE
├── README.md
├── assets
├── cf_bypass_logo.png
└── cf_turnstile.gif
├── cloudflare_bypass
├── __init__.py
├── auto.py
├── base_detector.py
├── cloudflare_detector.py
└── images
│ ├── cf_logo.png
│ ├── cf_logo_dark.png
│ ├── cf_popup.png
│ └── cf_popup_dark.png
├── requirements.txt
├── setup.py
└── tests
├── __init__.py
└── test_auto.py
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Tam Nguyen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Cloudflare CAPTCHA Bypass
2 |
3 |
4 |

5 |
6 |
7 | Detect and bypass Cloudflare CAPTCHA challenges effortlessly with the Cloudflare Captcha Bypass package.
8 |
9 |
10 |
11 |
12 | ## Installation
13 |
14 | ```bash
15 | pip install cloudflare_bypass
16 | ```
17 |
18 | ## Usage
19 | ```Python
20 | from cloudflare_bypass import bypass
21 |
22 | bypassed = bypass(mode='dark', warmup_time=5, timeout=30, interval=0.5)
23 |
24 | if bypassed:
25 | print("Cloudflare CAPTCHA bypassed successfully!")
26 | else:
27 | print("Timeout reached, CAPTCHA not bypassed.")
28 | ```
29 |
30 | Explanation of parameters:
31 |
32 | - `mode` (str): Choose 'light' for a light-colored webpage or 'dark' for a dark-colored webpage.
33 | - `warmup_time` (int): Optional warm-up time before starting detection (in seconds).
34 | - `timeout` (int): Maximum time to wait for the CAPTCHA logo to disappear after clicking (in seconds).
35 | - `interval` (int): Time interval between successive detections (in seconds).
36 |
37 | ## Limitations
38 | - This package only works on Cloudflare turnstile.
39 | - It can only run in GUI mode (not headless/background).
40 | - The speed is relatively slow.
41 |
42 | ## Disclaimer
43 | Note: This package is provided for educational and testing purposes only. Unauthorized use of this package to circumvent security measures is strictly prohibited. The author and contributors are not responsible for any misuse or consequences arising from the use of this package.
44 |
45 | ## Support
46 | If you find this project helpful, consider buying me a coffee to support ongoing development
47 |
48 | [](https://www.buymeacoffee.com/tamnvworkr)
49 |
50 |
51 | ## Contact
52 | For inquiries or support, please contact me:
53 | ```
54 | Name: Tam Nguyen
55 | Email: tamnv.work@gmail.com
56 | ```
57 |
58 | Feel free to open issues or contribute to the project on GitHub.
59 |
60 | ## Support My Side Project
61 | - [IconFst](https://iconfst.com)
62 |
--------------------------------------------------------------------------------
/assets/cf_bypass_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamnguyenvan/cloudflare-bypass/cd0fc7430cab52203e9327249b324d1086c44d28/assets/cf_bypass_logo.png
--------------------------------------------------------------------------------
/assets/cf_turnstile.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamnguyenvan/cloudflare-bypass/cd0fc7430cab52203e9327249b324d1086c44d28/assets/cf_turnstile.gif
--------------------------------------------------------------------------------
/cloudflare_bypass/__init__.py:
--------------------------------------------------------------------------------
1 | from cloudflare_bypass.auto import bypass
2 |
3 | __all__ = ['bypass']
--------------------------------------------------------------------------------
/cloudflare_bypass/auto.py:
--------------------------------------------------------------------------------
1 | from typing import Union
2 | import time
3 | import random
4 | import pyautogui
5 | from cloudflare_bypass.cloudflare_detector import CloudFlareLogoDetector, CloudFlarePopupDetector
6 |
7 |
8 | def wait_until(detector, warmup_time: Union[None, int] = None, timeout: int = 20):
9 | """
10 | Wait until a detector is detected or timeout is reached.
11 |
12 | Parameters:
13 | - detector: An instance of a detector.
14 | - warmup_time (int or None): Optional warm-up time before starting to detect.
15 | - timeout (int): Maximum time to wait for detection.
16 |
17 | Returns:
18 | - Union[None, Tuple[int]]: Bounding box coordinates if detection occurs, else None.
19 | """
20 | if warmup_time:
21 | time.sleep(warmup_time)
22 |
23 | t0 = time.time()
24 | while True:
25 | time.sleep(1)
26 | if detector.is_detected():
27 | return detector.matched_bbox
28 |
29 | if time.time() - t0 > timeout:
30 | break
31 |
32 |
33 | def click_like_human(x: int, y: int, max_value: int = 5):
34 | """
35 | Simulate a human-like click with a small random deviation.
36 |
37 | Parameters:
38 | - x (int): X-coordinate of the click.
39 | - y (int): Y-coordinate of the click.
40 | - max_value (int): Maximum deviation from the specified coordinates.
41 | """
42 | delta_x = random.randint(-max_value, max_value)
43 | delta_y = random.randint(-max_value, max_value)
44 | pyautogui.click(x=x + delta_x, y=y + delta_y)
45 |
46 |
47 | def bypass(
48 | mode: str = 'light',
49 | warmup_time: int = None,
50 | timeout: int = 20,
51 | interval: int = 1,
52 | threshold: float = 0.8,
53 | ):
54 | """
55 | Bypass CloudFlare challenges by clicking on the detected popup.
56 |
57 | Parameters:
58 | - mode (str): Choose the appropriate mode based on the webpage background color ('light' or 'dark').
59 | - warmup_time (int or None): Optional warm-up time before starting to detect.
60 | - timeout (int): Maximum time to wait for the CloudFlare logo to disappear after clicking the popup.
61 | - interval (int): Time interval between successive detections (default: 1 second).
62 | - threshold (float): Detection threshold for the CloudFlare logo and popup. Default is 0.8.
63 |
64 | Returns:
65 | - bool: True if the logo disappears within the timeout, else False.
66 | """
67 | # Optionally wait for warmup_time before starting the detection process
68 | if warmup_time is not None and isinstance(warmup_time, (int, float)):
69 | time.sleep(warmup_time)
70 |
71 | # Initialize CloudFlare detectors with the specified mode
72 | cf_popup_detector = CloudFlarePopupDetector(mode=mode, threshold=threshold)
73 | cf_logo_detector = CloudFlareLogoDetector(mode=mode, threshold=threshold)
74 |
75 | t0 = time.time()
76 | clicked = False
77 | while cf_logo_detector.is_detected():
78 | # Click on the popup if detected and not clicked before
79 | if not clicked and cf_popup_detector.is_detected():
80 | x1, y1, x2, y2 = cf_popup_detector.matched_bbox
81 | cx = x1 + int((x2 - x1) * 0.1)
82 | cy = (y1 + y2) // 2
83 | click_like_human(x=cx, y=cy)
84 | clicked = True
85 |
86 | # Wait for `interval` second before the next iteration
87 | time.sleep(interval)
88 |
89 | # Check if the timeout has been reached
90 | if time.time() - t0 > timeout:
91 | return clicked
92 |
93 | return clicked
94 |
--------------------------------------------------------------------------------
/cloudflare_bypass/base_detector.py:
--------------------------------------------------------------------------------
1 | from typing import Union, Tuple
2 | import cv2
3 | from PIL import ImageGrab
4 | import numpy as np
5 |
6 |
7 | class BaseDetector:
8 | def __init__(self, template_path: str, threshold: float = 0.8) -> None:
9 | """
10 | Initializes the BaseDetector with a template image and a matching threshold.
11 |
12 | Parameters:
13 | - template_path (str): Path to the template image file.
14 | - threshold (float): Matching threshold (default is 0.8).
15 | """
16 | self.template = cv2.imread(template_path, 0)
17 | self.threshold = threshold
18 | self.matched_bbox = None
19 |
20 | def _match(self, img: np.ndarray, template: np.ndarray) -> Union[None, Tuple[int]]:
21 | """
22 | Performs template matching on the input image.
23 |
24 | Parameters:
25 | - img (np.ndarray): Input image.
26 | - template (np.ndarray): Template image.
27 |
28 | Returns:
29 | - Union[None, Tuple[int]]: Bounding box coordinates if match is found, else None.
30 | """
31 | result = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)
32 | _, confidence, _, max_loc = cv2.minMaxLoc(result)
33 |
34 | if confidence >= self.threshold:
35 | h, w = template.shape
36 | top_left = max_loc
37 | bottom_right = (top_left[0] + w, top_left[1] + h)
38 | return top_left[0], top_left[1], bottom_right[0], bottom_right[1]
39 | else:
40 | return None
41 |
42 | def is_detected(self) -> bool:
43 | """
44 | Checks if the template is detected in the current screen.
45 |
46 | Returns:
47 | - bool: True if template is detected, else False.
48 | """
49 | img = np.array(ImageGrab.grab())
50 | img_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
51 |
52 | self.matched_bbox = self._match(img_gray, self.template)
53 | return self.matched_bbox is not None
--------------------------------------------------------------------------------
/cloudflare_bypass/cloudflare_detector.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from cloudflare_bypass.base_detector import BaseDetector
3 |
4 | image_dir = Path(__file__).parent
5 |
6 |
7 | class CloudFlarePopupDetector(BaseDetector):
8 | def __init__(self, mode: str = 'light', threshold: float = 0.8):
9 | """
10 | Initializes the CloudFlarePopupDetector with the path to the template image.
11 |
12 | The template image is used for detecting the presence of a CloudFlare popup.
13 |
14 | """
15 | if mode == 'light':
16 | self.template_path = str(image_dir / 'images/cf_popup.png')
17 | else:
18 | self.template_path = str(image_dir / 'images/cf_popup_dark.png')
19 |
20 | super().__init__(template_path=self.template_path, threshold=threshold)
21 |
22 |
23 | class CloudFlareLogoDetector(BaseDetector):
24 | def __init__(self, mode: str = 'light', threshold: float = 0.8):
25 | """
26 | Initializes the CloudFlareLogoDetector with the path to the template image.
27 |
28 | The template image is used for detecting the presence of the CloudFlare logo.
29 |
30 | """
31 | if mode == 'light':
32 | self.template_path = str(image_dir / 'images/cf_logo.png')
33 | else:
34 | self.template_path = str(image_dir / 'images/cf_logo_dark.png')
35 | super().__init__(template_path=self.template_path, threshold=threshold)
--------------------------------------------------------------------------------
/cloudflare_bypass/images/cf_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamnguyenvan/cloudflare-bypass/cd0fc7430cab52203e9327249b324d1086c44d28/cloudflare_bypass/images/cf_logo.png
--------------------------------------------------------------------------------
/cloudflare_bypass/images/cf_logo_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamnguyenvan/cloudflare-bypass/cd0fc7430cab52203e9327249b324d1086c44d28/cloudflare_bypass/images/cf_logo_dark.png
--------------------------------------------------------------------------------
/cloudflare_bypass/images/cf_popup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamnguyenvan/cloudflare-bypass/cd0fc7430cab52203e9327249b324d1086c44d28/cloudflare_bypass/images/cf_popup.png
--------------------------------------------------------------------------------
/cloudflare_bypass/images/cf_popup_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamnguyenvan/cloudflare-bypass/cd0fc7430cab52203e9327249b324d1086c44d28/cloudflare_bypass/images/cf_popup_dark.png
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | opencv-python
2 | Pillow
3 | numpy
4 | pyautogui
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 |
3 | # Function to read requirements from requirements.txt file
4 | def get_requirements():
5 | with open('requirements.txt') as f:
6 | return f.read().splitlines()
7 |
8 | # Read the content of README.md for long description
9 | with open('README.md', encoding='utf-8') as f:
10 | long_description = f.read()
11 |
12 |
13 | setup(
14 | name='cloudflare-bypass',
15 | version='0.1.2',
16 | description='A tool for bypassing Cloudflare CAPTCHA',
17 | long_description=long_description,
18 | long_description_content_type='text/markdown',
19 | url='https://github.com/tamnguyenvan/cloudflare-bypass',
20 | author='Tam Nguyen',
21 | author_email='tamnvhustcc@gmail.com',
22 | homepage='https://github.com/tamnguyenvan/cloudflare-bypass',
23 | packages=find_packages(),
24 | install_requires=get_requirements(),
25 | package_data={
26 | 'cloudflare_bypass': ['images/*.png', 'images/*.gif'],
27 | },
28 | classifiers=[
29 | 'Development Status :: 5 - Production/Stable',
30 | 'Intended Audience :: Developers',
31 | 'License :: OSI Approved :: MIT License',
32 | 'Programming Language :: Python :: 3',
33 | 'Programming Language :: Python :: 3.6',
34 | 'Programming Language :: Python :: 3.7',
35 | 'Programming Language :: Python :: 3.8',
36 | 'Programming Language :: Python :: 3.9',
37 | 'Programming Language :: Python :: 3.10',
38 | 'Programming Language :: Python :: 3.11',
39 | 'Programming Language :: Python :: 3.12',
40 | 'Topic :: Software Development :: Libraries',
41 | 'Topic :: Software Development :: Libraries :: Python Modules',
42 | ],
43 | keywords='cloudflare captcha bypass',
44 | project_urls={
45 | 'Documentation': 'https://tamnguyenvan.github.io/cloudflare-bypass',
46 | 'Source': 'https://github.com/tamnguyenvan/cloudflare-bypass',
47 | },
48 | )
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tamnguyenvan/cloudflare-bypass/cd0fc7430cab52203e9327249b324d1086c44d28/tests/__init__.py
--------------------------------------------------------------------------------
/tests/test_auto.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from cloudflare_bypass.auto import bypass
3 |
4 | from selenium import webdriver
5 |
6 |
7 | class TestAuto(unittest.TestCase):
8 | def test_bypass(self):
9 | url = 'https://nopecha.com/demo'
10 | options = webdriver.ChromeOptions()
11 | options.add_argument('--start-maximized')
12 | driver = webdriver.Chrome()
13 | driver.get(url)
14 | result = bypass(mode='dark', warmup_time=5, timeout=5)
15 |
16 | # Assertions
17 | self.assertTrue(result)
18 |
19 |
20 | if __name__ == '__main__':
21 | unittest.main()
--------------------------------------------------------------------------------