{"flag":true,"single":true,"pageTitle":"Chrome Automation with Cloudflare Turnstile Protection","post":{"id":346,"user_id":"1","slug":"chrome-automation-with-cloudflare-turnstile-protection-hp1u","title":"Chrome Automation with Cloudflare Turnstile Protection","body":"<pre class=\"language-markup\"><code>\"\"\"\r\nChrome Automation with Cloudflare Turnstile Protection\r\n\r\nSETUP:\r\npip install patchright==1.56.0 psutil\r\n\"\"\"\r\n\r\nimport asyncio\r\nimport os\r\nimport sys\r\nfrom pathlib import Path\r\nfrom patchright.async_api import async_playwright\r\n\r\n\r\nclass ChromeAutomation:\r\n    def __init__(self):\r\n        print(\"Chrome Automation started. Please wait...\")\r\n        self.playwright = None  # Patchright engine\r\n        self.browser = None     # Browser session\/profile\r\n        self.page = None        # Active tab\r\n\r\n    async def open_profile(self, profile_no=1, max_retries=3, use_cwd=False):\r\n        \"\"\"\r\n        Open Chrome with specified profile.\r\n        \r\n        Args:\r\n            profile_no: Profile number (1 = \"Profile 1\", 0 = \"Default\")\r\n            max_retries: Retry attempts (not used yet)\r\n            use_cwd: If True, use current directory; if False, use Chrome original profiles\r\n        \"\"\"\r\n        if self.playwright is None:\r\n            self.playwright = await async_playwright().start()\r\n        \r\n        # Determine profile directory name\r\n        if profile_no == 0:\r\n            profile_dir_name = \"Default\"\r\n        else:\r\n            profile_dir_name = f\"Profile {profile_no}\"\r\n        \r\n        # Determine user data directory\r\n        if use_cwd:\r\n            # Use current working directory\r\n            user_data_dir = str(Path.cwd() \/ \"ChromeProfile\")\r\n            Path(user_data_dir).mkdir(exist_ok=True)\r\n            print(f\"???? Using CWD profile: {user_data_dir}\")\r\n        else:\r\n            # Use Chrome original profiles\r\n            username = os.getenv('USERNAME') or os.getenv('USER') or 'User'\r\n            \r\n            if sys.platform == 'win32':\r\n                user_data_dir = f\"C:\\\\Users\\\\{username}\\\\AppData\\\\Local\\\\Google\\\\Chrome\\\\User Data\"\r\n            elif sys.platform == 'darwin':\r\n                user_data_dir = str(Path.home() \/ \"Library\" \/ \"Application Support\" \/ \"Google\" \/ \"Chrome\")\r\n            else:  # Linux\r\n                user_data_dir = str(Path.home() \/ \".config\" \/ \"google-chrome\")\r\n            \r\n            if not Path(user_data_dir).exists():\r\n                print(f\"?????? Original Chrome profile not found at {user_data_dir}\")\r\n                print(\"???? Try using use_cwd=True to create profile in current directory\")\r\n                raise FileNotFoundError(f\"Chrome profile not found: {user_data_dir}\")\r\n            \r\n            print(f\"???? Using Chrome original profile: {user_data_dir}\")\r\n        \r\n        self.browser = await self.playwright.chromium.launch_persistent_context(\r\n            user_data_dir=user_data_dir,\r\n            channel=\"chrome\",\r\n            headless=False,\r\n            no_viewport=True,\r\n            args=[f\"--profile-directory={profile_dir_name}\"]\r\n        )\r\n        \r\n        # Use existing page if available\r\n        if len(self.browser.pages) &gt; 0:\r\n            self.page = self.browser.pages[0]\r\n        else:\r\n            self.page = await self.browser.new_page()\r\n        \r\n        print(f\"??? Chrome session ready with {profile_dir_name}\")\r\n\r\n    async def solve_turnstile_challenge(self):\r\n        \"\"\"\r\n        Detect and solve Cloudflare Turnstile challenge.\r\n        \r\n        Returns:\r\n            bool: True if solved or not present, False if failed\r\n        \"\"\"\r\n        try:\r\n            print(\"Checking for human verification challenge...\")\r\n            \r\n            # Step 1: Quickly check if a Cloudflare\/Turnstile iframe is injected into the DOM\r\n            # We wait up to 3.5 seconds for the iframe itself. If it's not and won't be there, we skip.\r\n            challenge_iframe = self.page.locator(\r\n                \"iframe[src*='cloudflare'], iframe[src*='turnstile'], \"\r\n                \"iframe[title*='challenge'], iframe[title*='Cloudflare']\"\r\n            ).first\r\n            \r\n            is_challenge_present = False\r\n            try:\r\n                await challenge_iframe.wait_for(state=\"attached\", timeout=3500)\r\n                is_challenge_present = True\r\n            except Exception:\r\n                pass\r\n                \r\n            if is_challenge_present:\r\n                print(\"Turnstile challenge detected! Waiting for checkbox to become visible...\")\r\n                # The iframe is present, now wait up to 15 seconds for the checkbox inside to be visible\r\n                checkbox = self.page.frame_locator(\"iframe\").locator(\r\n                    \".cb-c input[type='checkbox'], label.cb-lb, .cb-i\"\r\n                ).first\r\n                await checkbox.wait_for(state=\"visible\", timeout=15000)\r\n                \r\n                print(\"Checkbox found! Moving mouse carefully...\")\r\n                await checkbox.hover()\r\n                await asyncio.sleep(0.8)  # Human-like pause\r\n                await checkbox.click(delay=150)  # Human-like click delay\r\n                print(\"Checkbox clicked successfully!\")\r\n                \r\n                # Wait a little bit for the challenge to resolve\r\n                await asyncio.sleep(5)\r\n                return True\r\n            else:\r\n                print(\"No Turnstile challenge detected on page. Proceeding immediately.\")\r\n                return True\r\n                \r\n        except Exception as e:\r\n            print(f\"Skipping verification check or failed: {e}\")\r\n            return False\r\n\r\n    async def close(self):\r\n        \"\"\"Close browser.\"\"\"\r\n        if self.browser:\r\n            await self.browser.close()\r\n        if self.playwright:\r\n            await self.playwright.stop()\r\n\r\n\r\nasync def main():\r\n    automation = ChromeAutomation()\r\n    \r\n    # Example 1: Use CWD with Profile 1\r\n    await automation.open_profile(profile_no=1, use_cwd=True)\r\n    \r\n    # Example 2: Use Chrome original profile (uncomment to use)\r\n    # await automation.open_profile(profile_no=1, use_cwd=False)\r\n    \r\n    await automation.page.goto('https:\/\/www.ip2location.com\/')\r\n    \r\n    await automation.solve_turnstile_challenge()\r\n    \r\n    await automation.page.screenshot(path=f'example-{automation.playwright.chromium.name}.png')\r\n    await automation.close()\r\n\r\n\r\nif __name__ == \"__main__\":\r\n    asyncio.run(main())\r\n<\/code><\/pre>","category_id":"37","is_private":"0","created_at":"2026-05-18T03:05:45.000000Z","updated_at":"2026-05-18T03:05:45.000000Z","category":{"id":37,"user_id":"1","name":"Playwright","slug":"playwright-c2zf","parent_id":null,"created_at":"2025-03-05T22:35:12.000000Z","updated_at":"2025-03-05T22:35:12.000000Z"},"user":{"id":1,"name":"R GONDAL","email":"rizikmw@gmail.com","email_verified_at":null,"two_factor_confirmed_at":null,"current_team_id":"1","profile_photo_path":null,"created_at":"2023-03-12T10:49:33.000000Z","updated_at":"2025-01-10T12:59:00.000000Z","profile_photo_url":"https:\/\/ui-avatars.com\/api\/?name=R+G&color=7F9CF5&background=EBF4FF"}},"pageDesc":"\"\"\" Chrome Automation with Cloudflare Turnstile Protection  SETUP: pip install patchright==1.56.0 psutil \"\"\"  import asyncio import os impor - Chrome Automation with Cloudflare Turnstile Protection (Updated: May 18, 2026) - Read more about Chrome Automation with Cloudflare Turnstile Protection at my programming site [SITE]","categories":[]}