A small Python HTTP server that drives a real headless Chromium via
Playwright to solve VK's not_robot_captcha. This is the only reliable
way to pass the bot detection because the captchaNotRobot.check request
must come from a real browser with a real FingerprintJS visitor_id
(browser_fp) — a value computed from canvas/webgl/font fingerprinting
that cannot be faked from Go code alone.
== How it works ==
1. Go client receives a captcha error from VK with a redirect_uri
pointing at https://id.vk.ru/not_robot_captcha?session_token=...
2. Go client (with -captcha-solver http://127.0.0.1:8766) POSTs
{"redirect_uri": "..."} to this server
3. The server:
- Opens the URL in headless Chromium
- Waits for #not-robot-captcha-checkbox to appear
- Generates a realistic mouse path (cubic Bezier + jitter)
from a random start point to the checkbox center
- Clicks the checkbox
- Intercepts the captchaNotRobot.check response and extracts
success_token
4. Returns {"success_token": "...", "elapsed": 6.0} (or {"error": ...})
5. Go client uses the success_token to complete calls.getAnonymousToken
Typical solve time: 6-8 seconds.
== Files ==
scripts/captcha_solver.py
HTTP server on 127.0.0.1:8766 (single-threaded because Playwright
sync API requires it). Reuses one Chromium instance across requests
(~500ms startup amortized). Health endpoint at GET /health.
deploy/vk-captcha-solver.service
systemd unit for production deployment.
== Setup (server) ==
apt install python3-pip
pip3 install --break-system-packages playwright
python3 -m playwright install chromium
python3 -m playwright install-deps chromium
cp scripts/captcha_solver.py /root/
cp deploy/vk-captcha-solver.service /etc/systemd/system/
systemctl enable --now vk-captcha-solver
== Setup (Termux, for on-device solving) ==
pkg install python
pip install playwright requests
playwright install chromium
playwright install-deps chromium
python3 ~/captcha_solver.py --listen 127.0.0.1:8766
== Client usage ==
./vk-turn-proxy \
-vk-link "https://vk.com/call/join/..." \
-peer <host:port> \
-n 8 -udp \
-captcha-solver http://127.0.0.1:8766
If the solver is unreachable, the client falls back to:
1. inline auto-captcha (PoW v2 + initSession — see previous commit)
2. slider POC
3. manual captcha (browser opens, user solves)
== Tested end-to-end ==
On a real VK call link, from a datacenter IP (201.51.28.86) that
previously always got status:BOT:
[STREAM 1] [Captcha] Using Playwright solver (real Chromium)...
[STREAM 1] [Captcha] Calling Playwright solver at http://127.0.0.1:8766/solve
[STREAM 1] [Captcha] Playwright solver returned success_token (elapsed=6.0s)
[STREAM 1] [VK Auth] Success with client_id=6287487