SolveHub

CAPTCHA types · perimeterx

PerimeterX (HUMAN) Solver API: _px3 Cookies via REST

Solve PerimeterX / HUMAN bot protection with the SolveHub API: app ID, target site, proxy and browser cookies. Learn which fields to send and how to consume the returned cookies.

For authorized QA automation and browser integration. Use only on websites and workflows you have permission to test.

Create this task type by sending the JSON below to POST /v1/tasks with Authorization: Bearer <API_KEY>, Content-Type: application/json and an Idempotency-Key. Check availability in live prices first; see the quick start for the full create-and-poll flow.

Requires the page address websiteURL, the PerimeterX application ID websiteKey (pxAppId), and an HTTP proxy. useragent is optional. Do not substitute a UUID or visitor ID that appears on the page for the application ID.

Request fields

The outer type and task are required; all task.* paths below are inside the task object. Field names are case-sensitive. Length limits are measured in UTF-8 bytes.

Field Type Required Limit Description
type String Yes Must be perimeterx Platform task type.
task JSON object Yes ≤ 7 MiB Task parameters for this type.
task.type String No Must be perimeterx if provided Compatibility with the legacy request format; can be omitted in new integrations.
task.websiteURL HTTP(S) URL Yes ≤ 2048 bytes Full URL of the target page to solve, without username or password.
task.websiteKey String Yes ≤ 256 bytes PerimeterX application ID, i.e. pxAppId; a visitor UUID/vid cannot be used instead.
task.useragent String No ≤ 512 bytes Custom browser User-Agent; for subsequent requests, prefer the actually returned solution.useragent.
task.proxyType String Yes http only Proxy protocol; must be http if provided.
task.proxyAddress String Yes ≤ 256 bytes Proxy IP or hostname; must be provided together with proxyPort.
task.proxyPort String Yes 1–5 bytes, value 1–65535 Proxy port; must be a quoted numeric string.
task.proxyLogin String No ≤ 256 bytes Username if the proxy requires authentication; must not be provided without the address and port.
task.proxyPassword String No ≤ 256 bytes Password if the proxy requires authentication; must not be provided without the address and port.

Create request example

{
  "type": "perimeterx",
  "task": {
    "websiteURL": "https://example.com/protected",
    "websiteKey": "PX_EXAMPLE_APP_ID",
    "proxyType": "http",
    "proxyAddress": "203.0.113.10",
    "proxyPort": "8080"
  }
}

cURL call

Replace the Key, site information, and proxy in the example with your actual values; keep the Idempotency-Key unchanged for the same business request.

curl -sS -X POST 'https://www.tiam.codes/v1/tasks' \
  -H 'Authorization: Bearer sh_REPLACE_ME' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: example-perimeterx-0001' \
  --data-binary @- <<'JSON'
{
  "type": "perimeterx",
  "task": {
    "websiteURL": "https://example.com/protected",
    "websiteKey": "PX_EXAMPLE_APP_ID",
    "proxyType": "http",
    "proxyAddress": "203.0.113.10",
    "proxyPort": "8080"
  }
}
JSON

Create response and polling

A successful creation returns HTTP 202, and the initial status is usually queued. Save the taskId and call GET /v1/tasks/{taskId} roughly every 2–3 seconds. The soft processing time limit for this type is 210 seconds; after the soft limit the task may enter uncertain. Results of accepted tasks can still be verified; clients should not blindly recreate the task with a new Idempotency-Key.

Result fields

Read solution only when status=completed; the table below lists common fields, and the actual fields are those in the task's response.

Field Type How to read
solution.cookies Object Browser session cookies; names are determined by the target page and may include _px3, _pxvid, _pxhd.
solution.useragent String User-Agent to reuse with the same proxy for subsequent requests.
solution.value String, optional Some results return an empty string; it cannot replace the cookies when judging success.

The result consists mainly of solution.cookies and solution.useragent; cookie names vary with the target site's configuration and may include _px3 and _pxvid. Sample result: {"cookies":{"_px3":"EXAMPLE_COOKIE"},"useragent":"Mozilla/5.0 ..."}. Subsequent requests should reuse the solving proxy and the returned User-Agent.

Completed response example (platform fields are separate from the result; price and timestamps are illustrative only):

{
  "taskId": "00000000-0000-4000-8000-000000000001",
  "type": "perimeterx",
  "status": "completed",
  "priceMicros": 1000,
  "traceId": "00000000-0000-4000-8000-000000000002",
  "solution": {
    "value": "",
    "cookies": {
      "_px3": "EXAMPLE_COOKIE",
      "_pxvid": "EXAMPLE_VISITOR"
    },
    "useragent": "Mozilla/5.0 ..."
  },
  "createdAt": "2026-10-05T00:00:00Z",
  "finishedAt": "2026-10-05T00:00:30Z"
}

Python: create and poll

The example uses requests. Replace the placeholder site, proxy, and environment variables with actual values. If the create request hits a network error, retry with the same Idempotency-Key and the same request body; do not change the key. When the task enters uncertain, keep the taskId and continue polling or contact support.

import os
import time
import requests

base = os.environ["SOLVEHUB_URL"].rstrip("/")
headers = {
    "Authorization": f"Bearer {os.environ['SOLVEHUB_API_KEY']}",
    "Idempotency-Key": "your-business-request-perimeterx-001",
}
payload = {
    "type": "perimeterx",
    "task": {
        "websiteURL": "https://example.com/protected",
        "websiteKey": "PX_EXAMPLE_APP_ID",
        "proxyType": "http",
        "proxyAddress": "203.0.113.10",
        "proxyPort": "8080",
    },
}
response = requests.post(f"{base}/v1/tasks", headers=headers, json=payload, timeout=20)
response.raise_for_status()
task_id = response.json()["taskId"]

deadline = time.monotonic() + 15 * 60
while time.monotonic() < deadline:
    response = requests.get(f"{base}/v1/tasks/{task_id}", headers=headers, timeout=20)
    response.raise_for_status()
    task = response.json()
    if task["status"] == "completed":
        solution = task["solution"]
        print(solution.get("cookies", {}), solution.get("useragent"))
        break
    if task["status"] in ("failed", "cancelled"):
        raise RuntimeError(task.get("errorCode", task["status"]))
    if task["status"] == "uncertain":
        print("Task uncertain (pending verification):", task_id)
        break
    time.sleep(3)
else:
    print("Local polling deadline reached; query the original task again later:", task_id)

Failures and troubleshooting

websiteKey must be the application ID pxAppId; do not submit a visitor UUID/vid. proxyPort is a string. For subsequent access, reuse the same proxy, the full cookie set, and solution.useragent.

Common errors on create requests are 400 INVALID_TASK, 402 INSUFFICIENT_BALANCE, 429 TASK_LIMIT_EXCEEDED, and 503 TYPE_UNAVAILABLE. When a created task fails, the public error code is TASK_FAILED or TASK_TIMEOUT; uncertain corresponds to TASK_UNCERTAIN. See the Platform API reference for details.

FAQ

  • What should websiteKey be? The target site's PerimeterX application ID pxAppId. Neither the page's visitor UUID nor the vid can replace it.
  • Can I omit the proxy? Not for this type. proxyType must be http, and proxyAddress and a string proxyPort must be provided together; fill in proxyLogin and proxyPassword only if the proxy requires authentication.
  • What if I need a SOCKS5 proxy? This type only accepts HTTP proxies; for socks5, use the perimeterx_cookies type (currently disabled by default; check GET /v1/prices).
  • Why can't the returned cookies be used? First confirm that you submitted the current target page, the application ID, and the full cookie set; subsequent requests must reuse the proxy egress used during solving and the returned solution.useragent. Cookie names are determined by the target page's configuration, so do not rely on _px3 alone.

The processing window starts after task creation is confirmed; queue waiting does not consume it. The current node timeout is approximately 180 seconds; the platform allows a 210-second soft window for transport and result polling.

Supported User Agents

Related documentation

Start with cURLCreate account

Last updated: