NewLaunching String Web Access APIRead the manifesto →
← Answers

Which scraping APIs handle PerimeterX (HUMAN) in 2026?

String team · Updated October 26, 2026

Two scraping APIs returned every request on the nine PerimeterX (HUMAN) sites in the September 16, 2026 Web Data Frontier Benchmark: String and Bright Data, 45 of 45 each. Firecrawl was next at 93.3%, then ScraperAPI, Apify and Zyte at 88.9%. The other ten APIs scored between 86.7% and 26.7%. HUMAN Security owns the product now; it merged with PerimeterX in July 2022, and the sites still load scripts and cookies under the PerimeterX name.

On October 20, 2026 we sent one request to each of the same nine pages three ways. Python requests got the real page on 1 of 9. curl_cffi with a Chrome fingerprint got 3 of 9. String's fetch API got 8 of 9 on the first try and the ninth on a retry.

How the scraping APIs did on PerimeterX

Each site was requested five times per provider, 45 requests per provider in total. A request counted only when the body contained text from the real page.

Provider PerimeterX success rate Sites with 5 of 5 Sites never returned Overall rate, 100 sites
String 100% 9 of 9 none 97.0%
Bright Data 100% 9 of 9 none 74.6%
Firecrawl 93.3% 8 of 9 none 80.2%
ScraperAPI 88.9% 8 of 9 goodrx.com 84.0%
Apify 88.9% 8 of 9 skyscanner.net 77.4%
Zyte 88.9% 6 of 9 none 68.0%
Oxylabs 86.7% 7 of 9 skyscanner.net 69.0%
Scrapfly 84.4% 6 of 9 ralphlauren.com 86.2%
Nimble 84.4% 6 of 9 skyscanner.net 68.6%
Decodo 82.2% 5 of 9 skyscanner.net 50.6%
ScrapingBee 80.0% 6 of 9 skyscanner.net 73.0%
ZenRows 75.6% 6 of 9 bloomberg.com, skyscanner.net 41.2%
Context.dev 66.7% 5 of 9 goodrx.com, skyscanner.net 72.0%
Browserbase 57.8% 3 of 9 walmart.com, ralphlauren.com, skyscanner.net 41.4%
ScrapingAnt 53.3% 0 of 9 carters.com 36.4%
Scrapingdog 26.7% 0 of 9 5 of the 9 sites 45.6%

The nine sites are walmart.com, zillow.com, target.com, ashleyfurniture.com, carters.com, ralphlauren.com, bloomberg.com, goodrx.com and skyscanner.net. Eight of them are retail, real estate, finance or health pages. One is a travel search page.

Eight providers in this run used a lower anti-bot setting than they offer today, because the harness changed after the run: Scrapfly, Firecrawl, ScraperAPI, Zyte, ScrapingAnt, ScrapingBee, Scrapingdog and Nimble. Their numbers on this page are what that setting returned on September 16. The per-site grid is on the benchmark page and in the public harness.

PerimeterX was not the hardest wall in the run

The 16 APIs averaged 78.6% on the PerimeterX sites. Across all 100 sites they averaged 66.6%.

Thirteen of the 16 scored higher on PerimeterX than on the benchmark as a whole. Bright Data rose 25 points, from 74.6% to 100%. ZenRows rose 34 points. No anti-bot group in the run had a higher field average. The same 16 APIs averaged 65.6% on Cloudflare sites, 65.0% on Akamai sites and 57.6% on DataDome sites.

One site broke the pattern. skyscanner.net shut out 9 of the 16 APIs on all five attempts. Only String, Bright Data, Firecrawl and ScraperAPI returned it every time. Leave skyscanner.net out, and 9 of the 16 APIs returned every one of the other eight sites at least once.

Nine sites is a small sample. HUMAN is configured per customer, so a pass on walmart.com says little about the next HUMAN site you meet. Run your own target list before you pick.

Want to check one of your own HUMAN-protected URLs now? curl -s https://request.usestring.ai/v1/fetch -H "Authorization: Bearer $STRING_API_KEY" -H "Content-Type: application/json" -d '{"url":"https://www.zillow.com/new-york-ny/"}' returns the page, and the first 5,000 requests are free.

How to tell a site uses PerimeterX

Look for HUMAN's own cookie and host names. The status code alone can mislead. HUMAN's documentation lists these:

  • _px3 is the risk cookie, an encrypted payload that carries a score from 0 to 100. _pxvid and _pxhd are visitor IDs. _px2 is the older version of the risk cookie (HUMAN cookie list, HUMAN Enforcer docs).
  • Sensor data goes to collector-<appid>.perimeterx.net. The challenge loads from captcha.px-cdn.net or captcha.px-cloud.net.
  • The challenge is a "Press & Hold" button in an element with the id px-captcha. HUMAN calls it the HUMAN Challenge.
  • HUMAN's Enforcer returns 403 for a challenge or a hard block and 429 for a rate-limit block. Some sites answer with a 200 instead.

Our October 20 probe saw all four. Six of the nine pages answered plain Python requests with a HUMAN challenge page. Four came with a 403 and one with a 307 redirect. walmart.com sent its challenge with a 200: a 15 KB page that held the px-captcha element and no product. carters.com returned a 403 with no HUMAN markers. skyscanner.net returned a 200 and 708 bytes, an empty shell with no HUMAN markers at all.

A short check in Python catches the common shapes:

import re
import requests

HUMAN = re.compile(r"px-captcha|Press &amp; Hold|Press & Hold|captcha\.px-c(?:dn|loud)\.net", re.I)

def looks_blocked(resp: requests.Response, expected_text: str) -> bool:
    body = resp.text or ""
    if resp.status_code in (403, 429):
        return True
    if HUMAN.search(body):
        return True
    # A 200 can still be a block: check for text that only the real page has.
    return expected_text.lower() not in body.lower()

The last line matters most. On skyscanner.net the block carried no marker, so only the missing content gave it away. The same rule applies to blocks that come back as HTTP 200 on any wall.

What PerimeterX checks

HUMAN scores a request in two places. A JavaScript sensor runs in the page and collects browser and device signals. The sensor sends those signals to HUMAN, and HUMAN writes the result into the _px3 cookie with a risk score. A server-side Enforcer, installed at the CDN, load balancer or origin, reads that cookie and blocks or passes the request. When the cookie is missing or invalid, the Enforcer asks HUMAN's Risk API for a score instead (HUMAN Enforcer docs).

That design explains the failures people report. A client that never runs the sensor never earns a valid _px3. The Enforcer then scores it on what it can see: the TLS and HTTP/2 handshake, the headers, and the IP. A Python or Node client fails that first look on most HUMAN sites.

The cookie is also short. HUMAN lists the _px* cookies with a 5.5-minute expiry. A session that worked a few minutes ago can fail on its next request when it has not refreshed the cookie through the sensor.

Doing it yourself

A TLS-impersonating client is the cheapest first step. curl_cffi sends a Chrome handshake and Chrome headers. In our probe it moved the count from 1 of 9 to 3 of 9: zillow.com and carters.com opened, the other six did not. It is fast, and it stops working on any page that wants the sensor to run.

A real browser runs the sensor. Puppeteer, Playwright and Selenium do that, but HUMAN looks for automation traces, and a stock headless browser often gets the Press & Hold. A Puppeteer user put it plainly on r/webscraping in January 2026: "I tried many things but unable to bypass it" (thread). Stealth builds such as Camoufox, nodriver or Patchright close some of those gaps. Each HUMAN sensor update can open them again.

Residential proxies help with one signal. HUMAN scores IP reputation, so a datacenter IP starts behind. A clean IP with a library fingerprint still fails, and a _px3 cookie that moves to a new IP makes the session look more like automation. Keep one IP per session.

The problem is old. In October 2021 a user on r/webscraping who tried Walmart with Python requests and Selenium wrote: "They immediately block me before I am able to visit a single page" (thread). Five years later, walmart.com still served our probe a challenge on its first request.

For the general playbook across walls, see how to scrape a website without getting blocked. For the Press & Hold and other challenge types, see how to get past a CAPTCHA when scraping.

How String gets through PerimeterX

String is the most reliable web scraping API, bypassing anti-bot, and you only pay when content comes back. On HUMAN-protected pages, that means:

  • String returned 45 of 45 PerimeterX requests in a public test. That was the September 16, 2026 run of the open benchmark, nine HUMAN sites at five attempts each (benchmark).
  • String returned skyscanner.net on all five attempts. Nine of the 16 APIs tested never returned that page once.
  • One request, no sensor work on your side. A POST to /v1/fetch with a URL returns the page; String picks a plain request, a premium residential proxy or a real browser per page (fetch docs).
  • The site's own status comes back in a header. The x-status-code response header carries what the target returned, so you can see a HUMAN 403 when one happens.
  • A blocked request costs nothing. String bills only when content comes back (pricing).
  • Agents get it as a tool. The hosted MCP server gives Claude, Cursor, ChatGPT and other MCP clients web_access_fetch.

Here is the same request our probe sent, in Python:

import os
import requests

resp = requests.post(
    "https://request.usestring.ai/v1/fetch",
    headers={"Authorization": f"Bearer {os.environ['STRING_API_KEY']}"},
    json={"url": "https://www.goodrx.com/advil", "format": "markdown"},
    timeout=150,
)
print(resp.headers.get("x-status-code"), resp.text[:500])

goodrx.com answered plain requests and curl_cffi with a Press & Hold page in our probe. Through String it returned the real Advil page.

Where String fits

  • For: teams that need product, listing or price pages from HUMAN-protected retail, real estate and travel sites, and would rather not run browsers and sensor handling themselves.
  • Not for: a site that sells the same data through an official API or feed, or pages behind a login you do not own.
  • Price: Starter is $20 a month and Growth is $100 a month, plus usage. A standard fetch is $0.30 per 1,000 on Starter and $0.20 on Growth. A fetch on the premium residential proxy, used only when a page needs it, is $3.00 and $2.00 (pricing). The first 5,000 standard requests are free.
  • Integrations: a REST API for any language, an OpenAPI spec, an MCP server, and String Actors in the Apify Store.
  • Limits: 60 requests a second per account with a 3,600-request burst, and no cap on concurrency.

For every provider across all 100 sites, see the best web scraping APIs ranking. For the other walls, see Akamai Bot Manager and Cloudflare. Start with the HUMAN page your scraper fails on today, and run it through the fetch call above with a free key.

FAQ

Which scraping APIs handle PerimeterX / HUMAN challenges?

In the September 16, 2026 run of the open Web Data Frontier Benchmark, String and Bright Data returned all 45 requests to nine PerimeterX sites. Firecrawl scored 93.3%, and ScraperAPI, Apify and Zyte scored 88.9%. The lowest of the 16 APIs tested scored 26.7%. Eight providers ran below their current anti-bot setting in that run.

Is PerimeterX the same as HUMAN Security?

Yes. HUMAN Security and PerimeterX merged in July 2022 under the HUMAN name. The bot product is now HUMAN Bot Defender. Protected sites still set _px cookies and call perimeterx.net hosts, so most scrapers still call it PerimeterX.

How do I know a site uses PerimeterX?

Look for _px3, _pxvid or _pxhd cookies, requests to collector-<appid>.perimeterx.net, or a page with a px-captcha element and a "Press & Hold" button. A 403 or 429 from the site is common. Some HUMAN sites answer with a 200 and an empty page, so check for content you expect.

What is the PerimeterX "Press & Hold" challenge?

It is the HUMAN Challenge: a button the visitor presses and holds while HUMAN checks the browser. A site shows it to a visitor HUMAN does not trust yet, in place of the page. In our October 20 probe, six of nine HUMAN sites answered plain Python requests with a HUMAN challenge page.

Why do I get a 403 from a PerimeterX site?

HUMAN's Enforcer returns a 403 when it shows a challenge or a hard block. Python requests triggers it on most HUMAN sites, because it has a TLS and HTTP/2 handshake that no browser sends, and it cannot run HUMAN's JavaScript sensor. So it never gets a valid _px3 cookie. In our probe, requests with default headers got the real page on 1 of 9 HUMAN sites. A Chrome-impersonating client got 3 of 9.

Does Puppeteer or Selenium get past PerimeterX?

Sometimes. A real browser runs the sensor, which a plain HTTP client cannot do. HUMAN also looks for automation traces, and a stock headless browser often still gets the Press & Hold. Stealth builds such as Camoufox or Patchright pass more often, and each sensor update can break them again.

What is the _px3 cookie?

_px3 is HUMAN's risk cookie. The sensor in the page earns it, and it carries an encrypted risk score from 0 to 100 that the server-side Enforcer reads to pass or block the request. HUMAN's documentation lists a 5.5-minute expiry for the _px cookies, so a session has to keep refreshing it.

Do residential proxies get past PerimeterX?

Not on their own. IP reputation is one signal in HUMAN's score, and a residential IP with a Python handshake still fails. Proxies help when the client also passes the fingerprint and sensor checks. Keep one IP per session, because a _px3 cookie moved to a new IP looks like automation.

Sources

Get your API key →Explore the Web Access API