Captcha bypass tutorials

How to bypass slider captcha

Demo repository with examples: github.com/2captcha/custom-slider-demo

The code in this article is a reference example. Every slider captcha implementation is unique: websites use different structures, validation checks, and behavioral analyzers. Full adaptation to your specific use case is up to you.


Introduction

Slider captchas are widely used on websites to prevent bots from accessing restricted content or performing unauthorized actions. While they offer a simple and user-friendly way to verify human users, they can also limit accessibility, frustrate legitimate users, and create challenges when testing applications or automating workflows.

For everyday users, it is straightforward: just one smooth swipe with a mouse or finger. For developers testing their own apps or automating legitimate tasks, it becomes a technical puzzle. Simple clicks at predefined coordinates no longer work: modern protection systems analyze not just the final result, but the entire interaction process.

Key insight: Modern captchas evaluate not only where you move the slider, but also how you move it. Behavioral patterns like mouse jitter, pauses, non-linear trajectories, and reaction time are all part of the verification.


Pros and Cons

Advantages

  • Easy to implement: Integrates with minimal technical setup.
  • Accessible: Requires only basic mouse or touch interaction.
  • Mobile-friendly: Natural swipe gestures work well on touchscreens.

Disadvantages

  • Accessibility concerns: May exclude users with motor impairments.
  • Vulnerable to automation: Can be bypassed with advanced scripting techniques.
  • User friction: Poor implementation can degrade the user experience.

How Slider Captcha Works

Understanding the internal logic is the first step toward bypassing it. The verification process breaks down into four stages:

  1. Task generation
    The server creates a unique image with a "cutout" area and a separate puzzle piece. Each task is tied to a session ID and has a limited lifespan (usually 30 to 120 seconds).

  2. Telemetry collection
    As the user interacts with the slider, JavaScript records:

    • Cursor coordinates (clientX, clientY)
    • Timestamps for every mousemove event
    • Speed, acceleration, micro-movements, and pauses
    • Instances where the cursor leaves the track area
  3. Server-side analysis
    The collected data undergoes two checks:

    • Visual: Does the final position match the expected offset?
    • Behavioral: Does the movement trajectory resemble human behavior?
  4. Token issuance
    If both checks pass, the server returns a cryptographic token or sets a secure cookie. This marker confirms successful verification and is included in subsequent requests to the protected resource.


The Solution

To bypass a slider captcha, you need to calculate the trajectory for moving the slider. In most cases, two points are enough:

  1. Starting point: Usually static (left edge of the track), determined once.
  2. Ending point: Coordinates of the center of the target puzzle piece.

The second point can be identified by our service operators: you send the captcha image with instructions, they mark the correct coordinate, and the API returns the result. This is handled via the Coordinates method in our documentation.


The Approach

Reliable bypass requires implementing three independent but connected mechanisms:

1. Visual solving

Determining the exact coordinates where the slider should stop. Writing custom computer vision algorithms (template matching, contour analysis, neural networks) is inefficient for production: every site uses different styles, adds noise, or changes dimensions. The optimal path is to delegate recognition to our API service, where tasks are solved by human operators or trained ML models.

2. Human-like behavior simulation

Once you have the coordinates, moving the cursor in a straight line is not enough. Human hand movement includes:

  • Smooth acceleration at the start
  • Small vertical oscillations (natural hand tremor)
  • Mid-path corrections
  • Gradual deceleration near the target
  • Micro-pauses and random delays between mousemove events

These behaviors are implemented using easing functions, sinusoidal noise, and randomized timing.

3. Automation masking

Automation browsers (Playwright, Selenium, Puppeteer) leave traces: the navigator.webdriver flag, specific headers, missing plugins, or unnatural window dimensions. Modern protection systems scan for these signals before the captcha even loads. Masking includes:

  • Overriding navigator properties
  • Using browser launch arguments that hide automation signals
  • Spoofing realistic User-Agent strings
  • Adding natural delays between page load stages

Setup

Installing dependencies (Node.js)

bash Copy
# Initialize project
npm init -y

# Install packages
npm install puppeteer @2captcha/captcha-solver dotenv

# Enable ES6 module support
npm pkg set type="module"

Installing dependencies (Python)

bash Copy
pip install playwright requests
playwright install chromium

Configuring your API key

Create a .env file in your project root:

env Copy
APIKEY=your_2captcha_api_key

Loading the key in code:

javascript Copy
// JavaScript
import { config } from 'dotenv';
config();
const solver = new Solver(process.env.APIKEY);
python Copy
# Python
import os
from dotenv import load_dotenv
load_dotenv()
API_KEY = os.getenv("APIKEY")

Conceptual Workflow

Instead of copying code blindly, let's walk through the logic you will adapt for your project:

  1. Environment setup. Launch the browser in a user-like mode. Disable automation detection flags and set realistic window parameters.
  2. Navigation and waiting. Go to the target page. Wait for the DOM to fully load and for the captcha element to appear. Handle any consent banners that may overlay the interface.
  3. Image extraction. Capture a screenshot of the captcha area or extract the canvas/img element as a base64 string. Ensure the image is readable and intact.
  4. Sending for solving. Submit the base64 string to the solver API with a clear text instruction (e.g., "Click the center of the puzzle piece"). Wait for the response containing the X and Y offset coordinates.
  5. Trajectory calculation. Determine the slider's starting position (usually the left edge). Calculate the endpoint: start_x + offset_x. Generate an array of intermediate coordinates using an easing function and random noise.
  6. Simulating the drag. Move the cursor to the start point, pause briefly, trigger mouse.down(), send move events along the generated trajectory with randomized delays, then trigger mouse.up().

Code Example

Minimal Python example (Playwright)

python Copy
import asyncio
import math
import random
import requests
from playwright.async_api import async_playwright

API_KEY = "your_api_key"

def get_eased_trajectory(start_x, start_y, end_x, end_y, steps=120):
    """Generate points with smooth easing and natural noise."""
    points = []
    for i in range(steps + 1):
        t = i / steps
        ease = 2 * t * t if t < 0.5 else -1 + (4 - 2 * t) * t
        noise_x = math.sin(t * math.pi * 6) * random.uniform(-2.5, 2.5)
        noise_y = math.cos(t * math.pi * 4) * random.uniform(-1.0, 1.0)
        x = start_x + (end_x - start_x) * ease + noise_x
        y = start_y + (end_y - start_y) * ease + noise_y
        delay = random.uniform(8, 18) if 0.1 < t < 0.9 else random.uniform(25, 45)
        points.append((x, y, delay))
    return points

async def solve_slider(url, canvas_selector, slider_selector):
    async with async_playwright() as p:
        browser = await p.chromium.launch(
            headless=True,
            args=["--disable-blink-features=AutomationControlled"]
        )
        page = await browser.new_page()
        
        # Mask automation signals
        await page.add_init_script("""
            Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
            Object.defineProperty(navigator, 'languages', { get: () => ['en-US','ru-RU'] });
        """)
        
        await page.goto(url, wait_until="networkidle", timeout=30000)
        await page.wait_for_selector(canvas_selector, timeout=10000)
        
        # Extract captcha image as base64
        captcha_b64 = await page.evaluate(f"""
            () => document.querySelector('{canvas_selector}').toDataURL('image/png').split(',')[1]
        """)
        
        # Send to solver API
        resp = requests.post("https://api.2captcha.com/createTask", json={
            "clientKey": API_KEY,
            "task": {
                "type": "CoordinatesTask",
                "body": captcha_b64,
                "comment": "Find puzzle center | Click the center of the puzzle piece"
            }
        }).json()
        
        task_id = resp.get("taskId")
        
        # Poll for result
        while True:
            await asyncio.sleep(3)
            res = requests.get("https://api.2captcha.com/getTaskResult",
                               json={"clientKey": API_KEY, "taskId": task_id}).json()
            if res.get("status") == "ready":
                offset_x = res["solution"]["x"]
                break
        
        # Simulate human-like drag
        slider = await page.query_selector(slider_selector)
        box = await slider.bounding_box()
        start = (box["x"] + box["width"]/2, box["y"] + box["height"]/2)
        end = (start[0] + offset_x - random.randint(2, 5), start[1] + random.uniform(-0.5, 0.5))
        
        await page.mouse.move(*start)
        await asyncio.sleep(random.uniform(0.4, 0.8))
        await page.mouse.down()
        
        for x, y, delay in get_eased_trajectory(*start, *end):
            await page.mouse.move(x, y)
            await asyncio.sleep(delay / 1000)
            
        await page.mouse.up()
        await page.wait_for_selector(".success, .verified", timeout=8000)
        print("✅ Captcha solved")
        await browser.close()

📌 Note: This is the core algorithm. A production-ready implementation will need iframe handling, retry logic, logging, and selector adaptation.


Running the Demo Code

You can also clone the demo repository, install dependencies, and run:

bash Copy
# Clone the repository
git clone https://github.com/2captcha/custom-slider-demo.git
cd custom-slider-demo

# Install dependencies
npm install  # or yarn install

# Configure your API key
echo "APIKEY=your_key" > .env

# Run the demo
npm start

Adapting the Template to Your Project

  1. Find the right selectors. Open DevTools (F12), locate the captcha image and slider elements, copy their unique CSS selectors, and replace canvas and .slider-button in the example.
  2. Handle iframes. If the captcha loads inside a frame:
    python Copy
    # Playwright Python
    frame = page.frame_locator("iframe[src*='captcha']")
    await frame.locator("canvas").wait_for()
    javascript Copy
    // Puppeteer JS
    const frame = page.frames().find(f => f.url().includes('captcha'));
    if (frame) await frame.waitForSelector('canvas');
  3. Refine your instructions. The clearer your comment in the API request, the higher the chance of an accurate solution:
    "Click exact center of puzzle piece | Find the middle of the sliding fragment"
  4. Fine-tune the trajectory. If the site rejects the solution: increase steps to 150–200, amplify the noise amplitude, or add random micro-pauses inside the movement loop.
  5. Debug in visible mode. Set headless=False to watch the cursor move in real time and adjust logic on the fly.

Common Questions

Why use Puppeteer or Playwright?

These frameworks provide low-level access to browser events like mousemove, mousedown, and mouseup. This level of control is essential for mimicking human interaction and bypassing behavioral checks.

Why doesn't the captcha solve on the first try?

Issue Solution
Inaccurate coordinates Refine your comment instruction or add a visual guide image
Automation detected Strengthen navigator masking and add launch arguments
Wrong selectors Verify the current page structure using DevTools
Captcha inside iframe Use frame_locator or iterate through page.frames()

How do I debug the script?

Set headless: false in your browser launch options to watch actions in real time. Add logging to capture browser output:

javascript Copy
page.on('console', msg => console.log('Browser:', msg.text()));
page.on('pageerror', err => console.error('Error:', err.message));

Helpful Resources


In short: Bypassing a slider captcha follows a clear, repeatable flow. You grab the image, send it for recognition, guide the slider with natural motion, and verify the server's response. The code in this article provides the foundation. Your job is to plug in your selectors, tune the timing, and handle edge cases for your specific target. When accurate targeting meets lifelike cursor behavior, the script runs reliably and smoothly.