Skip to content

Selenium Example: TikTok Slider Captcha ​

This example shows how to solve the TikTok slider captcha in a Selenium script written in Python. The script does not try to find the gap by itself. It sends the captcha images to the Cap.guru API, gets back the distance the slider has to travel and then drags it with Selenium's ActionChains.


logo

How the script works ​

  1. Opens the TikTok login page, fills in the form and waits for the captcha.
  2. Reads the URLs of the background image and the puzzle piece.
  3. Sends both images to in.php and gets a task ID.
  4. Asks res.php for the result every 5 seconds until the answer is ready.
  5. Drags the slider by the returned offset. If the first attempt fails, it tries once more.

Before you run it ​

Install the packages with pip install selenium requests. The example uses Chrome, so make sure Chrome is installed. Then replace YOUR_API_KEY at the top of the script with the key from your dashboard, and put your own login details in place of the test ones.

Code ​

Python
py
import requests
import base64
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import logging
import json
import re

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')
logger = logging.getLogger()

# CAPTCHA solving API key
API_KEY = "YOUR_API_KEY"

# Set up Chrome WebDriver
options = webdriver.ChromeOptions()
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=options)

driver.execute_cdp_cmd("Network.clearBrowserCache", {})

def get_captcha_images(driver):
    """
    Extract CAPTCHA image URLs from the webpage.
    """
    try:
        # Wait for the images to load
        background_img = WebDriverWait(driver, 15).until(
            EC.presence_of_element_located((By.XPATH, "//img[contains(@class, 'cap-h-[170px]')]"))
        )
        puzzle_img = WebDriverWait(driver, 15).until(
            EC.presence_of_element_located((By.XPATH, "//img[contains(@class, 'cap-absolute')]"))
        )

        background_url = background_img.get_attribute("src")
        puzzle_url = puzzle_img.get_attribute("src")
        logger.info(f"Background Image URL: {background_url}")
        logger.info(f"Puzzle Image URL: {puzzle_url}")
        return background_url, puzzle_url
    except Exception as e:
        logger.error(f"Error fetching CAPTCHA images: {e}")
        return None, None

def solve_slider_captcha(background_url, puzzle_url):
    """
    Send CAPTCHA images to the cap.guru API for solving and retrieve the X offset.
    """
    try:
        # Convert URLs to Base64 (in case required by API)
        background_base64 = base64.b64encode(background_url.encode()).decode()  # URL as Base64
        puzzle_base64 = base64.b64encode(puzzle_url.encode()).decode()  # URL as Base64

        # Send data to API
        payload = {
            "key": API_KEY,
            "method": "base64",
            "textinstructions": "koleso",
            "click": "geetest",
            "body0": background_base64,
            "body1": puzzle_base64,
            "json": 1
        }

        response = requests.post("http://api2.cap.guru/in.php", data=payload)

        if response.status_code == 200 and response.json().get("status") == 1:
            task_id = response.json()["request"]
            logger.info(f"CAPTCHA Task ID: {task_id}")
        else:
            logger.error(f"Failed to send CAPTCHA images to API. Response: {response.text}")
            return None

        # Poll for the result
        for _ in range(10):
            time.sleep(5)
            result = requests.get(f"http://api2.cap.guru/res.php?key={API_KEY}&action=get&id={task_id}&json=1")
            if result.status_code == 200:
                response_data = result.json()
                if response_data.get("status") == 1:
                    coordinates = response_data["request"]
                    coordinates = re.sub(r"[^0-9,]", "", coordinates)
                    logger.info(f"CAPTCHA solved: {coordinates}")
                    x_offset = int(coordinates.split(',')[1])
                    x_offset = round(x_offset / 271 * 284)  # Adjust offset scale
                    return x_offset
                elif response_data.get("request") == "CAPCHA_NOT_READY":
                    logger.info("CAPTCHA not ready yet. Retrying...")
                else:
                    logger.error(f"Error in CAPTCHA response: {response_data}")
                    return None
            else:
                logger.error(f"Error in API request: {result.text}")
                return None
        return None
    except Exception as e:
        logger.error(f"Error solving CAPTCHA: {e}")
        return None

def move_slider(driver, x_offset):
    """
    Move the slider based on the calculated X offset.
    """
    try:
        slider = WebDriverWait(driver, 15).until(
            EC.visibility_of_element_located((By.ID, "captcha_slide_button"))
        )
        action = ActionChains(driver)
        action.click_and_hold(slider).pause(2)
        action.move_by_offset(x_offset, 0).pause(35.5)
        action.release().perform()
        logger.info(f"Slider moved by {x_offset} pixels.")
    except Exception as e:
        logger.error(f"Error moving slider: {e}")

def login_to_tiktok():
    """
    Perform login to TikTok with CAPTCHA solving.
    """
    try:
        # Open TikTok login page
        driver.get("https://www.tiktok.com/login/phone-or-email/email")
        logger.info("Opened TikTok login page.")

        # Input email and password
        email_field = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.XPATH, "//input[@placeholder='Email or username']"))
        )
        email_field.send_keys("exampl3223243email")

        password_field = driver.find_element(By.XPATH, "//input[@placeholder='Password']")
        password_field.send_keys("3223d234asda")

        submit_button = driver.find_element(By.XPATH, "//button[@type='submit']")
        submit_button.click()
        logger.info("Submitted login form.")

        # Fetch CAPTCHA image URLs
        background_url, puzzle_url = get_captcha_images(driver)
        if not background_url or not puzzle_url:
            logger.error("Could not retrieve CAPTCHA images.")
            return

        # Solve the CAPTCHA
        retries = 2
        x_offset = None
        for attempt in range(retries):
            x_offset = solve_slider_captcha(background_url, puzzle_url)

            if x_offset:
                move_slider(driver, x_offset)
                break
            else:
                logger.error(f"Failed to solve CAPTCHA. Attempt {attempt + 1} of {retries}. Retrying...")
                time.sleep(5)
        if not x_offset:
            logger.error("Failed to solve CAPTCHA after multiple attempts.")

        # Check login status
        time.sleep(5)
        if "login" not in driver.current_url:
            logger.info("Login successful!")
        else:
            logger.warning("Login failed, check credentials or CAPTCHA.")
    except Exception as e:
        logger.error(f"Error during login: {e}")
    finally:
        driver.quit()

if __name__ == "__main__":
    login_to_tiktok()

The request parameters for this captcha are described on the TikTok captcha API page. For slider tasks in general, see How to work with slider.