├── 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 | Cloudflare CAPTCHA Bypass Logo 5 |
6 | 7 | Detect and bypass Cloudflare CAPTCHA challenges effortlessly with the Cloudflare Captcha Bypass package. 8 | 9 | Bypassed image 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 | [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](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() --------------------------------------------------------------------------------