AOCAPTCHA / SELF-HOSTED PHP + JAVASCRIPT

Drag the shape.
Check the movement.
Verify on your server.

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.

Original illustration · explore the approach and details below.
FROM WIDGET TO FORM HANDLER

Two server checks.
Different responsibilities.

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.

01 / CHALLENGE VERIFICATION

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.
ONE-TIME
PASS TOKENSent with the form
02 / FORM SUBMISSION

Consume the stored 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.
Inspect CaptchaHandler ↗
WHAT THE ANALYSER ACTUALLY READS

A sequence of points.
Changes within the gesture.

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 ↗
HOSTING AND INTEGRATION

Your endpoint.
Your form workflow.

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.

THREE PLACES TO CONNECT
  1. The page

    Load and configure the widget; send its challenge requests to your endpoint.

  2. The challenge endpoint

    Use CaptchaHandler with the chosen storage implementation to create and verify challenges.

  3. The form handler

    Check the pass token alongside your field validation and application permissions.

Read the integration example ↗
WHAT TO CHECK BEFORE DEPLOYMENT

A pass, a retry
and a repeated submission.

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 ↗
Does it call an external CAPTCHA service?

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.

Does this replace other form protection?

No. Your form still needs input validation, request protection, permissions and appropriate rate controls. The CAPTCHA adds a gesture check to that flow.

Can a successful token be reused?

verifyPass() deletes the stored pass when checking it. The repository test checks that a token succeeds once and fails on a second check.

Where are PHP and installation requirements listed?

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.

ADD THE CHECK TO THE WHOLE FORM FLOW

The widget is one part.
The submission completes it.

Tell us about your application, form endpoint and hosting setup if you need help integrating AOCaptcha.

Discuss integration ↗

A GOOD PLACE TO START

Tell us about the idea.

Share a little about your goals and we will take it from there.

We use these details to respond to your enquiry. Read our Privacy Policy and Cookie Policy.

Loading verification…

Drag the shape onto its outline. If you cannot use the challenge, email us instead.