Inside TikTok's CAPTCHA: collection and verification
Published Fri Dec 26 2025
Note: This post is for educational and research purposes only. It does not encourage or endorse bypassing security mechanisms, violating terms of service, or engaging in unlawful activity. Any actions taken based on this content are the sole responsibility of the reader.
Finding the right script
When you try to log in to TikTok, if your IP appears suspicious, you are using a VPN, or your browser profile seems unusual, you are often instantly presented with a CAPTCHA. One common type is the “whirl” or “rotate” CAPTCHA.
It looks something like this:
I encountered this when using the email/username login method. I inspected the network traffic to see where the images come from and found that it loads two images and overlays them. The goal is to determine the correct drag distance for the slider.
I found some scripts on GitHub that used OpenCV, but they didn’t work out-of-the-box. I integrated their logic into my Playwright script to test it. With a few adjustments, it could determine the correct angle.
Analysis
Unlike Cloudflare, there were no debugger; statements to detect if DevTools are open. This made it easier to analyze its behavior.
After the CAPTCHA loaded, I added a breakpoint on the mouse “click” event, but it didn’t pause execution no matter where I clicked. Next, I set a conditional XHR breakpoint on captcha/verify.
Here’s how it looks:
This triggered the breakpoint. I could see the payload, but it was encrypted:
The request loads a massive ~70k line CAPTCHA script.
Frustrated with the lack of progress, I decided to try one last approach:
The script likely listens for specific events when the slider is dragged: ['mousemove', 'pointermove', 'touchmove']. I wrote a script to intercept these events and added a debugger statement to verify if they were triggered.
After some effort, I finally observed the data collection process.
The script attaches a mousemove listener to the window. It collects mouse movement data in a reply array, sampling every 5-15ms until the mouse button is released.
This data is then encrypted, likely along with the CAPTCHA’s unique ID and the user ID assigned upon the first visit. I won’t go into the exact encryption details here, but the overall mechanism is quite interesting.
The whirl CAPTCHA is just one of several types used by TikTok. Others include:
- Whirl
- Icon
- Voice
- Hcaptcha
- Hashcash
- Arkose
- Geetest
The CAPTCHA doesn’t load every time; the system likely calculates a risk score to decide whether to present a challenge.
TikTok’s Sladar system
TikTok’s Sladar system constantly collects browser data. By inspecting the URLs, I identified the following data points:
browser_name=Mozilla
browser_version=5.0 (Windows)
browser_language=en-US
browser_platform=Win32
os=windows
device_platform=web_pc
screen_width=1536
screen_height=864
is_fullscreen=false
cookie_enabled=true
region=US
tz_name=America/New_York
priority_region=
browser_language=en-US
user_is_login=false
focus_state=true
is_page_visible=true
browser_online=true
history_len=2
fromWeb=1
from_page=
referer=
app_name=tiktok_web
channel=tiktok_web
aid=1988
app_language=en
webcast_language=en
It turned out to be relatively straightforward to understand what it was doing, though locating the data required some effort. If I find time, I will write a follow-up post to expand on these findings.
Disclaimer
This article is provided strictly for educational and academic discussion of security mechanisms. It is not intended to encourage, facilitate, or endorse the circumvention of safeguards, abuse of services, or violation of any platform’s terms of service or applicable laws.
The techniques, concepts, and observations discussed are presented for awareness and defensive research purposes only. Any application of this information outside a lawful, authorized, and ethical context is solely the responsibility of the reader.
The author makes no warranties regarding the legality, correctness, or suitability of applying any information from this post and assumes no liability for misuse.