Skip to content

Invisible CAPTCHA (Beta)

Invisible CAPTCHA provides seamless bot protection without interrupting the user experience. The CAPTCHA challenge runs in the background and only presents a visible challenge if additional verification is needed.

Invisible CAPTCHA works by:

  1. Running verification challenges in the background
  2. Analyzing user behavior and browser characteristics
  3. Only showing a visible challenge if the user appears suspicious
  4. Providing a smooth experience for legitimate users

The most intelligent option that dynamically adapts based on user behavior:

<button
class="procaptcha"
data-sitekey="your_site_key"
data-captcha-type="frictionless"
data-size="invisible"
data-callback="onCaptchaSuccess">
Submit
</button>

Runs a computational challenge invisibly in the background:

<button
class="procaptcha"
data-sitekey="your_site_key"
data-captcha-type="pow"
data-size="invisible"
data-callback="onCaptchaSuccess">
Submit
</button>

Shows visible challenges to verify the user on form submission:

<button
class="procaptcha"
data-sitekey="your_site_key"
data-captcha-type="image"
data-size="invisible"
data-callback="onCaptchaSuccess">
Submit
</button>

Add the procaptcha class and data attributes directly to your form elements:

<!DOCTYPE html>
<html>
<head>
<script src="https://js.prosopo.io/js/procaptcha.bundle.js" async defer></script>
</head>
<body>
<form>
<input type="email" name="email" required>
<button
type="button"
class="procaptcha"
data-sitekey="your_site_key"
data-captcha-type="frictionless"
data-size="invisible"
data-callback="handleSubmit"
data-failed-callback="handleFailure">
Submit Form
</button>
</form>
<script>
function handleSubmit(token) {
console.log('CAPTCHA verified:', token);
// Submit your form with the token
}
function handleFailure() {
console.log('CAPTCHA verification failed');
// Handle failure case
}
</script>
</body>
</html>

For more control over the CAPTCHA lifecycle:

<!DOCTYPE html>
<html>
<head>
<script src="https://js.prosopo.io/js/procaptcha.bundle.js" async defer></script>
</head>
<body>
<form id="demo-form">
<input type="email" name="email" required>
<div id="captcha-container"></div>
<button type="submit">Submit Form</button>
</form>
<script type="module">
import { render, execute } from "https://js.prosopo.io/js/procaptcha.bundle.js"
let widgetId;
function handleCaptchaSuccess(token) {
console.log('CAPTCHA verified:', token);
// Process form submission with token
}
function handleCaptchaFailure() {
console.log('CAPTCHA verification failed');
// Handle failure
}
document.addEventListener('DOMContentLoaded', function() {
// Render invisible CAPTCHA
widgetId = render(document.getElementById('captcha-container'), {
siteKey: 'your_site_key',
captchaType: 'frictionless',
size: 'invisible',
callback: handleCaptchaSuccess,
'failed-callback': handleCaptchaFailure
});
// Handle form submission
document.getElementById('demo-form').addEventListener('submit', function(e) {
e.preventDefault();
// Trigger CAPTCHA verification
execute();
});
});
</script>
</body>
</html>
AttributeValueDescription
data-size"invisible"Required. Enables invisible mode
data-captcha-type"frictionless", "pow", "image"Type of CAPTCHA challenge
data-callbackFunction nameCalled when CAPTCHA is successfully verified
data-failed-callbackFunction nameCalled when CAPTCHA verification fails
data-sitekeyYour site keyRequired. Your Procaptcha site key
  • Frictionless: Best for most use cases, adapts automatically
  • PoW: Good for forms where you want consistent invisible challenges
  • Image: Use when you need image-based verification with invisible fallback

Always implement a failed callback to handle verification failures:

function onCaptchaFailed() {
// Show user-friendly error message
alert('Verification failed. Please try again.');
// Reset form or provide alternative
}

Since verification happens in the background, consider showing loading states:

function onCaptchaStart() {
document.getElementById('submit-btn').disabled = true;
document.getElementById('submit-btn').textContent = 'Verifying...';
}
function onCaptchaComplete(token) {
document.getElementById('submit-btn').disabled = false;
document.getElementById('submit-btn').textContent = 'Submit';
// Process with token
}

Always verify the Procaptcha response on your server:

// Node.js example
const response = await fetch('https://api.prosopo.io/siteverify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
secret: 'your_secret_key',
response: token, // Token from Procaptcha callback
remoteip: userIP // Optional
})
});
const result = await response.json();
if (result.success) {
// Procaptcha verified successfully
console.log('Verification successful');
} else {
// Verification failed
console.log('Verification failed:', result['error-codes']);
}
  • Ensure data-size="invisible" is set
  • Check that your site key is correct and active
  • Verify your domain is registered in the portal
  • Confirm you’re on Pro or Enterprise tier

This is normal behavior when:

  • User behavior appears suspicious
  • Browser characteristics suggest automation
  • Additional verification is needed for security
  • Make sure the Procaptcha script loads before your code runs
  • Check browser console for error messages
  • Verify callback functions are defined globally
  • Test with different CAPTCHA types to isolate issues

Migration from Visible CAPTCHA

Section titled Migration from Visible CAPTCHA

To convert existing visible CAPTCHA implementations:

  1. Add data-size="invisible" to existing configurations
  2. Update UI to remove CAPTCHA container (for implicit rendering)
  3. Adjust form styling since no visible widget will appear
  4. Test user flows to ensure smooth experience
  5. Update any size-dependent CSS or JavaScript