Getting Started
Install, configure, and extend better-captcha for production-ready CAPTCHA integrations.
This library is in early development and is not production ready yet. Expect breaking API changes while the provider surface stabilizes.
Overview
better-captcha provides a unified, framework-agnostic interface for popular CAPTCHA providers. Each widget ships as a client component that:
- ✅ Loads provider scripts safely on demand
- ✅ Exposes a predictable imperative handle
- ✅ Makes tokens easy to retrieve during form submissions
- ✅ Shares the same lifecycle across all providers
- ✅ Allows you to swap vendors without touching your UI
Quick Start
1. Install the package for your framework
| Framework | Package | Installation |
|---|---|---|
| React | @better-captcha/react | npm i @better-captcha/react |
| Qwik | @better-captcha/qwik | npm i @better-captcha/qwik |
| SolidJS | @better-captcha/solidjs | npm i @better-captcha/solidjs |
| Vue | @better-captcha/vue | npm i @better-captcha/vue |
| Svelte | @better-captcha/svelte | npm i @better-captcha/svelte |
| Lit | @better-captcha/lit | npm i @better-captcha/lit |
2. Import and use a provider
import { ReCaptcha } from "@better-captcha/react/provider/recaptcha";
export function ContactForm() {
return <ReCaptcha sitekey="your-site-key" />;
}3. Access the handle to control the widget
import { useRef } from "react";
import { ReCaptcha, type ReCaptchaHandle } from "@better-captcha/react/provider/recaptcha";
export function ContactForm() {
const captchaRef = useRef<ReCaptchaHandle>(null);
const handleSubmit = async () => {
const token = captchaRef.current?.getResponse();
// Send token to your backend for verification
};
return (
<form onSubmit={handleSubmit}>
<ReCaptcha ref={captchaRef} sitekey="your-site-key" />
<button type="submit">Submit</button>
</form>
);
}Supported Providers
| Provider | Description | Auto Theme |
|---|---|---|
| ReCaptcha | Google's comprehensive bot protection | Enhanced ✨ |
| hCaptcha | Privacy-focused with monetization | Enhanced ✨ |
| Turnstile | Cloudflare's privacy-first alternative | Native ✅ |
| Friendly Captcha | GDPR-compliant, no user interaction | Native ✅ |
| Private Captcha | Self-hosted with full control | Enhanced ✨ |
| Captcha Fox | Customizable themes and challenges | Enhanced ✨ |
| Prosopo | Web3-integrated bot protection | Enhanced ✨ |
| CapWidget | Cap.JS widget library | N/A |
Key Features
Unified API
All providers share the same imperative handle methods:
render()- Render the CAPTCHA widgetexecute()- Trigger the CAPTCHA challengereset()- Reset the widget to its initial statedestroy()- Clean up and remove the widgetgetResponse()- Get the current response token
Lifecycle Callbacks
Every provider supports three lifecycle callbacks:
onReady- Called when the widget is rendered and readyonSolve- Called when the challenge is solved with a tokenonError- Called when an error occurs
Framework-Specific Integration
Each framework has its own idiomatic way of accessing the handle:
- React:
useRefhook - Qwik:
useCaptchaControllerhook - SolidJS:
createCaptchaControllerfunction - Vue:
useCaptchacomposable or template refs - Svelte:
bind:thisdirective - Lit:
getHandle()method
Next Steps
- Choose your framework and learn the framework-specific patterns
- Explore provider options for your chosen CAPTCHA service
- Configure auto theme for automatic dark/light mode support
- Customize script loading behavior