Skip to content

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:

yaml
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_KEY is your dashboard's login. We recommend making it at least 32 characters
  • Change 3000:3000 if that port is already in use on your host.
  • If the dashboard is unreachable, try adding network_mode: "host" under the cap service.

Start the container:

bash
docker compose up -d

Open 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:

html
<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:

bash
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:

json
{ "success": true }

Built in Europe 🇪🇺
Released under the Apache 2.0 License.