Skip to content
../products
TikTok CaptchaTikTokCaptchaTaskProxyLess

TikTok Captcha Solver, solved in 2.0s.

Solve TikTok / ByteDance's Whirl (rotate) captcha. Send the two challenge images and get back the exact rotation angle, slide proportion and drag distance — drop-in compatible with the standard TikTok-rotate API.

$2.00per 1,000
~2.0savg solve
99%+success
30/mthroughput
innerImage: iVBORw0KGgoAAAANSUhEUg... (b…0.00s
POST/createTask type=TikTokCaptchaTaskProxyLess
taskId tsk_sodm2kse
POLL/getTaskResult status=processing
status ready
token 0x4d98c9b2c24a6...
type: TikTokCaptchaTaskProxyLess● running on production solvers

What is TikTok Captcha?

TikTok — and the rest of ByteDance (CapCut, Lark, Douyin) — protects logins, signups, uploads and other risky actions with the ByteDance "secsdk" captcha. On the web it almost always appears as the Whirl challenge: two stacked circular images, a larger outer ring and a smaller inner disc, under the instruction "Drag the slider to fit the puzzle." You rotate the inner disc with a slider until its picture lines up with the outer ring. Capzy currently supports the Whirl / rotate subtype only. ByteDance also ships slide-puzzle, 3D-shape-match and icon-click variants, but on the web those are vanishingly rare (they live almost entirely in the mobile app). We have wired handlers for them, but they are experimental and not enabled — for production, stick to Whirl. This is a pure image-CV solve. You extract the two circle images from the page, send them to us, and we return the exact rotation angle. You apply the drag in your own browser/session. No proxy is required and the answer is device-independent, so it works no matter how the captcha is sized on screen.

How it works

1

Send Task

POST your TikTokCaptchaTaskProxyLess with the target URL and sitekey to our API. We'll queue it instantly.

2

We Solve

We unwrap both circles to polar coordinates and cross-correlate the outer ring against the inner disc along their shared seam, then refine the peak to sub-degree precision. The output is the exact angle the inner disc must turn to align — returned as angle (degrees), slideProportion (angle / 360) and a ready-to-use distance in pixels.

3

Get Token

Poll getTaskResult — when status is 'ready', the solution contains the token to inject into the target page.

Quick integration

solve.py
import requests, time

API = "https://api.capzy.ai"
KEY = "capzy_your_key_here"

# Step 1: Create task
task = requests.post(f"{API}/createTask", json={
    "clientKey": KEY,
    "task": {
        "type": "TikTokCaptchaTaskProxyLess",
        "innerImage": "iVBORw0KGgoAAAANSUhEUg... (base64 of the inner disc)",
        "outerImage": "/9j/4AAQSkZJRgABAQAAAQ... (base64 of the outer ring)",
        "captchaType": "whirl",
        "sliderWidth": "260"
    }
}).json()

task_id = task["taskId"]
print(f"Task created: {task_id}")

# Step 2: Poll for result
while True:
    result = requests.post(f"{API}/getTaskResult", json={
        "clientKey": KEY,
        "taskId": task_id
    }).json()

    if result["status"] == "ready":
        print("Solved!", result["solution"])
        break
    elif result["status"] == "failed":
        print("Failed:", result.get("errorDescription"))
        break

    time.sleep(1)

# Step 3: Rotate — apply the angle to the captcha image control
angle = result["solution"]["angle"]
# e.g. slider.set_rotation(angle)  or  POST angle=<value> to the site
print(f"rotate by {angle} degrees")

Using your own proxy

Use TikTokCaptchaTask instead of TikTokCaptchaTaskProxyLess to route the solve through your own proxy. This is useful when the target site checks the IP that solved the captcha matches the IP submitting the form.

solve_proxy.py
import requests, time

API = "https://api.capzy.ai"
KEY = "capzy_your_key_here"

# Step 1: Create task
task = requests.post(f"{API}/createTask", json={
    "clientKey": KEY,
    "task": {
        "type": "TikTokCaptchaTask",
        "proxyPort": "8080",
        "proxyType": "http",
        "proxyLogin": "user",
        "captchaType": "whirl",
        "sliderWidth": "260",
        "proxyAddress": "1.2.3.4",
        "innerImageUrl": "https://.../captcha/inner.png",
        "outerImageUrl": "https://.../captcha/outer.jpg",
        "proxyPassword": "pass"
    }
}).json()

task_id = task["taskId"]
print(f"Task created: {task_id}")

# Step 2: Poll for result
while True:
    result = requests.post(f"{API}/getTaskResult", json={
        "clientKey": KEY,
        "taskId": task_id
    }).json()

    if result["status"] == "ready":
        print("Solved!", result["solution"])
        break
    elif result["status"] == "failed":
        print("Failed:", result.get("errorDescription"))
        break

    time.sleep(1)

# Step 3: Rotate — apply the angle to the captcha image control
angle = result["solution"]["angle"]
# e.g. slider.set_rotation(angle)  or  POST angle=<value> to the site
print(f"rotate by {angle} degrees")

additional proxy parameters

proxyTypetypestringreqnohttp / https / socks5. Only needed for the proxy variant, where you send image URLs instead of base64.
proxyAddresstypestringreqyesProxy host/IP we use to download outerImageUrl / innerImageUrl.
proxyPorttypenumberreqyesProxy port.
proxyLogintypestringreqnoProxy username, if authenticated.
proxyPasswordtypestringreqnoProxy password, if authenticated.

Task parameters

captchaTypetypestringreqyesSet to "whirl" (aliases: rotate, spin). The only supported subtype today.
outerImagetypestringreqyesBase64 of the larger OUTER ring image (strip any "data:image/...;base64," prefix). Or send outerImageUrl to have us fetch it.
innerImagetypestringreqyesBase64 of the smaller INNER disc image (strip the data: prefix). Or send innerImageUrl.
sliderWidthtypenumberreqnoRendered width (px) of the slider track in your page. When supplied we return `distance` in px; otherwise compute it yourself from slideProportion.

Solution response

angletypenumberDegrees (0-360) to rotate the inner disc clockwise to align it. Drag distance = (trackWidth - handleWidth) x angle / 360.
slideProportiontypenumberangle / 360 (0-1). Multiply by your rendered slider track width for a device-independent drag distance in px.
distancetypenumberDrag distance in px, pre-computed from the sliderWidth you passed (0 if you didn't pass one — use slideProportion instead).

Example response

Full getTaskResult response shape. The fields in the table above describe what's inside solution — the outer envelope (errorId, status) is identical for every captcha type.

{
  "errorId": 0,
  "status": "ready",
  "solution": {
    "angle": 287,
    "distance": 207,
    "slideProportion": 0.7972
  }
}

Error response

Failures use the same envelope with errorId: 1 plus errorCode + errorDescription. See the error-code reference for the full list.

{
  "errorId": 1,
  "errorCode": "ERROR_CAPTCHA_UNSOLVABLE",
  "errorDescription": "Solver gave up — automatically refunded."
}

Pending response

While the solver is still working, getTaskResult returns status: "processing". Poll every 1–2 seconds until ready or failed.

{
  "errorId": 0,
  "status": "processing"
}

Features

Whirl / rotate solved to sub-degree accuracy
Drop-in return format: angle, slideProportion, distance
No proxy required — IP-independent image-CV
Accepts base64 images or image URLs
Ready-made Playwright & Selenium drag examples
Pay per success — failed solves auto-refunded

task types

proxyless: TikTokCaptchaTaskProxyLess

with proxy: TikTokCaptchaTask

Frequently asked questions

start solving tiktok captcha.

$0.10 in free credits — no card. ~250 free solves to test before you spend.