Cap Standalone
Cap Standalone is the recommended way to self-host Cap's backend. It runs on Bun and keeps idle memory usage around 50 MB. It ships with built-in support for instrumentation challenges, which significantly raise the bar for bots, a siteverify API compatible with reCAPTCHA, and a web dashboard for managing multiple site keys.
We recommend using Docker to run Cap Standalone.
Installation
Create a docker-compose.yml file:
version: "3.8"
services:
cap:
image: tiago2/cap:latest
container_name: cap
ports:
- "3000:3000"
environment:
ADMIN_KEY: your_secret_password
volumes:
- cap-data:/usr/src/app/.data
restart: unless-stopped
volumes:
cap-data:Tips
ADMIN_KEYis your dashboard's login. We recommend making it at least 32 characters- Change
3000:3000if that port is already in use on your host. - If the dashboard is unreachable, try adding
network_mode: "host"under thecapservice.
Start the container:
docker compose up -dOpen http://localhost:3000 (or your server's IP/domain on port 3000) to access the dashboard. Log in with your admin key, create a site key, and note down both the site key and its secret key, you'll need both.
If you want the best protection and can handle higher memory usage, we also recommend turning on instrumentation challenges and potentially headless browser detection.
Your Cap Standalone instance must be publicly reachable from the internet so the widget can communicate with it. If you're using a reverse proxy, review the options guide to configure rate-limiting correctly.
Usage
Client-side
Point the widget at your instance by setting the data-cap-api-endpoint attribute:
https://<instance_url>/<site_key>/<instance_url>— the public URL of your Cap Standalone instance<site_key>— the site key from your dashboard
Example:
<cap-widget data-cap-api-endpoint="https://cap.example.com/d9256640cb53/"></cap-widget>We recommend reading our widget documentation for more details and example snippets for multiple frameworks.
Server-side
Once a user completes the CAPTCHA, your backend must verify the token before trusting it. Send a POST request to your instance's /siteverify endpoint with the following JSON body:
curl "https://<instance_url>/<site_key>/siteverify" \
-X POST \
-H "Content-Type: application/json" \
-d '{ "secret": "<key_secret>", "response": "<captcha_token>" }'Where <key_secret> is the secret key from your dashboard (not the dashboard admin key), and <captcha_token> is the challenge token generated by the widget.
A successful verification returns:
{ "success": true }