Captcha Integration Guide
Learn how to add captcha protection to your forms to protect your website from bots and spam. PrivateStater Captcha is designed to work seamlessly for customers using VPNs. (Google reCAPTCHA often requires VPN users to solve more than 10 captchas.)
How It Works
PrivateStater captcha uses 3-step verification:
- Honeypot - Detects hidden fields that bots and AI automatically fill
It is mainly effective in defending against AI bots, but customers using AI browsers may also be blocked, so uncheck to disable the function if not needed.
- Puzzle Challenge - User drags a puzzle piece to fit
- PoW (Proof of Work) - Performs 5 rounds of Argon2id hashing to block bots
Step 1: Install the Script
Add the following script to your website's <head> section:
<script>
window.PrivateStaterConfig = { prstSite: "YOUR_SITE_ID" };
</script>
<script src="https://privatestater.com/privatestater.js"></script>
Replace YOUR_SITE_ID with your website ID from the dashboard.
Step 2: Enable Captcha in the Dashboard
- Navigate to Dashboard > Website > Captcha > Settings
- Turn on Enable Captcha
- Configure the options as needed
Configuration Options
| Setting | Description | Default |
|---|---|---|
| Enabled | Enable captcha feature | Disabled |
| Allow Localhost | Allow testing on localhost | Disabled |
| Honeypot Enabled | Hidden field for AI/bot detection | Enabled |
| PoW Level | Proof of Work difficulty (low/medium/high) | medium |
PoW Difficulty Levels
| Level | Memory Usage | Iterations | Estimated Time |
|---|---|---|---|
| low | 4MB | 16 | ~1 second |
| medium | 8MB | 24 | ~2 seconds |
| high | 16MB | 32 | ~3 seconds |
Higher difficulty is more effective at blocking bots but increases user wait time.
Step 3: Add the Captcha Widget
Method 1: Auto-initialization (Recommended)
Add a div with the data-captcha attribute where you want to display the captcha in your form:
<form id="contact-form">
<input type="text" name="name" placeholder="Name">
<input type="email" name="email" placeholder="Email">
<!-- Captcha Widget -->
<div data-captcha="prst"></div>
<button type="submit">Submit</button>
</form>
The captcha widget will automatically appear when the page loads.
Method 2: Programmatic
You can dynamically display the captcha using JavaScript:
window.PrivateStater.showCaptcha({
container: document.getElementById('captcha-container'),
onSuccess: function(token) {
console.log('Verification successful! Token:', token);
// Send token to your server
},
onError: function(error) {
console.error('Verification failed:', error);
}
});
showCaptcha Options
| Option | Type | Description |
|---|---|---|
container |
Element | DOM element to render captcha (optional, defaults to document.body) |
onSuccess |
Function | Success callback (receives token) |
onError |
Function | Failure callback (receives error message) |
Return Value
showCaptcha returns an object with the following methods:
const captcha = await window.PrivateStater.showCaptcha({...});
// Remove widget
captcha.destroy();
Step 4: Handle the Callback
Auto-initialization Method (data-captcha)
Define global callback functions:
<script>
window.onPrivateStaterCaptchaSuccess = function(token) {
console.log('Captcha verification successful!');
// Add token to form
document.getElementById('captcha-token').value = token;
// Or submit form directly
document.getElementById('contact-form').submit();
};
window.onPrivateStaterCaptchaError = function(error) {
console.error('Captcha error:', error);
alert('Captcha verification failed. Please try again.');
};
</script>
Form Submission Example
<form id="contact-form" action="/submit" method="POST">
<input type="text" name="name" required>
<input type="email" name="email" required>
<!-- Hidden field to store captcha token -->
<input type="hidden" id="captcha-token" name="captchaToken">
<!-- Captcha Widget -->
<div data-captcha="prst"></div>
<button type="submit">Submit</button>
</form>
<script>
window.onPrivateStaterCaptchaSuccess = function(token) {
document.getElementById('captcha-token').value = token;
};
</script>
Step 5: Verify the Token on Your Server
You must verify the token received from the client on your server.
API Request
const response = await fetch('https://privatestater.com/api/captcha/validate', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
websiteId: 'YOUR_SITE_ID',
verifyToken: captchaToken
})
});
const result = await response.json();
if (result.success) {
// Captcha verification successful, proceed with form processing
} else {
// Verification failed
console.error('Captcha verification failed:', result.error);
}
Node.js/Express Example
app.post('/submit', async (req, res) => {
const { name, email, captchaToken } = req.body;
// Verify captcha token
const captchaResponse = await fetch('https://privatestater.com/api/captcha/validate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
websiteId: process.env.PRST_SITE_ID,
verifyToken: captchaToken
})
});
const captchaResult = await captchaResponse.json();
if (!captchaResult.success) {
return res.status(400).json({ error: 'Captcha verification failed' });
}
// Captcha verification successful, proceed with form processing
// ...
res.json({ success: true });
});
Validation API Response
On success:
{
"success": true
}
On failure:
{
"success": false,
"error": "token_invalid_or_expired"
}
Important Notes
- Tokens are single-use only. They are immediately discarded after verification.
- Tokens expire after 5 minutes.
- Verification must be performed server-side.
Captcha Statistics
You can view captcha usage statistics in the dashboard:
| Statistic | Description |
|---|---|
| Attempts | Number of captcha challenges created |
| Success | Number of verifications completed |
| Honeypot Failures | Number of bots caught by honeypot |
| Puzzle Failures | Number of puzzle matching failures |
| PoW Failures | Number of proof of work failures |
| Timeouts | Number of failures to complete within 5 minutes |
| Success Rate | Success / Attempts ratio |
Styling
The captcha widget is isolated using Shadow DOM, so it's unaffected by external CSS. The widget automatically adapts to dark and light modes (prefers-color-scheme detection).
Multi-language Support
The captcha widget automatically displays in Korean or English based on browser language. If you need additional languages, please contact us and I will add them quickly.
Troubleshooting
Captcha widget doesn't appear
- Verify captcha is enabled in the dashboard
- Check the script is correctly installed
- Check for errors in the console
Doesn't work on localhost
Enable the Allow Localhost option in the dashboard.
Token verification fails
- Check if the token has expired (valid for 5 minutes)
- Check if the token was already used (single-use)
- Verify
websiteIdis correct
Error Codes
| Error | Cause |
|---|---|
token_invalid_or_expired |
Token expired or already used |
website_id_mismatch |
Token and websiteId don't match |
captcha_not_enabled |
Captcha is not enabled |
host_mismatch |
Request Origin doesn't match registered domain |