PerimeterX / HUMAN ACTIVE
PX2/PX3/PX23/PX203/PX182 protocol + WASM captcha automation.
Overview
PerimeterX (now HUMAN Security) uses a multi-event fingerprint protocol:
- › PX2 — init event
- › PX3 — canvas, audio, WebGL fingerprint
- › PX23 / PX203 — high-security hashes
- › PX182 — activity heartbeat
VexSolver sends all events natively in Go, decodes the XOR-encrypted OB responses, and bakes the _px3, _pxhd, _pxde (and _px2 where applicable) cookies. If the site triggers a WASM captcha challenge, VexSolver automatically solves the proof-of-work and simulates the Press & Hold interaction.
Supports first-party, third-party, and hsprotect.net PX deployments (Microsoft / Outlook signup). Auto-detects the AppId and collector URL from the target page; custom deployments can override via the app_id request field.
Cookies returned
- ›
_px3— main session token, RSA-signed by PerimeterX - ›
_pxhd— hardened device ID (UUID) - ›
_pxde— device enrichment payload (timestamp + incident id) - ›
_px2— init token (non-hsprotect deployments)
Step 1 — Submit
curl -X POST https://api.vexsolver.com/api/solve \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://www.zillow.com/",
"proxy": "http://user:pass@your-proxy:8080"
}'
# → { "taskId": "abc123xyz" }Step 2 — Poll
curl -G "https://api.vexsolver.com/api/getTaskResult" \ -H "X-API-Key: sk_live_..." \ --data-urlencode "taskId=abc123xyz" # Retry every 1-2 seconds until status != "pending".
Microsoft / Outlook signup (signup.live.com)
signup.live.com uses a custom hsprotect PX deployment. Pass app_id: "PXzC5j78di" to bypass AppId auto-detection and hit it reliably.
curl -X POST https://api.vexsolver.com/api/solve \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://signup.live.com/signup",
"proxy": "http://user:pass@your-proxy:8080",
"app_id": "PXzC5j78di"
}'Force fresh solve
Pass "fresh": true to bypass our 5-min cache and get a new PerimeterX-signed token on every call.
curl -X POST https://api.vexsolver.com/api/solve \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://signup.live.com/signup",
"proxy": "http://user:pass@your-proxy:8080",
"app_id": "PXzC5j78di",
"fresh": true
}'Pin your own User-Agent (TLS replay)
PerimeterX cross-checks the cookie's UA against the TLS handshake fingerprint on every request. If your TLS client is fixed at a specific Chrome version (e.g. Chrome 146), pass that exact UA in the user_agent field and VexSolver will mint the cookie with EXACTLY that UA — so your replay TLS + cookie UA stay aligned.
curl -X POST https://api.vexsolver.com/api/solve \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://identity.walmart.com/account/login",
"app_id": "PXu6b0qd2S",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
"fresh": true
}'When omitted, VexSolver picks from a randomized desktop pool (Chrome 131–147 / macOS / Android / iPad). The poll result's user_agent field always tells you which UA was actually used — replay with that exact value.
Poll result shape
{
"success": true,
"vendor": "perimeterx",
"source": "px_solver",
"target": "https://signup.live.com/signup",
"attempts": 1,
"cached": false,
"elapsed_ms": 596,
"solve_ms": 596,
"solved_at": 1776997536,
"expires_at": 1776998736,
"ttl_sec": 1200,
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
"proxy_fp": "f2e8631d8304",
"cookies": "_px3=181114e3...; _pxde=e855ddba...; _pxhd=1160a60f-...",
"cookie_map": {
"_px3": "181114e3045c626fbb8076478ac086...",
"_pxde": "e855ddbab4b77a76cc714f537a478a31...",
"_pxhd": "1160a60f-3f81-11f1-911b-9812291b09e9"
}
}- Replay through the same proxy you passed to
/api/solve - Replay with the same User-Agent — either pin it via the request
user_agentfield, or read it back from the poll result and replay with that exact value - Keep the full cookie set together (
_px3 + _pxde + _pxhd)
Go end-to-end example
// 1. Submit
body, _ := json.Marshal(map[string]string{
"url": "https://signup.live.com/signup",
"proxy": "http://user:pass@your-proxy:8080",
"app_id": "PXzC5j78di",
})
req, _ := http.NewRequest("POST", "https://api.vexsolver.com/api/solve", bytes.NewReader(body))
req.Header.Set("X-API-Key", "sk_live_...")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
var sub struct{ TaskID string `json:"taskId"` }
json.NewDecoder(resp.Body).Decode(&sub)
resp.Body.Close()
// 2. Poll
var out struct {
Status string `json:"status"`
Success bool `json:"success"`
Cookies string `json:"cookies"`
UserAgent string `json:"user_agent"`
}
poll := "https://api.vexsolver.com/api/getTaskResult?taskId=" + sub.TaskID
for i := 0; i < 60 && out.Status != ""; i++ {
time.Sleep(2 * time.Second)
r, _ := http.NewRequest("GET", poll, nil)
r.Header.Set("X-API-Key", "sk_live_...")
rr, _ := http.DefaultClient.Do(r)
json.NewDecoder(rr.Body).Decode(&out)
rr.Body.Close()
if out.Status != "pending" { break }
}
// 3. Replay
req2, _ := http.NewRequest("GET", "https://signup.live.com/signup", nil)
req2.Header.Set("Cookie", out.Cookies)
req2.Header.Set("User-Agent", out.UserAgent) // MUST match our solve UA
// ...and send it through the SAME proxy you passed above.
identity.walmart.com), Wayfair, Zillow, signup.live.com, login.live.com, skyscanner (all TLDs), crunchbase, indeed, ticketmaster, stockx, seatgeek, fubo.tv, spothero, belk, westmarine, and dozens more.Mobile SDK (Android / iOS) — /api/solve-mobile
Native iOS and Android apps that ship with PerimeterX's mobile SDK (com.perimeterx.mobile_sdk) speak a different protocol than the web flow: a single /api/v1/collector/mobile POST mints session identifiers, then X-PX-* headers (not cookies) carry the session on every outgoing request.
VexSolver's /api/solve-mobile endpoint follows the same async submit + poll pattern as /api/solve:
curl -X POST https://api.vexsolver.com/api/solve-mobile \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"app_id": "PXu6b0qd2S",
"app_package": "com.walmart.android",
"app_name": "Walmart",
"app_version": "26.17",
"user_agent": "okhttp/4.12.0",
"proxy": "http://USER:PASS@your-proxy:PORT"
}'
# → { "taskId": "..." }, poll /api/getTaskResult as usual.Final poll result shape:
{
"success": true,
"vendor": "perimeterx-mobile",
"vid": "9c333cf0-8099-400f-b9bb-e58c7115a401",
"uuid": "5b8a9197-4b93-4314-b310-e4ce02b40881",
"user_agent": "okhttp/4.12.0",
"headers": {
"X-PX-AUTHORIZATION": "PerimeterX Android SDK/3.3.0",
"X-PX-OS": "Android",
"X-PX-OS-VERSION": "14",
"X-PX-MOBILE-SDK-VERSION": "3.3.0",
"X-PX-VID": "9c333cf0-...",
"X-PX-UUID": "5b8a9197-...",
"X-PX-DEVICE-FP": "...",
"X-PX-DEVICE-MODEL": "Pixel 7"
},
"captcha_solved": false,
"elapsed_ms": 317
}Attach the headers map to every outgoing request your bot sends to the protected backend. Pass the same user_agent as your TLS client. The same proxy you supplied here must be used on replay.
Typical performance
- › Cache hit: 1-30 ms (
cached: true) - › Replay template: 500 ms - 2 s
- › Cold capture: 3-8 seconds
- › With WASM captcha: 10-12 seconds
- › Mobile (Init only): ~300 ms via
/api/solve-mobile - › Mobile (HoldCaptcha solve): 8-12 seconds
