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
services:
  cap:
    image: tiago2/cap:latest
    container_name: cap
    ports:
      - "3000:3000"
    environment:
      ADMIN_KEY: your_secret_password
      REDIS_URL: redis://valkey:6379
    depends_on:
      valkey:
        condition: service_healthy
    restart: unless-stopped

  valkey:
    image: valkey/valkey:8-alpine
    container_name: cap-valkey
    volumes:
      - valkey-data:/data
    command: valkey-server --save 60 1 --loglevel warning --maxmemory-policy noeviction
    healthcheck:
      test: ["CMD", "valkey-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 5
    restart: unless-stopped

volumes:
  valkey-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.

Instrumentation challenges are enabled by default when creating new site keys. We recommend keeping them on, as they significantly raise the bar for bots. You can also enable headless browser detection for additional protection.

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.