How to bypass press and hold captcha
Press and Hold captcha asks the user to press a button, keep it pressed until a progress indicator completes, and then release it. The interaction looks simple, but the challenge can evaluate the complete browser session rather than only the hold duration.
This verification method is commonly associated with HUMAN Challenge. It may analyze mouse, touch, keyboard, browser, session, and challenge-specific signals before accepting the interaction.
For authorized QA and integration testing, the correct approach is to use the testing mechanism provided by the captcha vendor. HUMAN provides a CAPTCHA Bypass Token that allows automated tests to complete the challenge without attempting to disguise Selenium as a normal user.
This guide explains how to:
- identify a Press and Hold captcha;
- understand why ordinary JavaScript clicks fail;
- create a repeatable testing workflow;
- use a vendor-issued CAPTCHA Bypass Token;
- configure the
x-px-captcha-testingheader; - set a predictable hold duration;
- automate the test with Selenium;
- diagnose repeated or incomplete challenges.
Use this workflow only on applications you own or are explicitly authorized to test.
What is Press and Hold captcha?
Press and Hold captcha is a behavioral verification challenge. The user must:
- Focus or point to the challenge button.
- Press and continue holding it.
- Wait until the progress indicator completes.
- Release the button.
- Wait for the verification result.
The required hold time may change between challenges. The verification system can also evaluate events generated while the button is held.
Signals may include:
- pointer-down and pointer-up events;
- total hold duration;
- mouse movement;
- touch events;
- keyboard events;
- browser cookies;
- session history;
- challenge identifiers;
- browser and device characteristics;
- repeated or replayed challenge responses.
This means that the challenge cannot usually be completed by assigning a value to a hidden input or submitting a fixed token.
Why JavaScript click does not work
A normal JavaScript click:
document.querySelector("button").click();
generates only a short click event. It does not reproduce a complete press-and-hold interaction.
The challenge may expect an event sequence similar to:
pointerdown
→ continuous hold
→ progress update
→ pointerup
→ challenge verification
The following script is therefore not a reliable solution:
const button = document.querySelector("button");
button.dispatchEvent(
new MouseEvent("mousedown")
);
setTimeout(() => {
button.dispatchEvent(
new MouseEvent("mouseup")
);
}, 5000);
Synthetic DOM events may differ from browser-generated input events. The challenge can also validate information outside the button itself, including the active session and challenge state.
Why a fixed Selenium hold may still fail
Selenium can generate a real browser input sequence:
ActionChains(driver) \
.click_and_hold(button) \
.pause(5) \
.release() \
.perform()
However, this does not guarantee acceptance.
A production challenge may reject the interaction because of:
- an incorrect hold duration;
- an expired challenge;
- missing session information;
- an automated browser environment;
- challenge replay;
- an invalid browser state;
- missing cookies;
- an incomplete vendor integration;
- a challenge that has already been attempted.
Trying random hold durations is not a stable testing strategy.
For repeatable automated tests, use the official testing token supplied through the HUMAN dashboard.
Does SolveCaptcha support Press and Hold captcha?
The current SolveCaptcha API documentation does not define a dedicated method for Press and Hold or HUMAN Challenge.
Do not invent parameters such as:
method=press_and_hold
Do not submit the challenge using an unrelated method such as:
method=turnstile
method=datadome
method=funcaptcha
These methods solve different captcha systems and do not represent HUMAN Challenge.
For an application protected by Press and Hold captcha, use one of the following approaches:
- Use the official vendor testing token.
- Disable the challenge in a controlled test environment.
- Allowlist test traffic.
- Mock the challenge result in application-level tests.
- Request authorized test access from the website owner.
- Contact SolveCaptcha support about a custom integration rather than assuming API compatibility.
Official testing method
HUMAN provides a CAPTCHA Bypass Token for integration testing.
The recommended workflow is:
- Open the HUMAN dashboard.
- Go to Bot Defender Settings.
- Open Challenge Settings.
- Open Challenge Tokens.
- Create a CAPTCHA Bypass Token.
- Store the token as a protected testing secret.
- Add it to the challenge request through the
x-px-captcha-testingheader.
Example:
x-px-captcha-testing: YOUR_BYPASS_TOKEN
The token should be created by the owner of the protected application. It should not be extracted from another website or shared publicly.
Set a predictable hold duration
For automated testing, HUMAN allows the required solve time to be appended to the bypass token.
The format is:
BYPASS_TOKEN~HOLD_TIME_MS
Example for a five-second hold:
x-px-captcha-testing: YOUR_BYPASS_TOKEN~5000
The documented duration range is:
1000–10000 milliseconds
This makes the test repeatable because the automation knows how long it should hold the button.
Example:
hold_time_ms = 5000
testing_header = (
f"{bypass_token}~{hold_time_ms}"
)
Do not use this header against a third-party website. The token must be issued for the application being tested.
Force the challenge to appear in testing
A legitimate browser session may not receive a challenge during every request.
For integration testing, HUMAN documents the use of a PhantomJS User-Agent to trigger the challenge:
User-Agent: PhantomJS
A unique suffix can be added between tests:
PhantomJS-press-hold-test-1
This can help avoid a recently completed challenge being reused from the previous session.
Use this only in a controlled testing environment. It is not intended to make production scraping traffic appear human.
Complete Selenium testing example
Install Selenium:
python -m pip install selenium
Set the required environment variables.
Linux or macOS:
export TARGET_URL="https://staging.example.com/protected-page"
export PX_CAPTCHA_BYPASS_TOKEN="YOUR_VENDOR_ISSUED_TOKEN"
export PX_HOLD_TIME_MS="5000"
Windows PowerShell:
$env:TARGET_URL="https://staging.example.com/protected-page"
$env:PX_CAPTCHA_BYPASS_TOKEN="YOUR_VENDOR_ISSUED_TOKEN"
$env:PX_HOLD_TIME_MS="5000"
Create press_and_hold_test.py:
#!/usr/bin/env python3
from __future__ import annotations
import os
import time
from selenium import webdriver
from selenium.common.exceptions import (
NoSuchElementException,
TimeoutException,
)
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support import (
expected_conditions as EC,
)
from selenium.webdriver.support.ui import WebDriverWait
TARGET_URL = os.environ.get(
"TARGET_URL",
"",
).strip()
BYPASS_TOKEN = os.environ.get(
"PX_CAPTCHA_BYPASS_TOKEN",
"",
).strip()
HOLD_TIME_MS = int(
os.environ.get(
"PX_HOLD_TIME_MS",
"5000",
)
)
CHALLENGE_IFRAME_SELECTOR = os.environ.get(
"PX_CHALLENGE_IFRAME_SELECTOR",
'iframe[title*="challenge" i]',
)
CHALLENGE_BUTTON_SELECTOR = os.environ.get(
"PX_CHALLENGE_BUTTON_SELECTOR",
"button",
)
SUCCESS_SELECTOR = os.environ.get(
"PX_SUCCESS_SELECTOR",
"",
).strip()
WAIT_TIMEOUT_SECONDS = 30
def validate_configuration() -> None:
if not TARGET_URL:
raise RuntimeError(
"Set TARGET_URL"
)
if not BYPASS_TOKEN:
raise RuntimeError(
"Set PX_CAPTCHA_BYPASS_TOKEN"
)
if not 1000 <= HOLD_TIME_MS <= 10000:
raise RuntimeError(
"PX_HOLD_TIME_MS must be between "
"1000 and 10000"
)
def configure_testing_headers(
driver: webdriver.Chrome,
) -> None:
unique_user_agent = (
"PhantomJS-press-hold-test-"
f"{int(time.time())}"
)
testing_token = (
f"{BYPASS_TOKEN}~{HOLD_TIME_MS}"
)
driver.execute_cdp_cmd(
"Network.enable",
{},
)
driver.execute_cdp_cmd(
"Network.setUserAgentOverride",
{
"userAgent": unique_user_agent,
},
)
driver.execute_cdp_cmd(
"Network.setExtraHTTPHeaders",
{
"headers": {
"x-px-captcha-testing": (
testing_token
),
},
},
)
def switch_to_challenge_frame(
driver: webdriver.Chrome,
) -> bool:
frames = driver.find_elements(
By.CSS_SELECTOR,
CHALLENGE_IFRAME_SELECTOR,
)
if not frames:
return False
driver.switch_to.frame(
frames[0]
)
return True
def press_and_hold(
driver: webdriver.Chrome,
) -> None:
wait = WebDriverWait(
driver,
WAIT_TIMEOUT_SECONDS,
)
button = wait.until(
EC.element_to_be_clickable(
(
By.CSS_SELECTOR,
CHALLENGE_BUTTON_SELECTOR,
)
)
)
actions = ActionChains(driver)
actions.move_to_element(button)
actions.click_and_hold(button)
actions.pause(
HOLD_TIME_MS / 1000
)
actions.release(button)
actions.perform()
def wait_for_success(
driver: webdriver.Chrome,
initial_url: str,
) -> bool:
driver.switch_to.default_content()
if SUCCESS_SELECTOR:
try:
WebDriverWait(
driver,
WAIT_TIMEOUT_SECONDS,
).until(
EC.presence_of_element_located(
(
By.CSS_SELECTOR,
SUCCESS_SELECTOR,
)
)
)
return True
except TimeoutException:
return False
try:
WebDriverWait(
driver,
WAIT_TIMEOUT_SECONDS,
).until(
lambda current_driver: (
current_driver.current_url
!= initial_url
)
)
return True
except TimeoutException:
return False
def main() -> None:
validate_configuration()
options = webdriver.ChromeOptions()
options.add_argument(
"--window-size=1440,1000"
)
driver = webdriver.Chrome(
options=options
)
try:
configure_testing_headers(
driver
)
driver.get(
TARGET_URL
)
initial_url = (
driver.current_url
)
switched = switch_to_challenge_frame(
driver
)
if not switched:
print(
"No challenge iframe was found. "
"The challenge may be rendered "
"directly in the document."
)
press_and_hold(
driver
)
solved = wait_for_success(
driver,
initial_url,
)
if not solved:
driver.save_screenshot(
"press-and-hold-failed.png"
)
raise RuntimeError(
"The expected success condition "
"was not detected"
)
driver.save_screenshot(
"press-and-hold-passed.png"
)
print(
"Press and Hold challenge "
"completed in test mode."
)
finally:
driver.quit()
if __name__ == "__main__":
main()
Run the test:
python press_and_hold_test.py
The iframe selectors are implementation-specific. Configure them through environment variables when the defaults do not match your application:
export PX_CHALLENGE_IFRAME_SELECTOR='iframe[data-testid="challenge-frame"]'
export PX_CHALLENGE_BUTTON_SELECTOR='button[data-testid="hold-button"]'
export PX_SUCCESS_SELECTOR='[data-testid="protected-content"]'
Important Selenium limitation
Some implementations may place the interactive element inside:
- a cross-origin iframe;
- a closed Shadow DOM;
- a vendor-controlled document;
- a customized blocking page.
Selenium cannot query a closed Shadow DOM through ordinary CSS selectors.
Do not attempt to modify browser internals or patch isTrusted values. For an application you control, use the vendor testing configuration or expose a stable test hook in staging.
A test hook can provide:
- a predictable iframe selector;
- a test-only success state;
- a controlled callback;
- a test-only challenge container;
- logging for challenge status changes.
Do not deploy test hooks or bypass tokens to public production code.
Testing a customized blocking page
A customized challenge page may require the application to handle a success callback.
For example, the integration may define:
window._pxOnCaptchaSuccess = function () {
window.location.reload();
};
Your test should verify that the callback:
- Receives the successful challenge state.
- Continues the interrupted application flow.
- Preserves the required cookies.
- Does not enter a reload loop.
- Handles a failed challenge separately.
If the progress bar completes but the page remains stuck, the problem may be in the success callback rather than in the hold interaction.
Testing keyboard accessibility
HUMAN Challenge provides keyboard-accessible interactions.
For accessibility testing:
- Use
Tabto move focus to the challenge. - Confirm that the focused control has an accessible name.
- Perform the documented keyboard interaction.
- Confirm that progress is announced correctly.
- Verify that success and failure states are accessible.
Do not treat keyboard access as a universal captcha bypass. It is an accessibility interface and remains subject to challenge validation.
A generic Selenium keyboard test may look like:
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys
actions = ActionChains(driver)
actions.send_keys(Keys.TAB)
actions.key_down(Keys.SPACE)
actions.pause(HOLD_TIME_MS / 1000)
actions.key_up(Keys.SPACE)
actions.perform()
The required key may depend on the focused control and the page implementation.
Why the challenge keeps repeating
Repeated challenges usually indicate that the complete test configuration was not accepted.
Check the following.
The bypass header was added too late
The header must be configured before navigating to the challenge page.
Incorrect:
driver.get(TARGET_URL)
configure_testing_headers(driver)
Correct:
configure_testing_headers(driver)
driver.get(TARGET_URL)
The token is invalid
Confirm that the token:
- was created in the correct HUMAN application;
- has not been deleted;
- was copied without extra whitespace;
- is sent under the correct header name.
The required header is:
x-px-captcha-testing
The hold duration does not match
If the header contains:
TOKEN~5000
the test should hold the button for approximately five seconds.
Do not configure:
TOKEN~5000
and release the button after one second.
Cookies from an earlier test remain active
Clear the browser profile or use a new temporary profile.
You can also use a unique testing User-Agent:
PhantomJS-press-hold-test-1720000000
The application callback is incomplete
The challenge may succeed while the application fails to continue.
Check:
- the success callback;
- redirects;
- cookie updates;
- application state;
- console errors;
- failed network requests.
How to structure automated tests
Do not make every application test depend on the live challenge.
A more stable testing strategy separates the workflow into layers.
Unit tests
Mock the result returned by the challenge integration.
Test:
- success handling;
- failure handling;
- retry handling;
- missing token behavior;
- application redirects.
Integration tests
Use the vendor-issued bypass token.
Test:
- challenge rendering;
- successful press and hold;
- application callback;
- cookies;
- protected page access.
Production smoke tests
Run a limited number of authorized tests against the real deployment.
Do not run production challenge tests on every commit or in a high-frequency loop.
What not to use
Avoid unsupported or unverifiable techniques such as:
- modifying Chromium source code to forge trusted input;
- patching the
isTrustedproperty; - injecting fake touch-pressure telemetry;
- randomizing TLS handshakes;
- changing browser fingerprints during a session;
- replaying challenge tokens;
- attempting to access closed Shadow DOM internals;
- using unrelated captcha API methods;
- relying on claimed zero-detection browsers.
These techniques are fragile, difficult to validate, and inappropriate for ordinary integration testing.
The vendor-issued bypass token provides a controlled and repeatable test path without attempting to defeat the production detection system.
Frequently asked questions
What is Press and Hold captcha?
It is a behavioral challenge where the user presses a control, holds it until verification completes, and releases it.
Which company provides this challenge?
The implementation commonly described as Press and Hold is HUMAN Challenge.
Does SolveCaptcha have a Press and Hold API method?
The current SolveCaptcha API documentation does not list a dedicated Press and Hold or HUMAN Challenge method.
Can I use the Turnstile API method?
No. Cloudflare Turnstile and HUMAN Challenge are different systems.
Can JavaScript solve the challenge with click()?
No. A click does not reproduce the required hold sequence or the complete challenge state.
Can Selenium press and hold the button?
Yes, Selenium can generate the interaction. For repeatable authorized tests, combine it with a vendor-issued CAPTCHA Bypass Token.
How can I control the required hold time?
Append a tilde and the required duration in milliseconds to the testing token:
YOUR_TOKEN~5000
Which header contains the testing token?
Use:
x-px-captcha-testing
Can the bypass token be used on another website?
No. It is issued by the owner of a specific protected application and should remain a private testing secret.
Why does the progress bar complete but the page remain blocked?
The application’s success callback, redirect, cookie handling, or customized blocking-page integration may be incomplete.
Should I use a captcha-solving service for this challenge?
Use a captcha-solving API only when it explicitly documents support for the challenge type. Do not submit Press and Hold captcha through an unrelated API method.
Conclusion
Press and Hold captcha is designed to evaluate more than a fixed mouse duration. A reliable production bypass cannot be reduced to:
button.click();
For authorized automated testing, use the official HUMAN testing workflow:
- Create a CAPTCHA Bypass Token.
- Add it through
x-px-captcha-testing. - Optionally specify the hold duration with
~milliseconds. - Configure the header before opening the page.
- Perform the press-and-hold interaction with Selenium.
- Verify the application callback and success state.
- Keep the bypass token out of public code.
- Use mocks for ordinary unit and CI tests.
SolveCaptcha does not currently document a dedicated Press and Hold method. Use only documented captcha methods or contact SolveCaptcha support to confirm whether a custom integration is available.