Getting Started

From zero to production with NeoCaptcha in under 15 minutes.

Updated 2/22/2026

Getting Started with NeoCaptcha

This guide takes you from a fresh account to a verified, production-ready captcha flow.

What you are building

By the end of this guide you will have:

  1. A NeoCaptcha widget rendered on your form.
  2. A secure backend verification route.
  3. A submission flow that rejects invalid or replayed tokens.

Prerequisites

  • A NeoCaptcha account at neocaptcha.com.
  • A website or app where users submit a form (signup, login, contact, checkout, etc.).
  • Backend runtime capable of making HTTPS requests (Node.js, Python, Go, Java, .NET, etc.).

Step 1: Create a site in the dashboard

In the NeoCaptcha dashboard:

  1. Create a Site.
  2. Add allowed domains:
    • Local: localhost and 127.0.0.1
    • Production: your exact hostnames (for example app.example.com)
  3. Save and copy:
    • Site Key (public; safe for frontend)
    • Site Secret (private; backend only)

Keep your Site Secret out of frontend code, public repos, and browser-accessible env vars.


Step 2: Add the captcha to your page

Choose one of two integration approaches.

Option A — CDN (no build step)

Add the script tag once per page, then add a container element with your site key. The script auto-discovers the element and mounts the widget inside it.

<script src="https://cdn.neocaptcha.com/v1/browser.js" defer></script>
 
<div id="neocaptcha" sitekey="YOUR_SITE_KEY"></div>

Listen for DOM events on the container:

const captcha = document.getElementById('neocaptcha');
let captchaToken = null;
 
captcha.addEventListener('neocaptcha:complete', (e) => {
  captchaToken = e.detail.verifyToken;
  document.getElementById('submit-btn').disabled = false;
});
 
captcha.addEventListener('neocaptcha:error', () => {
  captchaToken = null;
  document.getElementById('submit-btn').disabled = true;
});
 
captcha.addEventListener('neocaptcha:expire', () => {
  captchaToken = null;
  document.getElementById('submit-btn').disabled = true;
});

Option B — npm package (init)

Install the package:

npm install @neocaptcha/sdk

Call init with a container element and your site key:

import { init } from '@neocaptcha/sdk';
 
let captchaToken: string | null = null;
 
init({
  container: document.getElementById('captcha-slot')!,
  siteKey: process.env.NEOCAPTCHA_SITE_KEY!,
  onComplete: (verifyToken) => {
    captchaToken = verifyToken;
    document.getElementById('submit-btn')!.removeAttribute('disabled');
  },
  onError: () => {
    captchaToken = null;
  },
  onExpire: () => {
    captchaToken = null;
  },
});

Step 3: Send token with your form

When the user submits your form, include the verifyToken in your request body.

await fetch('/api/signup', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    email,
    password,
    captchaToken,
  }),
});

Step 4: Verify on your server (required)

Your server must call the NeoCaptcha verify endpoint before processing sensitive actions.

const verifyRes = await fetch('https://neocaptcha.com/api/v1/verify', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    solution: req.body.captchaToken,
    siteKey: process.env.NEOCAPTCHA_SITE_KEY,
    secret: process.env.NEOCAPTCHA_SITE_SECRET,
    expectedOrigin: 'https://app.example.com',
  }),
});
 
const verification = await verifyRes.json();
if (!verification.valid) {
  return res.status(400).json({ error: 'Captcha verification failed' });
}

If verification succeeds, continue your business logic.

Frontend Examples

CDN

<!DOCTYPE html>
<html>
  <head>
    <title>NeoCaptcha Example</title>
    <script src="https://cdn.neocaptcha.com/v1/browser.js" defer></script>
  </head>
  <body>
    <form id="contact-form">
      <label for="email">Email:</label>
      <input type="email" id="email" name="email" required />
 
      <label for="message">Message:</label>
      <textarea id="message" name="message" required></textarea>
 
      <div id="neocaptcha" sitekey="YOUR_SITE_KEY"></div>
 
      <button type="submit" id="submit-btn" disabled>Submit</button>
    </form>
 
    <script>
      let captchaToken = null;
      const captcha = document.getElementById('neocaptcha');
 
      captcha.addEventListener('neocaptcha:complete', (e) => {
        captchaToken = e.detail.verifyToken;
        document.getElementById('submit-btn').disabled = false;
      });
 
      captcha.addEventListener('neocaptcha:error', () => {
        captchaToken = null;
        document.getElementById('submit-btn').disabled = true;
      });
 
      captcha.addEventListener('neocaptcha:expire', () => {
        captchaToken = null;
        document.getElementById('submit-btn').disabled = true;
      });
 
      document.getElementById('contact-form').addEventListener('submit', (e) => {
        if (!captchaToken) {
          e.preventDefault();
          alert('Please complete the captcha first');
        }
      });
    </script>
  </body>
</html>

npm (init)

import { init } from '@neocaptcha/sdk';
 
let captchaToken: string | null = null;
 
init({
  container: document.getElementById('captcha-slot')!,
  siteKey: process.env.NEOCAPTCHA_SITE_KEY!,
  onComplete: (verifyToken) => {
    captchaToken = verifyToken;
  },
  onError: () => {
    captchaToken = null;
  },
  onExpire: () => {
    captchaToken = null;
  },
});
 
document.getElementById('contact-form')!.addEventListener('submit', async (e) => {
  e.preventDefault();
  if (!captchaToken) {
    alert('Please complete the captcha first');
    return;
  }
 
  const email = (document.getElementById('email') as HTMLInputElement).value;
  const message = (document.getElementById('message') as HTMLTextAreaElement).value;
 
  await fetch('/api/contact', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, message, captchaToken }),
  });
});

Production checklist

  • Domain allowlist configured for all production hostnames.
  • Site Secret only available in backend environment variables.
  • All sensitive POST routes verify captcha before action.
  • Replay prevention enabled (single-use token behavior).
  • Logs include challenge ID/token ID for incident investigation.
  • Monitoring alerts on spikes in invalid captcha attempts.

Next steps

  • Read Server Verification for backend architecture and anti-abuse patterns.
  • Read Browser for full CDN and init option reference.
  • Read React for SPA/Next.js integration patterns.