PermaData Captcha
A user-friendly bot detection system that analyzes natural mouse movements
Installation
Link to this sectionThere are two ways to install PermaData Captcha: using the React component or the standalone script.
1. Install the package
npm install @permadata/captcha2. Import and use the component
import { CaptchaCheckbox } from '@permadata/captcha';
function MyForm() {
const [isCaptchaValid, setIsCaptchaValid] = useState(false);
const [captchaToken, setCaptchaToken] = useState(null);
const handleCaptchaValidityChange = (isValid, token) => {
setIsCaptchaValid(isValid);
setCaptchaToken(token);
};
return (
<form>
{/* Your form fields */}
<CaptchaCheckbox onValidityChange={handleCaptchaValidityChange} />
<button type="submit" disabled={!isCaptchaValid}>Submit</button>
</form>
);
}Server-Side Verification
Link to this sectionAlways verify the captcha token on your server before processing form submissions. PermaData provides a server-side verification library for multiple platforms.
1. Install the package
npm install @permadata/captcha-verify2. Verify the token
// Next.js API Route or Server Action
import { verifyCaptchaToken } from '@permadata/captcha-verify';
// In a Next.js API route
export async function POST(request) {
const { captchaToken, ...formData } = await request.json();
// Verify the captcha token
const result = await verifyCaptchaToken(captchaToken, {
apiKey: process.env.PERMADATA_API_KEY // Your PermaData API key
});
if (!result.valid) {
return Response.json({
success: false,
error: 'Captcha verification failed'
}, { status: 400 });
}
// Process the form data
// ...
return Response.json({ success: true });
}
// In a Server Action
'use server'
export async function processForm(formData) {
const captchaToken = formData.get('captcha-token');
// Verify the captcha token
const result = await verifyCaptchaToken(captchaToken, {
apiKey: process.env.PERMADATA_API_KEY // Your PermaData API key
});
if (!result.valid) {
return {
success: false,
error: 'Captcha verification failed'
};
}
// Process the form data
// ...
return { success: true };
}Complete Implementation Example
Link to this sectionHere's a complete example of a contact form with client-side and server-side captcha validation using Next.js.
Client Component
// app/contact/page.tsx
'use client'
import { useState } from 'react'
import { CaptchaCheckbox } from '@permadata/captcha'
import { submitContactForm } from '@/app/actions/contact-form'
export default function ContactPage() {
const [isCaptchaValid, setIsCaptchaValid] = useState(false)
const [captchaToken, setCaptchaToken] = useState<string | undefined>(undefined)
const [isSubmitting, setIsSubmitting] = useState(false)
const [formResponse, setFormResponse] = useState<{ success: boolean; message?: string; error?: string } | null>(null)
const handleCaptchaValidityChange = (isValid: boolean, token?: string) => {
setIsCaptchaValid(isValid)
setCaptchaToken(token)
}
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
if (!isCaptchaValid || !captchaToken) {
setFormResponse({
success: false,
error: "Please complete the captcha verification",
})
return
}
setIsSubmitting(true)
setFormResponse(null)
try {
// Get form data
const formData = new FormData(e.currentTarget)
// Add captcha token to form data
formData.append("captcha-token", captchaToken)
// Submit the form
const response = await submitContactForm(formData)
setFormResponse(response)
// Reset form on success
if (response.success) {
e.currentTarget.reset()
setIsCaptchaValid(false)
setCaptchaToken(undefined)
}
} catch (error) {
setFormResponse({
success: false,
error: "An unexpected error occurred",
})
} finally {
setIsSubmitting(false)
}
}
return (
<div className="max-w-md mx-auto">
<h1 className="text-2xl font-bold mb-6">Contact Us</h1>
{formResponse?.success ? (
<div className="bg-green-50 p-6 rounded-md">
<h3 className="text-xl font-semibold text-green-800 mb-2">Message Sent!</h3>
<p className="text-green-700">{formResponse.message}</p>
</div>
) : (
<form onSubmit={handleSubmit} className="space-y-6">
{formResponse?.error && (
<div className="bg-red-50 p-4 rounded-md">
<span className="text-red-700">{formResponse.error}</span>
</div>
)}
<div>
<label htmlFor="name" className="block text-sm font-medium text-gray-700">Name</label>
<input
id="name"
name="name"
type="text"
required
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm"
/>
</div>
<div>
<label htmlFor="email" className="block text-sm font-medium text-gray-700">Email</label>
<input
id="email"
name="email"
type="email"
required
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm"
/>
</div>
<div>
<label htmlFor="message" className="block text-sm font-medium text-gray-700">Message</label>
<textarea
id="message"
name="message"
rows={4}
required
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm"
></textarea>
</div>
<div>
<CaptchaCheckbox onValidityChange={handleCaptchaValidityChange} />
</div>
<button
type="submit"
className="w-full bg-blue-600 text-white py-2 px-4 rounded-md"
disabled={isSubmitting || !isCaptchaValid}
>
{isSubmitting ? "Sending..." : "Send Message"}
</button>
</form>
)}
</div>
)
}Server Action
// app/actions/contact-form.ts
'use server'
import { verifyCaptchaToken } from '@permadata/captcha-verify'
export async function submitContactForm(formData: FormData) {
// Extract the captcha token
const captchaToken = formData.get("captcha-token") as string
if (!captchaToken) {
return { success: false, error: "Captcha verification required" }
}
// Verify the captcha token
try {
const verifyResult = await verifyCaptchaToken(captchaToken, {
apiKey: process.env.PERMADATA_API_KEY // Your PermaData API key
})
if (!verifyResult.valid) {
return { success: false, error: verifyResult.error || "Captcha verification failed" }
}
// Extract form data
const name = formData.get("name") as string
const email = formData.get("email") as string
const message = formData.get("message") as string
// Validate form data
if (!name || !email || !message) {
return { success: false, error: "All fields are required" }
}
// Process the form data (e.g., send email, save to database)
// This is just a placeholder for your actual implementation
console.log("Form submission:", { name, email, message })
// Return success response
return {
success: true,
message: "Thank you for your message! We will get back to you soon.",
}
} catch (error) {
console.error("Error processing form:", error)
return { success: false, error: "An error occurred while processing your request" }
}
}API Reference
Link to this sectionCaptchaCheckbox Component Props
| Prop | Type | Default | Description |
|---|---|---|---|
| onValidityChange | (isValid: boolean, token?: string) => void | undefined | Callback function that receives the validation state and token |
| className | string | "" | Additional CSS classes to apply to the component |
| theme | "light" | "dark" | "light" | Visual theme of the captcha component |
Verification API Response
| Property | Type | Description |
|---|---|---|
| valid | boolean | Whether the captcha token is valid |
| formToken | string | A new token for form submission (only present if valid is true) |
| error | string | Error message (only present if valid is false) |
Security Considerations
Link to this sectionWhile PermaData Captcha provides strong protection against automated bots, it's important to follow these best practices:
- Always validate on the server: Client-side validation can be bypassed, so always verify the captcha token on your server before processing sensitive operations.
- Token expiration: Captcha tokens expire after 15 minutes. Ensure users complete forms within this timeframe or prompt them to refresh the captcha.
- Additional protections: For highly sensitive operations, consider combining the captcha with other security measures like rate limiting and IP-based restrictions.
- Keep your API keys secure: Never expose your PermaData API keys in client-side code.
Troubleshooting
Link to this sectionCaptcha not validating
If the captcha is not validating properly, ensure that:
- You're correctly passing the token to your server
- The token hasn't expired (tokens are valid for 15 minutes)
- Your server can reach the verification API endpoint
- You're using the correct API key
Accessibility issues
The captcha is designed to be accessible, but if users report issues:
- Ensure keyboard navigation is working properly
- Check that screen readers can interpret the captcha status
- Consider providing an alternative verification method for users with disabilities
Integration issues
If you're having trouble integrating the captcha:
- Check that you're using the latest version of the package
- Ensure you've followed all installation steps correctly
- Check the browser console for any JavaScript errors
- Verify that your server environment meets all requirements
Support
Link to this sectionIf you need help with PermaData Captcha, there are several resources available:
Documentation
Comprehensive documentation with examples and API references.
View DocumentationCommunity Forum
Connect with other developers and get help from the community.
Join the CommunitySupport
Get direct support from our team for technical issues.
Contact SupportGitHub
Report issues, contribute, or explore the source code.
View on GitHub