Static Forms - Secure form backend and form endpoint for contact formsStatic Forms - Secure form backend and form endpoint for contact forms
  • Home
  • Features
  • Docs
  • Blog
  • Pricing
Register
  • Home
  • Features
  • Docs
  • Blog
  • Pricing
Back to all posts

Implementing Altcha CAPTCHA in Next.js

August 25, 2025
3 min read
Static Forms Team
altchanextjscaptchaprivacy
Share:

Adding CAPTCHA protection to your Next.js forms doesn't have to be complicated. Altcha provides a privacy-focused solution that's easy to implement and doesn't track your users. Let's add it to a simple contact form.

What You Need

Before starting, make sure you have:

  1. Next.js application
  2. Paid plan - Altcha needs a Static Forms paid plan (Pro or Advanced)
  3. API key - From your Static Forms account

Step 1: Install Altcha

Bash
npm install altcha

Step 2: Add Your API Key

Create a .env.local file:

ENV
NEXT_PUBLIC_STATIC_FORMS_API_KEY=your_api_key_here

Step 3: Create a Simple Contact Form

Here's a basic contact form with Altcha verification:

TSX
'use client';

import { useState, useEffect } from 'react';

export default function ContactForm() {
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [status, setStatus] = useState('');

  // Load ALTCHA package
  useEffect(() => {
    import('altcha');
  }, []);

  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    
    const form = e.currentTarget;
    setIsSubmitting(true);
    
    try {
      const formData = new FormData(form);
      formData.append('apiKey', process.env.NEXT_PUBLIC_STATIC_FORMS_API_KEY || '');
      
      const response = await fetch('https://api.staticforms.dev/submit', {
        method: 'POST',
        body: formData,
      });
      
      if (response.ok) {
        setStatus('Message sent successfully!');
        form.reset();
        // Reset ALTCHA widget
        const altchaWidget = document.querySelector('altcha-widget') as any;
        if (altchaWidget?.reset) {
          altchaWidget.reset();
        }
      } else {
        setStatus('Failed to send message. Please try again.');
      }
    } catch (error) {
      setStatus('An error occurred. Please try again.');
    } finally {
      setIsSubmitting(false);
    }
  };
  
  return (
    <div className="max-w-md mx-auto p-6">
      {status && (
        <div className="mb-4 p-3 rounded bg-blue-50 text-blue-800">
          {status}
        </div>
      )}
    
      <form onSubmit={handleSubmit} className="space-y-4">
        <div>
          <label className="block mb-2 font-medium">Name</label>
          <input
            type="text"
            name="name"
            required
            className="w-full p-3 border rounded-md"
          />
        </div>
        
        <div>
          <label className="block mb-2 font-medium">Email</label>
          <input
            type="email"
            name="email"
            required
            className="w-full p-3 border rounded-md"
          />
        </div>
        
        <div>
          <label className="block mb-2 font-medium">Message</label>
          <textarea
            name="message"
            required
            rows={4}
            className="w-full p-3 border rounded-md"
          />
        </div>
        
        <div>
          <label className="block mb-2 font-medium">Verify you're human</label>
          <altcha-widget
            challengeurl={`https://www.staticforms.dev/api/altcha/challenge?apiKey=${process.env.NEXT_PUBLIC_STATIC_FORMS_API_KEY || ''}`}
            name="altchaToken"
          />
        </div>
        
        <button
          type="submit"
          disabled={isSubmitting}
          className="w-full py-3 bg-blue-600 text-white rounded-md disabled:bg-gray-400"
        >
          {isSubmitting ? 'Sending...' : 'Send Message'}
        </button>
      </form>
    </div>
  );
}

Step 4: Use the Component

Create a page to use your form:

TSX
// app/contact/page.tsx
import ContactForm from './ContactForm';

export default function ContactPage() {
  return (
    <div className="container mx-auto py-12">
      <h1 className="text-3xl font-bold text-center mb-8">Contact Us</h1>
      <ContactForm />
    </div>
  );
}

Step 5: Enable Altcha

  1. Go to your CAPTCHA settings
  2. Switch to "Altcha" tab
  3. Generate your keys
  4. Save settings

That's It!

Your form now has privacy-focused CAPTCHA protection. The widget automatically:

  • ✅ Loads and verifies challenges
  • ✅ Works without tracking users
  • ✅ Protects against spam
  • ✅ No puzzles for users to solve

Need Help?

  • Get a paid plan (Pro or Advanced) to use Altcha
  • Configure settings in your account
  • Read more guides

Related Articles

  • Implementing Altcha CAPTCHA on HTML Websites
  • Getting Started with Static Forms
  • Adding Contact Forms to Static Sites
Previous

Implementing Altcha CAPTCHA on HTML Websites

Next

Using StaticForms with Gatsby: Complete Integration Guide

Related Articles

Implementing Altcha CAPTCHA on HTML Websites

Learn how to implement Altcha CAPTCHA on your HTML website for privacy-first security. Complete guide with code examples.

Aug 21, 2025·4 min read

hCaptcha Best Practices

A practical guide to using hCaptcha, including setup decisions, common mistakes, and implementation planning tips.

Mar 13, 2026·4 min read

Cloudflare Turnstile Best Practices

A practical guide to using Cloudflare Turnstile, including rollout advice, common mistakes, and implementation planning tips.

Mar 11, 2026·4 min read
Static Forms - Secure form backend and form endpoint for contact formsStatic Forms - Secure form backend and form endpoint for contact forms

The fastest way to add working contact forms to any website. No backend required.

Product

  • Features
  • Pricing
  • Documentation
  • Changelog

Resources

  • Blog
  • Examples
  • Templates
  • Tools
  • Integrations
  • reCAPTCHA Guide
  • FAQ

Alternatives

  • All Alternatives
  • Formspree
  • Netlify Forms
  • Typeform
  • Formspark

Company

  • Contact
  • About

Legal

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • DPA

© 2026 Static Forms. All rights reserved.

Committed to sustainability