Captcha solving service blog | SolveCaptcha How to bypass PerimeterX (HUMAN) in authorized automation workflows

How to bypass PerimeterX (HUMAN) for authorized testing

PerimeterX, now part of HUMAN Security, protects websites and applications by analyzing the complete browser session rather than relying on a single captcha widget.

The system may evaluate:

  • network and protocol characteristics;
  • browser properties;
  • JavaScript execution;
  • cookies and local storage;
  • navigation history;
  • request frequency;
  • mouse, keyboard, and touch events;
  • IP address reputation;
  • previous activity associated with the session.

This makes HUMAN fundamentally different from a classic image captcha. There is normally no public site key that can be submitted to a captcha solver to obtain one universal token.

For legitimate QA, application monitoring, business-process automation, and testing of infrastructure you control, the reliable approach is to create an authorized access path rather than attempting to forge browser telemetry.

For a custom integration, provide the protected workflow, expected request volume, target environment, current response, and automation requirements through the contact form.

Use the methods described below only on websites you own or are explicitly authorized to test.

What is PerimeterX?

PerimeterX was a bot-detection and application-security platform that is now part of HUMAN Security.

Depending on the protected application, HUMAN may be used for:

  • bot detection;
  • account takeover prevention;
  • scraping protection;
  • credential-stuffing protection;
  • fraud detection;
  • automated abuse prevention;
  • API protection;
  • behavioral verification.

The protection can operate across multiple layers.

A request may pass the network layer but fail after JavaScript executes. Another request may be rejected immediately based on its source network or connection profile.

Possible results include:

  • HTTP 403 responses;
  • HTTP 429 responses;
  • a blocking page;
  • a JavaScript verification flow;
  • a Press and Hold challenge;
  • redirects;
  • repeated cookie updates;
  • successful HTML followed by blocked API requests.

Why basic HTTP requests fail

A request created with Python Requests, curl, or a standard HTTP client does not behave exactly like Chrome, Firefox, or Safari.

Changing only the User-Agent does not change:

  • TLS negotiation;
  • HTTP/2 behavior;
  • supported browser APIs;
  • JavaScript execution;
  • cookies;
  • navigation sequence;
  • browser timing;
  • device properties.

For example:

import requests

response = requests.get(
    "https://example.com/",
    headers={
        "User-Agent": (
            "Mozilla/5.0 (...) "
            "Chrome/... Safari/537.36"
        )
    },
)

print(response.status_code)

The header claims that the client is Chrome, but the underlying connection is still generated by Requests.

A protection system can identify the inconsistency between the declared browser and the actual client.

HUMAN protection layers

A PerimeterX or HUMAN block can originate from several independent layers.

Understanding which layer caused the failure is more useful than repeatedly changing random headers.

Network layer

The protection may evaluate properties of the connection before the page is rendered.

Relevant signals can include:

  • TLS version;
  • cipher suites;
  • protocol negotiation;
  • HTTP version;
  • HTTP/2 settings;
  • connection reuse;
  • header consistency;
  • source network;
  • IP reputation.

The important factor is consistency.

A browser identity, HTTP headers, network behavior, and source IP should represent one coherent client environment.

Browser environment

After the page loads, client-side scripts can inspect browser and device properties.

These may include:

  • screen dimensions;
  • viewport size;
  • browser feature support;
  • CPU information;
  • device memory;
  • timezone;
  • language;
  • WebGL properties;
  • Canvas behavior;
  • iframe behavior;
  • storage availability;
  • automation-related indicators.

Overriding one visible property does not reproduce an entire browser environment.

For example, changing:

navigator.webdriver

does not make all other browser APIs and timing values consistent with an ordinary interactive session.

Behavioral signals

The protection can observe how the user interacts with the page.

Possible signals include:

  • mouse movement;
  • pointer events;
  • scrolling;
  • keyboard input;
  • touch events;
  • delays between actions;
  • navigation order;
  • form interaction;
  • focus changes.

A browser session can appear technically valid but still be challenged when its behavior differs significantly from the expected application workflow.

Cookies and session state

Protected websites may set cookies associated with the current browser and security state.

Commonly observed PerimeterX-related cookie names may include:

_px
_px2
_px3
_pxhd

Their presence alone does not guarantee access.

A cookie may be evaluated together with:

  • source IP;
  • hostname;
  • browser environment;
  • other cookies;
  • navigation history;
  • challenge state;
  • cookie age.

Copying a cookie from another browser or proxy is therefore unreliable.

IP reputation

The browser can be correctly configured while the source IP remains restricted.

The protection may evaluate whether an address belongs to:

  • a hosting provider;
  • a heavily reused proxy range;
  • an abusive network;
  • an unexpected geographic location;
  • a network with previous suspicious activity.

Changing JavaScript properties does not resolve an independent network restriction.

What is HUMAN Challenge?

When the system requires additional verification, it may display HUMAN Challenge.

One recognizable format is the Press and Hold challenge. The visitor must press a control and hold it until verification completes.

The challenge can evaluate more than the total hold duration. It may also consider:

  • the browser session;
  • pointer or touch events;
  • challenge state;
  • cookies;
  • timing;
  • surrounding user interaction;
  • network consistency.

A normal JavaScript click is not equivalent to a Press and Hold interaction:

document.querySelector("button").click();

The challenge may expect a sequence such as:

pointerdown
→ continued hold
→ verification progress
→ pointerup
→ server-side validation

For authorized automated testing, use a vendor-provided testing mechanism, staging exception, or application-level test hook instead of trying to synthesize production behavioral data.

Does SolveCaptcha support PerimeterX?

The current SolveCaptcha API documentation does not define a dedicated PerimeterX, HUMAN, or Press and Hold method.

Do not invent a request such as:

method=perimeterx

or:

method=press_and_hold

Do not submit the challenge through unrelated methods such as:

method=turnstile
method=datadome
method=funcaptcha
method=userrecaptcha

These methods are designed for specific captcha providers and do not generate HUMAN browser-session tokens.

When a HUMAN-protected website displays a separate supported captcha, identify the actual provider and use the corresponding documented SolveCaptcha method.

For a custom HUMAN-related workflow, contact SolveCaptcha support or submit the project details through the contact form.

How to identify a HUMAN block

An HTTP 403 response alone does not prove that HUMAN caused the restriction.

Inspect:

  • response headers;
  • response body;
  • cookies;
  • redirects;
  • JavaScript files;
  • browser console;
  • network requests;
  • final page URL.

Record the complete response before modifying the client.

Python diagnostic example

The following script saves the response metadata, cookies, redirect chain, and HTML.

It does not bypass the protection. It helps identify where the failure occurs.

#!/usr/bin/env python3

from __future__ import annotations

import json
import sys
from pathlib import Path

import requests

def inspect_target(
    url: str,
    output_directory: Path,
) -> None:
    output_directory.mkdir(
        parents=True,
        exist_ok=True,
    )

    session = requests.Session()

    session.headers.update(
        {
            "User-Agent": (
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                "AppleWebKit/537.36 (KHTML, like Gecko) "
                "Chrome/126.0.0.0 Safari/537.36"
            ),
            "Accept": (
                "text/html,application/xhtml+xml,"
                "application/xml;q=0.9,*/*;q=0.8"
            ),
            "Accept-Language": "en-US,en;q=0.9",
        }
    )

    response = session.get(
        url,
        timeout=30,
        allow_redirects=True,
    )

    result = {
        "requested_url": url,
        "final_url": response.url,
        "status_code": response.status_code,
        "redirects": [
            {
                "status": item.status_code,
                "url": item.url,
                "location": item.headers.get(
                    "Location"
                ),
            }
            for item in response.history
        ],
        "headers": dict(response.headers),
        "cookies": session.cookies.get_dict(),
    }

    (
        output_directory
        / "metadata.json"
    ).write_text(
        json.dumps(
            result,
            indent=2,
        ),
        encoding="utf-8",
    )

    (
        output_directory
        / "response.html"
    ).write_text(
        response.text,
        encoding="utf-8",
        errors="replace",
    )

    print(
        json.dumps(
            result,
            indent=2,
        )
    )

def main() -> None:
    if len(sys.argv) != 2:
        raise SystemExit(
            "Usage: python inspect_human.py URL"
        )

    inspect_target(
        url=sys.argv[1],
        output_directory=Path(
            "human-diagnostics"
        ),
    )

if __name__ == "__main__":
    main()

Run it:

python inspect_human.py https://example.com/

Compare the output for:

  • an accepted browser session;
  • a blocked browser session;
  • staging and production;
  • different test accounts;
  • different approved source networks.

Diagnose the page with Playwright

A browser is more useful when the protection depends on JavaScript execution.

Install Playwright:

npm install playwright
npx playwright install chromium

Create inspect-human.js:

import {
  mkdir,
  writeFile,
} from "node:fs/promises";

import { chromium } from "playwright";

const TARGET_URL =
  process.env.TARGET_URL;

if (!TARGET_URL) {
  throw new Error(
    "Set TARGET_URL"
  );
}

await mkdir(
  "human-browser-diagnostics",
  {
    recursive: true,
  }
);

const browser =
  await chromium.launch({
    headless: false,
  });

const context =
  await browser.newContext({
    viewport: {
      width: 1366,
      height: 900,
    },
  });

const page =
  await context.newPage();

const events = [];

page.on(
  "request",
  (request) => {
    events.push({
      type: "request",
      method: request.method(),
      url: request.url(),
      resourceType:
        request.resourceType(),
    });
  }
);

page.on(
  "response",
  async (response) => {
    events.push({
      type: "response",
      status: response.status(),
      url: response.url(),
      headers:
        await response.allHeaders(),
    });
  }
);

page.on(
  "console",
  (message) => {
    events.push({
      type: "console",
      level: message.type(),
      text: message.text(),
    });
  }
);

try {
  const response =
    await page.goto(
      TARGET_URL,
      {
        waitUntil:
          "domcontentloaded",
        timeout: 45_000,
      }
    );

  await page.waitForTimeout(
    10_000
  );

  const result = {
    targetUrl: TARGET_URL,
    finalUrl: page.url(),
    title: await page.title(),
    mainStatus:
      response?.status() ?? null,
    cookies:
      await context.cookies(),
    events,
  };

  await writeFile(
    "human-browser-diagnostics/result.json",
    JSON.stringify(
      result,
      null,
      2
    ),
    "utf8"
  );

  await writeFile(
    "human-browser-diagnostics/page.html",
    await page.content(),
    "utf8"
  );

  await page.screenshot({
    path:
      "human-browser-diagnostics/page.png",
    fullPage: true,
  });

  console.log(
    JSON.stringify(
      result,
      null,
      2
    )
  );
} finally {
  await browser.close();
}

Run it:

TARGET_URL=https://example.com/ node inspect-human.js

Review:

  • the initial document response;
  • redirects;
  • loaded security scripts;
  • failed network requests;
  • cookies created during navigation;
  • browser console errors;
  • the final URL;
  • the displayed challenge.

Safe bypass methods for authorized testing

The most reliable solutions require cooperation from the website owner or security configuration.

1. Allowlist the test network

Create a dedicated exception for known QA traffic.

Possible identifiers include:

  • fixed office IP addresses;
  • test VPN egress addresses;
  • dedicated CI runner addresses;
  • approved monitoring networks;
  • authenticated test requests.

Restrict the exception to:

  • specific paths;
  • specific HTTP methods;
  • specific environments;
  • specific accounts;
  • a limited period;
  • a defined request rate.

Do not disable protection globally.

2. Use a staging environment

Run browser automation against a dedicated staging hostname:

https://staging.example.com/

The staging environment can use:

  • reduced enforcement;
  • monitoring-only mode;
  • dedicated test accounts;
  • predictable challenge behavior;
  • separate rate limits;
  • mocked verification.

This keeps production protection enabled while allowing repeatable tests.

3. Use a signed testing header

The protected application can implement a short-lived signed header for authorized automation.

Example concept:

X-Automation-Test: TIMESTAMP.NONCE.SIGNATURE

The signature can include:

  • HTTP method;
  • request path;
  • timestamp;
  • nonce;
  • environment;
  • test account identifier.

The edge or application validates the signature before applying the test exception.

Do not use a permanent static value such as:

X-Bypass: true

Static bypass values can be leaked and replayed.

4. Configure an approved automation identity

Monitoring services, business integrations, and internal automation should have a documented identity.

The policy can define:

  • allowed endpoints;
  • source networks;
  • authentication method;
  • maximum request rate;
  • approved User-Agent;
  • policy owner;
  • expiration date.

This is more reliable than trying to make automation indistinguishable from public browser traffic.

5. Use official APIs

When the website provides an API, use it instead of automating the public interface.

Official APIs normally provide:

  • documented authentication;
  • stable request formats;
  • predictable rate limits;
  • lower operational cost;
  • fewer bot-detection conflicts.

Browser automation should be used only when the required workflow is not exposed through an API.

6. Use a vendor-provided testing mode

When HUMAN provides a testing, monitoring, or challenge-bypass mechanism for the protected application, configure it through the application owner’s security dashboard.

Treat any testing credential as a private secret.

It should be:

  • scoped to the correct application;
  • restricted to test environments;
  • short-lived where possible;
  • stored outside source code;
  • monitored and rotated;
  • removed when testing is complete.

Do not attempt to obtain or reuse another website’s testing credentials.

7. Preserve session consistency

For authorized browser automation, keep the client environment stable during the complete workflow.

Maintain:

  • one browser context;
  • one User-Agent;
  • one source IP;
  • session cookies;
  • local storage;
  • expected navigation sequence;
  • reasonable request timing.

Avoid:

  • launching a new browser for every request;
  • changing proxy nodes mid-session;
  • copying cookies between environments;
  • replaying old challenge responses;
  • mixing unrelated browser and HTTP sessions;
  • retrying blocked requests continuously.

Testing Press and Hold challenges

For applications you control, do not make every automated test solve a live production challenge.

Use a layered testing strategy.

Unit tests

Mock the challenge result and test:

  • successful validation;
  • rejected validation;
  • callback behavior;
  • redirects;
  • error messages;
  • session updates.

Integration tests

Use the authorized testing mechanism configured by the application owner.

Verify:

  • challenge rendering;
  • successful completion;
  • application callback;
  • cookies;
  • access to the protected page.

Production smoke tests

Run only a limited number of authorized end-to-end tests against production.

Do not execute challenge tests on every commit or in a high-frequency loop.

Why cookie transfer is unreliable

A common approach is to open a browser, obtain a _px3 cookie, and then copy it to a faster HTTP client.

This can fail because the cookie may be evaluated with:

  • the source IP;
  • browser properties;
  • other cookies;
  • session timing;
  • navigation history;
  • target hostname;
  • challenge state.

The following workflow is unreliable:

Browser A + IP A receives cookie
→ cookie copied
→ HTTP client B + IP B sends requests

For an authorized integration, keep requests inside the same browser session or use an approved application access method.

Why browser stealth plugins are unreliable

Plugins that hide a few automation indicators do not reproduce the full browser environment.

They can create inconsistencies between:

  • JavaScript properties;
  • native function output;
  • browser features;
  • network behavior;
  • cookies;
  • timing;
  • interaction patterns.

A stealth plugin may work for one version of a protected page and fail after the security script changes.

Do not make a critical production workflow depend on undocumented browser patches.

Why reverse engineering is not a stable integration

Deobfuscating security scripts, recreating telemetry, or generating proprietary cookies outside the browser is fragile and inappropriate for ordinary QA or business automation.

The implementation can change without notice, and incorrect telemetry may result in:

  • additional challenges;
  • blocked sessions;
  • IP restrictions;
  • account restrictions;
  • unreliable production behavior.

For systems you own, use a formal security test with an approved scope. For routine automation, create an authorized policy exception.

Mobile application testing

Mobile protection can use native SDKs and application-specific authorization data.

The correct testing approach is to use:

  • a dedicated test build;
  • staging API endpoints;
  • vendor-provided testing configuration;
  • approved test devices;
  • controlled certificates;
  • mock verification responses.

Do not attempt to disable certificate pinning or reverse engineer third-party mobile applications without explicit authorization.

Common implementation mistakes

Changing only the User-Agent

A User-Agent does not change the connection, browser APIs, cookies, or session behavior.

Using a new browser for every request

Frequent new sessions can appear abnormal and prevent cookies from accumulating.

Rotating the proxy during one workflow

A source-IP change can invalidate the current session.

Copying cookies to another client

Cookies may be associated with the original network and browser context.

Retrying every 403 response

Repeated retries can increase the risk assessment.

Stop, save the response, and identify the responsible rule.

Disabling JavaScript

The security script and protected application may require JavaScript to function correctly.

Blocking Canvas or WebGL

Removing browser APIs can make the environment less consistent rather than more private.

Using unsupported SolveCaptcha methods

Do not send HUMAN Challenge through unrelated captcha methods.

Disabling protection globally

Create a narrow exception for known test traffic instead.

Recommended QA architecture

A controlled HUMAN testing workflow can use:

QA runner
    ↓
Dedicated test network
    ↓
Limited HUMAN policy exception
    ↓
Staging or approved production paths
    ↓
Application authentication
    ↓
Audit logs and rate controls

Recommended controls include:

Dedicated source IP
Short-lived test credential
Limited paths
Maximum request rate
Separate test account
Automatic expiration
Central logging
Named policy owner

Troubleshooting checklist

When authorized automation is blocked, record:

Exact timestamp
Source IP
Target hostname
Request URL
HTTP method
Response status
Response headers
Response body
Final browser URL
Browser User-Agent
Cookie names
Security policy version
Test account
Expected request rate
Screenshot
Console errors

Then determine:

  1. Was the block produced by HUMAN or the application?
  2. Was the request blocked before or after JavaScript execution?
  3. Did the source IP change?
  4. Were cookies preserved?
  5. Did the browser load all required scripts?
  6. Did the workflow skip an expected navigation step?
  7. Did the page display a challenge?
  8. Did a recent security-policy change affect the test?
  9. Was the test credential valid?
  10. Was the request rate within the approved limit?

Frequently asked questions

Is PerimeterX the same as HUMAN Security?

PerimeterX is now part of HUMAN Security. Older integrations, cookies, scripts, and documentation may still use PerimeterX or PX terminology.

Is HUMAN Challenge a normal captcha?

It is a behavioral verification mechanism. It can evaluate the complete session in addition to the visible interaction.

Can SolveCaptcha bypass PerimeterX directly?

The current SolveCaptcha API documentation does not define a dedicated PerimeterX or HUMAN method.

Can I use the DataDome method?

No. DataDome and HUMAN are separate protection systems.

Can I use the Turnstile method?

No. Cloudflare Turnstile and HUMAN Challenge are different products.

Can I copy a _px3 cookie?

A copied cookie may be rejected when the IP, browser, hostname, or session context differs.

Does a residential proxy guarantee access?

No. The complete session is evaluated. A proxy does not correct browser, cookie, workflow, or authorization problems.

What is the best approach for QA?

Use staging, a dedicated test network, a narrow policy exception, and an authorized testing credential.

What should I do when monitoring is blocked?

Register the monitor as approved automation and create a limited rule for its source network, endpoints, and request rate.

Can I automate Press and Hold with Selenium?

Selenium can produce a press-and-hold interaction, but reliable authorized tests should use a vendor-provided testing mechanism rather than attempting to imitate production behavioral signals.

Conclusion

PerimeterX and HUMAN Security evaluate the complete browser and request environment. Reliable authorized automation cannot be reduced to one modified header, copied cookie, proxy, or browser plugin.

The correct workflow is:

  1. Confirm that HUMAN generated the block.
  2. Identify whether it occurs at the network, browser, behavioral, or application layer.
  3. Record the response, cookies, redirects, and browser events.
  4. Use a staging environment where possible.
  5. Create a narrow exception for a dedicated test network.
  6. Use short-lived authorized testing credentials.
  7. Preserve the browser, cookie, and IP session.
  8. Follow the expected application workflow.
  9. Respect documented rate limits.
  10. Keep public protection enabled for normal traffic.

For a custom authorized solution, submit the target URL, required workflow, expected request volume, test environment, current response, and automation stack through the contact form.