Integration guide
Two steps: embed the widget, then verify the token on your
server. Replace YOUR_SITE_KEY / YOUR_SECRET_KEY with
the keys from your site.
1. Add the widget to your page
Drop this into your HTML form. On success the widget injects a
hidden nc-response field — a plain form submit just works, no
custom JavaScript required.
<div data-nordcaptcha data-site-key="YOUR_SITE_KEY"></div> <script src="https://cdn.nordcaptcha.com/v1/nc.js" async defer></script>Copy ↗
2. Verify the token on your server
When the form is submitted, exchange the
nc-response token for a verdict using your secret key.
The token is single-use and carries no personal data.
curl -X POST https://api.nordcaptcha.com/v1/verify \
-H "content-type: application/json" \
-d '{"secret": "YOUR_SECRET_KEY", "token": "$NC_TOKEN"}'
Copy ↗
import requests
r = requests.post("https://api.nordcaptcha.com/v1/verify", json={
"secret": "YOUR_SECRET_KEY",
"token": request.POST["nc-response"],
}).json()
if r.get("success"):
... # proceed
Copy ↗
const res = await fetch("https://api.nordcaptcha.com/v1/verify", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ secret: "YOUR_SECRET_KEY", token: req.body["nc-response"] }),
});
const data = await res.json();
if (data.success) {
// proceed
}
Copy ↗
<?php
$ch = curl_init("https://api.nordcaptcha.com/v1/verify");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["content-type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["secret" => "YOUR_SECRET_KEY", "token" => $_POST["nc-response"]]),
]);
$data = json_decode(curl_exec($ch), true);
if (!empty($data["success"])) {
// proceed
}
Copy ↗
body, _ := json.Marshal(map[string]string{
"secret": "YOUR_SECRET_KEY",
"token": r.FormValue("nc-response"),
})
resp, _ := http.Post("https://api.nordcaptcha.com/v1/verify",
"application/json", bytes.NewReader(body))
var data struct{ Success bool `json:"success"` }
json.NewDecoder(resp.Body).Decode(&data)
if data.Success {
// proceed
}
Copy ↗
require "net/http"
require "json"
res = Net::HTTP.post(URI("https://api.nordcaptcha.com/v1/verify"),
{ secret: "YOUR_SECRET_KEY", token: params["nc-response"] }.to_json,
"content-type" => "application/json")
if JSON.parse(res.body)["success"]
# proceed
end
Copy ↗
Response & errors
A success returns
{ "success": true, "ts": ..., "hostname": "..." }. Compare
hostname against your expected host. On failure you get an HTTP 400
with { "detail": { "code": ..., "message": ... } }:
| Error | Meaning | What to do |
|---|---|---|
| invalid_site_key | Secret key wrong, or token not issued for this site. | Check you're sending this site's secret key. |
| token_expired | Token is older than its short lifetime. | Reject; have the visitor solve again (widget.reset()). |
| token_already_used | Token was already verified once (single-use). | Reject; never verify the same token twice. |