Self-hosted service
tiagozip/cap avatar
tiagozip/cap

Cap: a self-hosted proof-of-work CAPTCHA that runs without visual puzzles

Free, open-source and self-hosted CAPTCHA alternative to reCAPTCHA. Privacy-first and powered by proof-of-work and instrumentation challenges.

7,904 stars601 forksJavaScriptNOASSERTION

At a glance

What is it?
Cap replaces image grids with proof-of-work and instrumentation challenges, and ships as a standalone Docker service plus a JavaScript widget. Here is what it does, how to deploy it, and where it falls short.
Who is it for?
Adopt Cap if you want a self-hosted challenge that avoids image puzzles and third-party telemetry, and you can run the standalone container yourself. Skip it if your threat model includes determined, well-funded bots, since proof-of-work only raises the cost of an automated request rather than blocking it.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 6 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Cap replaces, and who it is built for

Cap is a CAPTCHA alternative that drops the image-selection puzzle entirely. Instead of asking a human to identify traffic lights, it issues a proof-of-work challenge and a set of instrumentation checks. The repository describes it as a replacement for reCAPTCHA, hCaptcha and Cloudflare Turnstile, and the README frames the main selling point as privacy: "Cap doesn't send any telemetry back to our servers."

The audience is fairly narrow and fairly clear. It suits teams running their own infrastructure who want bot mitigation without handing visitor data to a third party, and who are willing to operate one more service. It also suits projects where a visual puzzle is a genuine accessibility problem, since there are no images to interpret. The README notes the widget can be hidden entirely so challenges are solved in the background, which removes the interaction step for ordinary visitors.

It does not suit anyone looking for a managed, hands-off service with a support contract. A free hosted instance is mentioned in the README's sponsorship comment, but the documented path is self-hosting.

Proof-of-work and instrumentation: the two challenge types

Cap uses two mechanisms, and the documentation treats them as separate pages (effectiveness and instrumentation).

Proof-of-work is the first. The client is handed a computational puzzle and must spend CPU cycles to find a solution before the request is accepted. This does not prove a human is present. It proves that whoever is submitting the form paid a measurable cost in time and electricity. A single browser tab barely notices. A script firing thousands of submissions per minute notices a great deal, because each attempt carries the same cost. That is the whole design: raise the per-request price of automation until bulk abuse stops being worthwhile.

The second mechanism is instrumentation. Rather than asking the user a question, Cap observes signals from the client environment to distinguish a real browser session from a scripted one. The README lists instrumentation challenges as a distinct feature alongside proof-of-work, and links to a dedicated guide page for it. The repository does not spell out the individual signals in the README itself, so the specifics live in the documentation site rather than in the code listing.

The practical consequence of this pairing is that Cap's difficulty is tunable along an economic axis rather than a perceptual one. You are not making a puzzle harder to see. You are making it more expensive to solve repeatedly.

Installing Cap with the standalone Docker container

The README states that "the default way to use Cap is with the Standalone Docker container," and the repository has a top-level standalone/ directory alongside core/, widget/ and wasm/. The docs site and a Railway deploy template are the two entry points the README points to. Because the README does not reproduce the full container invocation, treat the documentation as the source of truth for flags and environment variables.

The shape of a deployment is a container serving the challenge API and the widget assets, with your application calling it to issue and verify challenges. The README does not give a runnable docker command, so the exact image tag and port come from the docs rather than from this article.

On the client side, the repository ships a widget/ directory and a wasm/ directory, and the README references an npm package under the @cap.js scope (the badge in the README points at @cap.js/wasm on jsDelivr). The README's own framing is that Cap is roughly 20kb with zero dependencies and "loads in milliseconds." The repository's demo/index.html and demo/index.js are the working integration examples to read first.

Once the widget is mounted, it renders the challenge and, after solving, exposes a token your backend must verify against the Cap endpoint before accepting the form. The README does not document the verification call in detail, so confirm the endpoint path and payload in the docs before wiring it up. What you should see after a correct setup is the widget completing without user input and a token appearing in the DOM.

The customization surface is CSS, and that is the point

Cap's README lists colors, size, position and icons as things you change "with CSS variables." This is a deliberate architectural choice: the widget is a DOM element you style, not an iframe you negotiate with. That matters for teams who have been burned by CAPTCHA vendors whose widget cannot be made to match a design system, and it matters for layout, because a styled element participates in your page's flow.

The trade-off is that styling a widget you host means you also own its accessibility and its failure states. A third-party CAPTCHA degrades in ways the vendor controls. A self-hosted widget degrades in ways you control, which is better when you have the engineering time and worse when you do not. The README claims the challenges are "accessible," and removing images does help screen readers, but the repository README does not describe keyboard interaction or ARIA attributes for the widget, so that claim is one to verify against the docs and your own assistive-technology testing rather than take on faith.

Where Cap is the wrong tool

Proof-of-work is a cost imposition, not a gate. An attacker with a botnet, a pool of cheap cloud instances, or a browser-farm service can absorb the compute and keep going. The mechanism raises the floor for casual scripted abuse and does essentially nothing against a motivated adversary with budget. If your threat model includes credential stuffing at scale or scraping by an organised operation, a proof-of-work CAPTCHA is a speed bump, and you should be pairing it with rate limiting and server-side anomaly detection rather than treating it as the defence.

The instrumentation half is harder to assess from the repository alone, because the README does not enumerate the signals. Any behavioural or environmental fingerprinting carries a false-positive risk: privacy-hardened browsers, unusual user agents and headless setups can look scripted. The README does not document a fallback flow for users who fail instrumentation repeatedly, and it does not document rollback for a bad deployment. If you need a guaranteed path for a legitimate user who cannot pass, you will have to build one.

Self-hosting also means you own availability. If the container is down, your forms are down. A managed CAPTCHA moves that failure to someone else's status page. That is a real operational cost, not a footnote.

How Cap differs from ALTCHA and mCaptcha

The closest comparisons are ALTCHA and mCaptcha, both of which appear in the search terms people use around this project, and both of which are also proof-of-work based. The difference is in scope rather than in the core mechanism.

ALTCHA is distributed primarily as a web component and library that you embed, with a strong emphasis on being a drop-in element for existing forms. mCaptcha is built around a self-hosted server that issues and verifies challenges, closer in spirit to Cap's standalone mode. Cap sits between them: it ships a styled widget plus a standalone container with what the README calls "analytics & more," and it adds instrumentation challenges on top of the proof-of-work that all three share.

If your requirement is the smallest possible client-side footprint with no server to run, a library-only approach is lighter than Cap's container. If your requirement is a server you control with a dashboard, Cap's standalone mode is the relevant comparison. The distinguishing feature here is the instrumentation layer, and that is also the part the README documents least, so evaluate it against the docs site before committing.

Licence, maintenance and upgrade cost

The README states the project is licensed under Apache 2.0, while the repository metadata reports the licence as NOASSERTION, meaning GitHub's detector could not classify it automatically. The LICENSE file in the repository root is the authoritative text; read it rather than relying on the metadata field. Apache 2.0 is permissive and includes a patent grant, which matters if you are embedding the widget in a commercial product. This is a description of the licence, not legal advice.

The repository is not archived, and the last push was on 2026-09-21, one day before this writing. Recent releases are tagged under the standalone package, with [email protected] published on 2026-09-04, following [email protected] on 2026-07-22 and [email protected] on 2026-07-15. That cadence suggests the standalone container is the actively released artefact, and it is the one to pin.

Upgrade cost is low by construction. The client is described as roughly 20kb with zero dependencies, so there is no dependency tree to reconcile. The real upgrade risk is the container's API contract with your backend, and the release notes are the place to check for changes there before bumping the tag.

Editorial conclusion

Adopt Cap if you want a self-hosted challenge that avoids image puzzles and third-party telemetry, and you can run the standalone container yourself. Skip it if your threat model includes determined, well-funded bots, since proof-of-work only raises the cost of an automated request rather than blocking it. Before rollout, verify that your client-side integration loads the widget from your own server and that your backend calls the validation endpoint, since a widget that renders but is never checked protects nothing.

Frequently asked questions

Is there a free CAPTCHA service available?

Cap is free and open source under the Apache 2.0 license, and you can self-host the standalone Docker container at no licence cost. The README also links to a Railway deploy template and mentions a free instance supported by DigitalOcean.

Can AI outsmart CAPTCHA?

Cap does not rely on visual puzzles, so image-recognition advances do not directly apply to it. Its proof-of-work challenge imposes a compute cost on each submission instead of testing perception, and the README presents this as the reason users no longer solve visual puzzles.

How does Cap compare to reCAPTCHA?

The README positions Cap as an alternative to reCAPTCHA, hCaptcha and Cloudflare Turnstile, and states that Cap sends no telemetry back to its servers. It replaces image challenges with proof-of-work and instrumentation challenges, and can be self-hosted via the standalone Docker container.

Do I need to run a server to use Cap?

The README says the default way to use Cap is with the Standalone Docker container, which also provides analytics. The repository also ships a widget and a wasm package under the @cap.js scope, so the client side is separable from the server deployment.

Can Cap's widget be hidden from users?

Yes. The README lists "no user interaction needed" as a feature and states that you can hide Cap's widget and solve challenges in the background. That removes the visible puzzle step for ordinary visitors.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Releases
  5. tiagozip/cap on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/tiagozip-cap.svg)](https://hysenlabs.com/projects/tiagozip-cap)