Documentation
Next.js
Use the browser SDK in the client and redeem the proof token in an App Router route handler.
client component
"use client";
import { useEffect, useRef, useState } from "react";
import { createCaptcha } from "@captchacc/browser";
export default function ContactForm() {
const slotRef = useRef(null);
const [captcha, setCaptcha] = useState(null);
useEffect(() => {
if (!slotRef.current) return;
createCaptcha(slotRef.current, {
siteKey: "pk_live_xxx",
apiBase: "https://captcha.cc"
}).then(setCaptcha);
}, []);
async function onSubmit(event) {
event.preventDefault();
if (!captcha) return;
const form = new FormData(event.currentTarget);
const answer = String(form.get("captcha_answer") || "");
const result = await captcha.verify(answer);
if (!result.ok) return;
await fetch("/api/contact", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ proofToken: result.proofToken })
});
}
return (
);
}
route handler
export async function POST(request: Request) {
const body = await request.json();
const verifyResponse = await fetch("https://captcha.cc/v1/siteverify", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
secret_key: process.env.CAPTCHA_CC_SECRET_KEY,
proof_token: body.proofToken
})
});
const verify = await verifyResponse.json();
if (!verify.success) {
return Response.json({ error: "captcha verification failed", verify }, { status: 400 });
}
return Response.json({ ok: true });
}