Before you submit — these must be correct
If any of these are wrong, your token may be accepted by our solver but rejected or scored poorly by the target site. We can’t detect these mismatches for you.
- Pass the SAME proxy + User-Agent the 403 was served to — the clearance binds to that (IP, UA).
- Send the block fresh — PerimeterX blocks expire, so replay the solved clearance promptly.
What is PerimeterX Block-Replay?
PerimeterX (now HUMAN Security) scores requests and, when it blocks, serves a 403 with a press-and-hold challenge tied to that exact session (its _pxvid / uuid). Block-Replay is the deterministic variant: instead of starting fresh, you hand us the block you already hit, and we solve THAT session so the clearance binds to your own visitor ID and validates on replay.
How it works
Send Task
POST your AntiPerimeterXBlockTask with the target URL and sitekey to our API. We'll queue it instantly.
We Solve
Send the raw 403 body (blockData), the cookies from that response, your exact User-Agent, and the same proxy the block came from. We adopt the session, navigate with it, solve the guaranteed press-and-hold, and return the PerimeterX clearance cookies (_px3 / _pxvid / _pxhd) bound to your _pxvid — replay from the same proxy + UA.
Get Token
Poll getTaskResult — when status is 'ready', the solution contains the token to inject into the target page.
Quick integration
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": "AntiPerimeterXBlockTask",
"type": "AntiPerimeterXBlockTask",
"cookies": "_pxvid=…; _pxhd=…",
"blockData": "<raw 403 body>",
"proxyPort": "10001",
"proxyType": "http",
"userAgent": "Mozilla/5.0 …",
"proxyLogin": "user",
"websiteURL": "https://www.example.com/account",
"proxyAddress": "gw.your-proxy.com",
"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)
Using the result
# Step 3: Use the result — set every cookie on a session jar
sol = result["solution"]
session = requests.Session()
for c in sol["cookies"]:
session.cookies.set(c["name"], c["value"], domain=c.get("domain"), path=c.get("path", "/"))
session.headers["User-Agent"] = sol.get("userAgent", "")
# IMPORTANT: route through the SAME proxy you supplied at solve time
resp = session.get("https://target.example.com/", proxies={
"http": "http://USER:PASS@PROXY_HOST:PORT",
"https": "http://USER:PASS@PROXY_HOST:PORT",
})
print(resp.status_code, len(resp.text), "bytes")Task parameters
typetypestringreqyesAntiPerimeterXBlockTask (with your proxy).websiteURLtypestringreqyesThe protected page your original request hit.blockDatatypestringreqyesThe raw 403 block response body (HTML interstitial or JSON/XHR payload).cookiestypestringreqyesThe cookies from the blocked response (string, list, or map).userAgenttypestringreqyesThe exact User-Agent your blocked request used.blockModetypestringreqnohtml | xhr | json | auto (default auto).proxyTypetypestringreqnohttp, https, or socks5.proxyAddresstypestringreqyesProxy host (IP or hostname). Required — the solve is IP-bound.proxyPorttypeintegerreqyesProxy port.proxyLogintypestringreqnoProxy username, if your proxy needs auth.proxyPasswordtypestringreqnoProxy password, if your proxy needs auth.Solution response
cookiestypearrayPerimeterX clearance cookies {name, value, domain, path} (_px3, _pxvid, _pxhd).tokentypestringThe primary _px3 clearance value.uuidtypestringThe PerimeterX session UUID (_pxvid) the clearance is bound to.vidtypestringVisitor ID.userAgenttypestringThe User-Agent used — reuse verbatim on replay.ipBoundtypebooleanAlways true — replay through the same proxy.consumedBlocktypebooleanTrue — the clearance was minted from your supplied block.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": {
"uuid": "<_pxvid>",
"token": "<_px3 value>",
"cookies": [
{
"name": "_px3",
"path": "/",
"value": "<clearance>",
"domain": ".example.com"
}
],
"ipBound": true,
"userAgent": "Mozilla/5.0 …",
"consumedBlock": true
}
}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
task types
required: AntiPerimeterXBlockTask