Position + movement trace
CaptchaHandler retrieves the stored challenge, checks that the shape was snapped near the target, and calls BehaviorAnalyzer with movement samples and duration.
Successful result: issue a random pass token.A drag-and-drop CAPTCHA that checks the gesture as well as where it ends.
The browser records a movement trace. Your PHP endpoint checks the drop position and movement characteristics, then issues a one-time pass token. Your form handler checks that token before accepting the protected action.
The first check evaluates a challenge attempt. The second consumes its pass token when your application receives the form. Showing a successful widget state does not replace that submission check.
CaptchaHandler retrieves the stored challenge, checks that the shape was snapped near the target, and calls BehaviorAnalyzer with movement samples and duration.
Successful result: issue a random pass token.The application calls verifyPass(). The handler reads and deletes the stored pass, then compares it with the submitted token.
Same token submitted again: no stored pass remains.Movement samples contain x, y and t values: position and time. The analyser checks sample count and duration, then considers speed variation, path length relative to direct distance, direction changes near the end and small acceleration changes.
These are heuristic signals used to accept or reject the attempt. They do not establish a person's identity or guarantee that all automated interactions will be rejected.
Read BehaviorAnalyzer ↗The project separates the JavaScript widget from the PHP handler. Its storage interface has session and Redis implementations, so challenge state and pass tokens can live behind the same handler API.
Visual settings are configurable, including colours and shape options. The endpoint sends no-cache headers so a cached challenge is not substituted for a fresh interaction.
The default handler sets a five-minute challenge lifetime and a ten-minute pass lifetime. Verification consumes the challenge, and checking a pass consumes the stored token. Failed or expired attempts therefore need a fresh challenge.
Load and configure the widget; send its challenge requests to your endpoint.
Use CaptchaHandler with the chosen storage implementation to create and verify challenges.
Check the pass token alongside your field validation and application permissions.
The repository tests challenge creation, rejection without a stored challenge, an incorrect position, empty movements and single-use pass tokens. It also tests the movement analyser separately.
For your form, test the entire submission and recovery path with the people and devices that will use it. A movement challenge needs an accessible alternative for visitors who cannot perform that interaction.
Read the handler tests ↗The challenge and verification run in the self-hosted widget and PHP endpoint. Session storage may use your application session cookie; self-hosted does not mean the whole application is cookie-free.
No. Your form still needs input validation, request protection, permissions and appropriate rate controls. The CAPTCHA adds a gesture check to that flow.
verifyPass() deletes the stored pass when checking it. The repository test checks that a token succeeds once and fails on a second check.
The Composer manifest specifies the PHP constraint; the README explains PHP and browser-package installation. Review the selected revision and its dependencies for your PHP 8.5 deployment.
Tell us about your application, form endpoint and hosting setup if you need help integrating AOCaptcha.
Discuss integration ↗