From b740a083d48653dd086ef2929d0b9c1ad10530cf Mon Sep 17 00:00:00 2001 From: dariyaanis Date: Fri, 2 Oct 2026 19:13:58 +0300 Subject: [PATCH] feat: add step-by-step example logs --- examples/cloudflare_challenge.py | 5 ++++- examples/common.py | 25 +++++++++++++++++++++++++ examples/coordinates.py | 13 ++++++++++++- examples/image_to_text.py | 5 ++++- examples/normal_captcha_canvas.py | 12 +++++++++++- examples/normal_captcha_params.py | 5 ++++- examples/recaptcha_v2.py | 5 +++++ examples/recaptcha_v2_callback.py | 5 ++++- examples/recaptcha_v2_callback_auto.py | 5 ++++- examples/recaptcha_v2_callback_proxy.py | 4 ++++ examples/recaptcha_v2_proxy.py | 5 +++++ examples/recaptcha_v3.py | 6 +++++- examples/turnstile.py | 13 ++++++++++++- 13 files changed, 99 insertions(+), 9 deletions(-) diff --git a/examples/cloudflare_challenge.py b/examples/cloudflare_challenge.py index 9a9f813..63a9157 100644 --- a/examples/cloudflare_challenge.py +++ b/examples/cloudflare_challenge.py @@ -4,7 +4,7 @@ import time from captcha_solver_api.tasks import TurnstileTaskProxyless -from common import create_client, required_env, show_success +from common import create_client, logged_example, required_env, show_success from selenium.common.exceptions import TimeoutException from selenium.webdriver.support.ui import WebDriverWait from seleniumbase import Driver @@ -66,6 +66,7 @@ def capture_params(driver): return state["params"] +@logged_example def main() -> None: with ( Driver(browser="chrome", headless=False, agent=BROWSER_USER_AGENT) as driver, @@ -80,6 +81,7 @@ def main() -> None: params = capture_params(driver) if params is None: return + print("Parameters received") solution = client.solve(TurnstileTaskProxyless(**params)) driver.execute_script( @@ -91,6 +93,7 @@ def main() -> None: """, solution["token"], ) + print("The token is sent to the callback function") show_success(driver) time.sleep(10) diff --git a/examples/common.py b/examples/common.py index 4c4db33..7a7f407 100644 --- a/examples/common.py +++ b/examples/common.py @@ -2,6 +2,7 @@ import json import os +from functools import wraps from typing import Any, Dict, Optional from captcha_solver_api import CaptchaClient @@ -23,11 +24,35 @@ def solve( timeout: Optional[int] = None, ) -> Dict[str, Any]: solution = super().solve(task, language_pool=language_pool, timeout=timeout) + if "text" in solution: + print(f"Captcha solved. Code: {solution['text']}") + elif "coordinates" in solution: + print("Captcha solved. Coordinates received") + else: + print("Captcha solved") print("API response:") print(json.dumps(solution, ensure_ascii=False, indent=2, sort_keys=True)) return solution +def logged_example(function): + """Print the same lifecycle messages as the reference Selenium examples.""" + + @wraps(function) + def wrapper(*args, **kwargs): + print("Started") + try: + result = function(*args, **kwargs) + except Exception as error: + print(f"An error occurred: {error}") + print("Failed to solve captcha") + raise + print("Finished") + return result + + return wrapper + + def required_env(name: str) -> str: value = os.getenv(name) if not value: diff --git a/examples/coordinates.py b/examples/coordinates.py index d60af5e..2e4e265 100644 --- a/examples/coordinates.py +++ b/examples/coordinates.py @@ -5,7 +5,14 @@ import time from captcha_solver_api.tasks import CoordinatesTask -from common import create_client, required_env, show_success, wait_for_css, wait_for_xpath +from common import ( + create_client, + logged_example, + required_env, + show_success, + wait_for_css, + wait_for_xpath, +) from selenium.webdriver import ActionChains from seleniumbase import Driver @@ -28,6 +35,7 @@ def png_size(png_base64: str): return struct.unpack(">II", image[16:24]) +@logged_example def main() -> None: with Driver(browser="chrome", headless=False) as driver, create_client() as client: driver.get(URL) @@ -46,16 +54,19 @@ def main() -> None: "coordinates:", solution["coordinates"], ) + print("The received response is converted into a list of coordinates") for point in solution["coordinates"]: ActionChains(driver).move_to_element_with_offset( captcha, point["x"] * scale_x - captcha.size["width"] / 2, point["y"] * scale_y - captcha.size["height"] / 2, ).click().perform() + print("The coordinates are marked on the image") submit = wait_for_xpath(driver, SUBMIT_LOCATOR) driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", submit) driver.execute_script("arguments[0].click();", submit) + print("Pressed the Check button") show_success(driver) time.sleep(5) diff --git a/examples/image_to_text.py b/examples/image_to_text.py index e4c44c5..dc703f3 100644 --- a/examples/image_to_text.py +++ b/examples/image_to_text.py @@ -3,7 +3,7 @@ import time from captcha_solver_api.tasks import ImageToTextTask -from common import create_client, required_env, show_success, wait_for_xpath +from common import create_client, logged_example, required_env, show_success, wait_for_xpath from seleniumbase import Driver URL = required_env("TARGET_URL") @@ -12,13 +12,16 @@ SUBMIT_LOCATOR = "//button[@type='submit']" +@logged_example def main() -> None: with Driver(browser="chrome", headless=False) as driver, create_client() as client: driver.get(URL) captcha = wait_for_xpath(driver, IMAGE_LOCATOR) solution = client.solve(ImageToTextTask(body=captcha.screenshot_as_base64)) wait_for_xpath(driver, ANSWER_LOCATOR).send_keys(solution["text"]) + print("Entered the answer to the captcha") wait_for_xpath(driver, SUBMIT_LOCATOR).click() + print("Pressed the Check button") show_success(driver) time.sleep(5) diff --git a/examples/normal_captcha_canvas.py b/examples/normal_captcha_canvas.py index 9ec1079..340ecb2 100644 --- a/examples/normal_captcha_canvas.py +++ b/examples/normal_captcha_canvas.py @@ -3,7 +3,14 @@ import time from captcha_solver_api.tasks import ImageToTextTask -from common import create_client, required_env, show_success, wait_for_css, wait_for_xpath +from common import ( + create_client, + logged_example, + required_env, + show_success, + wait_for_css, + wait_for_xpath, +) from seleniumbase import Driver URL = required_env("TARGET_URL") @@ -21,6 +28,7 @@ """ +@logged_example def main() -> None: with Driver(browser="chrome", headless=False) as driver, create_client() as client: driver.get(URL) @@ -28,7 +36,9 @@ def main() -> None: image = driver.execute_script(CANVAS_SCRIPT, IMAGE_SELECTOR) solution = client.solve(ImageToTextTask(body=image)) wait_for_xpath(driver, ANSWER_LOCATOR).send_keys(solution["text"]) + print("Entered the answer to the captcha") wait_for_xpath(driver, SUBMIT_LOCATOR).click() + print("Pressed the Check button") show_success(driver) time.sleep(5) diff --git a/examples/normal_captcha_params.py b/examples/normal_captcha_params.py index 227c1f2..a829564 100644 --- a/examples/normal_captcha_params.py +++ b/examples/normal_captcha_params.py @@ -3,7 +3,7 @@ import time from captcha_solver_api.tasks import ImageToTextTask -from common import create_client, required_env, show_success, wait_for_xpath +from common import create_client, logged_example, required_env, show_success, wait_for_xpath from seleniumbase import Driver URL = required_env("TARGET_URL") @@ -12,6 +12,7 @@ SUBMIT_LOCATOR = "//button[@type='submit']" +@logged_example def main() -> None: with Driver(browser="chrome", headless=False) as driver, create_client() as client: driver.get(URL) @@ -25,7 +26,9 @@ def main() -> None: ) ) wait_for_xpath(driver, ANSWER_LOCATOR).send_keys(solution["text"]) + print("Entered the answer to the captcha") wait_for_xpath(driver, SUBMIT_LOCATOR).click() + print("Pressed the Check button") show_success(driver) time.sleep(5) diff --git a/examples/recaptcha_v2.py b/examples/recaptcha_v2.py index f1c013d..469744e 100644 --- a/examples/recaptcha_v2.py +++ b/examples/recaptcha_v2.py @@ -7,6 +7,7 @@ from common import ( create_client, fill_response_field, + logged_example, wait_for_css, wait_for_xpath, ) @@ -18,6 +19,7 @@ SUCCESS_SELECTOR = ".recaptcha-success, p.successMessage" +@logged_example def main() -> None: with Driver(browser="chrome", headless=False) as driver, create_client() as client: driver.get(URL) @@ -25,6 +27,7 @@ def main() -> None: sitekey = widget.get_attribute("data-sitekey") if not sitekey: raise RuntimeError("No reCAPTCHA sitekey found") + print(f"Sitekey received: {sitekey}") solution = client.solve( RecaptchaV2TaskProxyless( @@ -34,7 +37,9 @@ def main() -> None: ) ) fill_response_field(driver, "g-recaptcha-response", solution["gRecaptchaResponse"]) + print("Token sent") wait_for_xpath(driver, SUBMIT_LOCATOR).click() + print("Pressed the Check button") print(wait_for_css(driver, SUCCESS_SELECTOR).text) time.sleep(5) diff --git a/examples/recaptcha_v2_callback.py b/examples/recaptcha_v2_callback.py index 8ee6f77..aabd2ac 100644 --- a/examples/recaptcha_v2_callback.py +++ b/examples/recaptcha_v2_callback.py @@ -3,22 +3,25 @@ import time from captcha_solver_api.tasks import RecaptchaV2TaskProxyless -from common import create_client, required_env, show_success, wait_for_xpath +from common import create_client, logged_example, required_env, show_success, wait_for_xpath from seleniumbase import Driver URL = required_env("TARGET_URL") SITEKEY_LOCATOR = "//div[@id='g-recaptcha']" +@logged_example def main() -> None: with Driver(browser="chrome", headless=False) as driver, create_client() as client: driver.get(URL) sitekey = wait_for_xpath(driver, SITEKEY_LOCATOR).get_attribute("data-sitekey") + print(f"Sitekey received: {sitekey}") solution = client.solve(RecaptchaV2TaskProxyless(websiteURL=URL, websiteKey=sitekey)) driver.execute_script( "window.verifyDemoRecaptcha(arguments[0]);", solution["gRecaptchaResponse"], ) + print("The token is sent to the callback function") show_success(driver) time.sleep(5) diff --git a/examples/recaptcha_v2_callback_auto.py b/examples/recaptcha_v2_callback_auto.py index 37e8c47..335eee9 100644 --- a/examples/recaptcha_v2_callback_auto.py +++ b/examples/recaptcha_v2_callback_auto.py @@ -3,7 +3,7 @@ import time from captcha_solver_api.tasks import RecaptchaV2TaskProxyless -from common import create_client, required_env, show_success +from common import create_client, logged_example, required_env, show_success from selenium.webdriver.support.ui import WebDriverWait from seleniumbase import Driver @@ -36,12 +36,14 @@ """ +@logged_example def main() -> None: with Driver(browser="chrome", headless=False) as driver, create_client() as client: driver.get(URL) params = WebDriverWait(driver, 30).until( lambda current: current.execute_script(FIND_CLIENT) ) + print("Got the callback function name and site key") solution = client.solve( RecaptchaV2TaskProxyless(websiteURL=URL, websiteKey=params["sitekey"]) ) @@ -56,6 +58,7 @@ def main() -> None: params.get("callbackPath"), solution["gRecaptchaResponse"], ) + print("The token is sent to the callback function") show_success(driver) time.sleep(5) diff --git a/examples/recaptcha_v2_callback_proxy.py b/examples/recaptcha_v2_callback_proxy.py index 079e943..577b3a3 100644 --- a/examples/recaptcha_v2_callback_proxy.py +++ b/examples/recaptcha_v2_callback_proxy.py @@ -5,6 +5,7 @@ from captcha_solver_api.tasks import RecaptchaV2Task from common import ( create_client, + logged_example, proxy_settings, required_env, selenium_proxy, @@ -18,6 +19,7 @@ SITEKEY_LOCATOR = "//div[@id='g-recaptcha']" +@logged_example def main() -> None: with ( Driver(browser="chrome", headless=False, cft=True, proxy=selenium_proxy()) as driver, @@ -31,6 +33,7 @@ def main() -> None: "The target page did not load through the configured proxy. " "Check the proxy address, credentials, and availability." ) from exc + print("Got the callback function name and site key") solution = client.solve( RecaptchaV2Task( websiteURL=URL, @@ -43,6 +46,7 @@ def main() -> None: "window.verifyDemoRecaptcha(arguments[0]);", solution["gRecaptchaResponse"], ) + print("The token is sent to the callback function") show_success(driver) time.sleep(5) diff --git a/examples/recaptcha_v2_proxy.py b/examples/recaptcha_v2_proxy.py index 8cdcee7..75a9cee 100644 --- a/examples/recaptcha_v2_proxy.py +++ b/examples/recaptcha_v2_proxy.py @@ -6,6 +6,7 @@ from common import ( create_client, fill_response_field, + logged_example, proxy_settings, required_env, selenium_proxy, @@ -20,6 +21,7 @@ SUBMIT_LOCATOR = "//button[@data-action='demo_action']" +@logged_example def main() -> None: with ( Driver(browser="chrome", headless=False, cft=True, proxy=selenium_proxy()) as driver, @@ -33,6 +35,7 @@ def main() -> None: "The target page did not load through the configured proxy. " "Check the proxy address, credentials, and availability." ) from exc + print(f"Sitekey received: {sitekey}") solution = client.solve( RecaptchaV2Task( websiteURL=URL, @@ -42,7 +45,9 @@ def main() -> None: ) ) fill_response_field(driver, "g-recaptcha-response", solution["gRecaptchaResponse"]) + print("Token sent") wait_for_xpath(driver, SUBMIT_LOCATOR).click() + print("Pressed the Check button") show_success(driver) time.sleep(5) diff --git a/examples/recaptcha_v3.py b/examples/recaptcha_v3.py index 82a9e21..74cff99 100644 --- a/examples/recaptcha_v3.py +++ b/examples/recaptcha_v3.py @@ -3,7 +3,7 @@ import time from captcha_solver_api.tasks import RecaptchaV3TaskProxyless -from common import create_client, required_env, show_success, wait_for_xpath +from common import create_client, logged_example, required_env, show_success, wait_for_xpath from selenium.webdriver.support.ui import WebDriverWait from seleniumbase import Driver @@ -18,12 +18,14 @@ """ +@logged_example def main() -> None: with Driver(browser="chrome", headless=False) as driver, create_client() as client: driver.get(URL) params = WebDriverWait(driver, 30).until( lambda current: current.execute_script(FIND_PARAMS) ) + print("Parameters sitekey and action received") solution = client.solve( RecaptchaV3TaskProxyless( websiteURL=URL, @@ -36,7 +38,9 @@ def main() -> None: "window.verifyRecaptcha(arguments[0]);", solution["gRecaptchaResponse"], ) + print("The token is sent") wait_for_xpath(driver, SUBMIT_LOCATOR).click() + print("Pressed the Check button") show_success(driver) time.sleep(5) diff --git a/examples/turnstile.py b/examples/turnstile.py index 3b6868e..2251f2b 100644 --- a/examples/turnstile.py +++ b/examples/turnstile.py @@ -3,7 +3,14 @@ import time from captcha_solver_api.tasks import TurnstileTaskProxyless -from common import create_client, fill_response_field, required_env, show_success, wait_for_xpath +from common import ( + create_client, + fill_response_field, + logged_example, + required_env, + show_success, + wait_for_xpath, +) from seleniumbase import Driver URL = required_env("TARGET_URL") @@ -11,6 +18,7 @@ SUBMIT_LOCATOR = "//button[@type='submit']" +@logged_example def main() -> None: with Driver(browser="chrome", headless=False) as driver, create_client() as client: driver.get(URL) @@ -18,10 +26,13 @@ def main() -> None: sitekey = widget.get_attribute("data-sitekey") if not sitekey: raise RuntimeError("No Turnstile sitekey found") + print(f"Sitekey received: {sitekey}") solution = client.solve(TurnstileTaskProxyless(websiteURL=URL, websiteKey=sitekey)) fill_response_field(driver, "cf-turnstile-response", solution["token"]) + print("Token sent") wait_for_xpath(driver, SUBMIT_LOCATOR).click() + print("Pressed the Check button") show_success(driver) time.sleep(5)