import time import json import logging import random import math from camoufox.sync_api import Camoufox logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) class HumanMouseMovement: @staticmethod def bezier_curve(start, end, steps=50): points = [] control1 = ( start[0] + random.randint(-100, 100), start[1] + random.randint(-100, 100) ) control2 = ( end[0] + random.randint(-100, 100), end[1] + random.randint(-100, 100) ) for i in range(steps + 1): t = i / steps x = (1-t)**3 * start[0] + 3*(1-t)**2*t * control1[0] + 3*(1-t)*t**2 * control2[0] + t**3 * end[0] y = (1-t)**3 * start[1] + 3*(1-t)**2*t * control1[1] + 3*(1-t)*t**2 * control2[1] + t**3 * end[1] shake_x = random.uniform(-2, 2) shake_y = random.uniform(-2, 2) points.append((x + shake_x, y + shake_y)) return points @staticmethod def add_micro_movements(x, y): micro_x = x + random.uniform(-1, 1) micro_y = y + random.uniform(-1, 1) return micro_x, micro_y class HCaptchaSolver: def __init__(self): self.browser = None self.page = None self.context = None self.mouse_pos = {'x': 0, 'y': 0} def setup_browser(self): logger.info("Setting up Camoufox browser...") try: self.browser = Camoufox( headless=True, humanize=True ) self.context = self.browser.new_context( viewport={'width': 1920, 'height': 1080}, user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', locale='en-US', timezone_id='America/New_York' ) self.page = self.context.new_page() self.page.add_init_script(""" Object.defineProperty(navigator, 'webdriver', { get: () => undefined }); window.chrome = { runtime: {}, }; Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5], }); """) logger.info("Camoufox browser setup complete") except Exception as e: logger.error(f"Browser setup failed: {e}") raise def human_mouse_move(self, target_x, target_y): start = (self.mouse_pos['x'], self.mouse_pos['y']) end = (target_x, target_y) points = HumanMouseMovement.bezier_curve(start, end, steps=random.randint(30, 60)) for x, y in points: micro_x, micro_y = HumanMouseMovement.add_micro_movements(x, y) self.page.mouse.move(micro_x, micro_y) time.sleep(random.uniform(0.001, 0.005)) self.mouse_pos = {'x': target_x, 'y': target_y} def human_click(self, selector=None, x=None, y=None): if selector: try: element = self.page.locator(selector) box = element.bounding_box() if box: click_x = box['x'] + box['width'] / 2 + random.uniform(-5, 5) click_y = box['y'] + box['height'] / 2 + random.uniform(-5, 5) else: return False except: return False else: click_x = x click_y = y self.human_mouse_move(click_x, click_y) time.sleep(random.uniform(0.05, 0.15)) for _ in range(random.randint(1, 3)): offset_x = random.uniform(-1, 1) offset_y = random.uniform(-1, 1) self.page.mouse.move(click_x + offset_x, click_y + offset_y) time.sleep(random.uniform(0.01, 0.03)) self.page.mouse.down() time.sleep(random.uniform(0.05, 0.12)) self.page.mouse.up() time.sleep(random.uniform(0.1, 0.3)) return True def open_page(self): logger.info("Opening bylo.ai...") self.page.goto("https://bylo.ai/features/sora-2", wait_until="networkidle", timeout=60000) time.sleep(random.uniform(2, 4)) def click_login_button(self): logger.info("Looking for login button...") try: self.page.wait_for_selector('button.flex.items-center.gap-3', timeout=10000) self.human_click('button.flex.items-center.gap-3') logger.info("Login button clicked") time.sleep(random.uniform(1.5, 2.5)) return True except Exception as e: logger.error(f"Error clicking login: {e}") return False def click_signup(self): logger.info("Looking for Sign Up...") try: self.page.wait_for_selector("text=Sign Up", timeout=10000) self.human_click("text=Sign Up") logger.info("Sign Up clicked") time.sleep(random.uniform(1.5, 2.5)) return True except Exception as e: logger.error(f"Error clicking signup: {e}") return False def fill_email(self, email): logger.info(f"Filling email: {email}") try: self.page.wait_for_selector('input[name="email"]', timeout=10000) email_input = self.page.locator('input[name="email"]') box = email_input.bounding_box() if box: click_x = box['x'] + box['width'] / 2 click_y = box['y'] + box['height'] / 2 self.human_mouse_move(click_x, click_y) self.page.mouse.click(click_x, click_y) time.sleep(random.uniform(0.3, 0.6)) for char in email: self.page.keyboard.type(char) time.sleep(random.uniform(0.08, 0.25)) logger.info("Email filled") time.sleep(random.uniform(0.5, 1)) return True except Exception as e: logger.error(f"Error filling email: {e}") return False def click_get_code(self): logger.info("Clicking Get Code...") try: self.page.wait_for_selector("text=Get Code", timeout=10000) self.human_click("text=Get Code") logger.info("Get Code clicked") time.sleep(random.uniform(2, 3)) return True except Exception as e: logger.error(f"Error clicking get code: {e}") return False def solve_hcaptcha(self): logger.info("="*60) logger.info("Starting hCaptcha solving process...") logger.info("="*60) try: time.sleep(3) logger.info("Looking for hCaptcha iframe...") frames = self.page.frames logger.info(f"Found {len(frames)} frames") hcaptcha_frame = None for frame in frames: try: frame_url = frame.url logger.info(f"Frame URL: {frame_url[:100] if frame_url else 'empty'}") if frame_url and 'hcaptcha.com/captcha' in frame_url: logger.info("Found hCaptcha checkbox frame!") hcaptcha_frame = frame break except: continue if not hcaptcha_frame: logger.warning("hCaptcha frame not found, waiting...") for i in range(5): logger.info(f"Waiting for hCaptcha to load... attempt {i+1}/5") time.sleep(2) frames = self.page.frames for frame in frames: try: if frame.url and 'hcaptcha.com/captcha' in frame.url: hcaptcha_frame = frame break except: continue if hcaptcha_frame: break if hcaptcha_frame: logger.info("Attempting to click hCaptcha checkbox...") try: checkbox = hcaptcha_frame.locator('#checkbox') checkbox.wait_for(timeout=5000) box = checkbox.bounding_box() if box: click_x = box['x'] + box['width'] / 2 + random.uniform(-3, 3) click_y = box['y'] + box['height'] / 2 + random.uniform(-3, 3) self.human_mouse_move(click_x, click_y) time.sleep(random.uniform(0.5, 1)) for _ in range(random.randint(2, 4)): micro_x = click_x + random.uniform(-2, 2) micro_y = click_y + random.uniform(-2, 2) self.page.mouse.move(micro_x, micro_y) time.sleep(random.uniform(0.02, 0.05)) self.page.mouse.down() time.sleep(random.uniform(0.08, 0.15)) self.page.mouse.up() logger.info("Checkbox clicked!") time.sleep(random.uniform(2, 4)) except Exception as e: logger.error(f"Error clicking checkbox: {e}") logger.info("Waiting for hCaptcha token...") for attempt in range(40): token = self.get_hcaptcha_token() if token: return token time.sleep(1) if attempt % 5 == 0: logger.info(f"Still waiting for token... {attempt}s") logger.warning("Token not found after waiting") return None except Exception as e: logger.error(f"Error solving hCaptcha: {e}") return None def get_hcaptcha_token(self): try: token = self.page.evaluate(""" () => { const elements = [ document.querySelector('textarea[name="h-captcha-response"]'), document.querySelector('[data-hcaptcha-response]'), document.querySelector('input[name="h-captcha-response"]') ]; for (let el of elements) { if (el && el.value && el.value.length > 10) { return el.value; } if (el && el.getAttribute('data-hcaptcha-response')) { return el.getAttribute('data-hcaptcha-response'); } } return null; } """) if token and len(token) > 10: logger.info("="*60) logger.info("TOKEN FOUND!") logger.info(f"Token: {token[:50]}...") logger.info(f"Length: {len(token)}") logger.info("="*60) return token except Exception as e: pass return None def run(self, email="herzfnf@gmail.com"): try: self.setup_browser() self.open_page() if not self.click_login_button(): raise Exception("Failed to click login button") if not self.click_signup(): raise Exception("Failed to click signup") if not self.fill_email(email): raise Exception("Failed to fill email") if not self.click_get_code(): raise Exception("Failed to click get code") token = self.solve_hcaptcha() if token: logger.info("SUCCESS! Token retrieved") return { "success": True, "token": token, "email": email } else: logger.warning("Failed to get token") return { "success": False, "message": "Failed to get hCaptcha token" } except Exception as e: logger.error(f"Error: {e}") return { "success": False, "error": str(e) } finally: self.cleanup() def cleanup(self): try: if self.page: self.page.close() if self.context: self.context.close() if self.browser: self.browser.close() logger.info("Browser closed") except: pass if __name__ == "__main__": solver = HCaptchaSolver() result = solver.run("herzfnf@gmail.com") print("\n" + "="*60) print("FINAL RESULT:") print(json.dumps(result, indent=2)) print("="*60)