Web Unlocker · PerimeterX (HUMAN)
PerimeterX web scraping ends for many scripts on a 403 page that says Press & Hold. The Web Unlocker makes the request from a residential or mobile IP with a browser-grade client, so the page can arrive before that challenge is shown, retries from a fresh exit when it is not, and reports a challenge it cannot pass.
PerimeterX-protected pages in our canary of 11 November 2026: 9 of 9 calls came back as the real page. All 27 protected pages of the run, 3 calls each: 72 of 81, with a median of 4.1 s. How it is measured, and the latest run
A browser gets a page with one button. A client that calls the site's API gets JSON it did not ask for. Both are the same block, and these are its marks.
| Where to look | What PerimeterX puts there |
|---|---|
| Status code | 403. An API or XHR call gets 403 with a JSON body where a page would be. |
| Page text | "Press & Hold to confirm you are a human (and not a bot)." The title of the page is "Access to this page has been denied". |
| Reference ID | A line at the bottom of the page that starts with "Reference ID #" and a long identifier. |
| JSON on API calls | Keys named appId, jsClientSrc, blockScript, vid and uuid. The appId starts with PX. |
| Elements and scripts | An element with the id px-captcha, and a script on a path that contains the PX app id. |
| Cookies | _px3, _pxvid and _pxhd, on some sites pxcts. _px3 carries the risk score of the session. |

PerimeterX, now part of HUMAN Security, scores the session and not only the request. On the first request there is no cookie yet, so the decision rests on the IP, the TLS handshake and the headers. A scripted client is flagged at that point, before any page is shown.
Once a page loads, a script on it reports browser and device signals and, later, how the pointer and the keyboard are used. The verdict travels in the _px3 cookie. A low score gets the 403 with Press & Hold, and holding the button is itself a behaviour test: it measures how the press is made. For PerimeterX web scraping the first request is therefore the one to get right.
It puts the effort where the first decision is made. The first attempt is a browser-grade request from a residential exit, so the IP, the handshake and the headers describe one ordinary browser. When that is served, the call returns with tier_served tls and nothing else is needed.
If an attempt meets the challenge, the call retries from a fresh exit, and a real browser opens the page when the site needs one. Press & Hold itself is not answered. When every attempt ends on it, you get blocked true with blockClass captcha, and the challenge page in body so you can see it.
A plain curl is enough to try a URL. In production, send the same JSON from your own code and keep the request_id of each answer.
When the URL is one of the site's JSON endpoints, check blocked before you parse. A PerimeterX block on an API call is JSON too, and it parses without an error.
curl -X POST https://app.quantumproxies.io/api/v1/scraper/unlock \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/", "country": "us"}'
Web Unlocker in the API docs: request, answer, blocked pages
| Field | What it tells you |
|---|---|
| status | The status of the page that was served, 200 for the real one. |
| blocked | true when the call ended on Press & Hold or on a flat refusal, on a page or on an API call alike. |
| blockClass | captcha for Press & Hold, fingerprint for a flat refusal. |
| vendor | perimeterx. The value keeps the old name and also covers sites that show HUMAN branding. |
| tier_served | tls when the first request was served, browser when a real browser opened the page. |
| attempts | How many tries the call needed. Each one is an entry of attempt_log. |
| cost | The bytes moved by every attempt of the call, and their cost. |
Press & Hold is built to need a person, so a blocked answer on a PerimeterX site is information to act on. For jobs that must never store a challenge as data, fail_on_block true turns a blocked page into a 424 target_blocked error that your pipeline can count.
What to do next depends on the class.
Because the score belongs to a session, how you spread the calls matters more here than on most systems. Leave rotation on. Each call then leaves from its own exit and is judged as a new visitor, instead of building a history on one address. Pin a session only for a flow that needs it, such as paging through one result list.
The batch endpoint takes up to 100 URLs in one job and runs a few at a time, which is a comfortable pace for a single site. The results wait for you for an hour, or arrive on your webhook.
A residential or mobile proxy helps with the first decision, the one that leans on the IP. If the client behind it is an HTTP library, the handshake still lowers the score and the challenge follows a few requests later. Use plain proxies under a real browser that you operate yourself; use the Web Unlocker when you would rather send a URL and read an answer.
Press & Hold, and every other captcha that asks for a person, is left unanswered and reported. The Web Unlocker opens public pages only: it does not sign in, register accounts or act as a logged-in user.
What you may collect is decided by the terms of the site and by the law that covers the data. A protection system does not change that, in either direction, and neither does getting the page.
Yes, for public pages. It makes the first request the way an ordinary browser on a home connection would, which is what PerimeterX judges before any cookie exists, and it retries from a fresh exit when a call is challenged. The answer says which tier served the page and how many attempts it took.
A JSON answer with blocked true, blockClass captcha and vendor perimeterx, and the challenge page in body. The Web Unlocker does not hold the button: that test asks for a person. Retrying is reasonable, because the next call is a new session from another exit and may be served the page.
Read blocked. On API and XHR requests PerimeterX answers 403 with a JSON body that names appId and blockScript, so a parser accepts it without complaint. The Web Unlocker recognises that body and flags the answer, with vendor perimeterx, before your code treats it as a result.
Yes. PerimeterX is now part of HUMAN Security and the product is sold under that name, but the block page, the px-captcha element and the _px cookies are the same. In our answers the vendor value stays perimeterx, so one filter in your logs covers sites under either name.
Usually not. PerimeterX scores sessions, and a long session from one exit gathers a history that a single page request does not. Leave rotation on for independent pages, and add a session id only when the pages depend on each other, for example a search and its second page.
Skip the marketing. QuantumProxies.io publishes a machine-readable site map, Markdown for every page, a free MCP server, and APIs billed from the same balance as your proxies.
Connect in one command: npx -y quantumproxies-mcp