Crovly

Backend Verification

Always verify the captcha token server-side. Never trust the client alone.

Flow

  1. User completes captcha → widget sets hidden input crovly-token
  2. User submits form → your server receives the token
  3. Your server → POST api.crovly.com/verify-token
  4. Crovly returns success + score
  5. Your server decides: accept or reject

IP Binding

Pass expectedIp in the verify-token request. Crovly checks that the IP that solved the puzzle matches the IP making the request. This prevents token farming — a bot can't solve the captcha on one IP and use the token from another.

// Node.js / Express
app.post("/submit", async (req, res) => {
  const token = req.body["crovly-token"];
  const ip = req.headers["cf-connecting-ip"]
           || req.headers["x-real-ip"]
           || req.headers["x-forwarded-for"]?.split(",")[0]
           || req.ip;

  const result = await fetch("https://api.crovly.com/verify-token", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.CROVLY_SECRET_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ token, expectedIp: ip }),
  }).then(r => r.json());

  if (!result.success || result.score < 0.5) {
    return res.status(403).json({ error: "Captcha failed" });
  }

  // Process the form...
});

Score Thresholds

The score ranges from 0.0 (definitely bot) to 1.0 (definitely human).

ThresholdUse Case
0.3Lenient — allows most traffic, blocks obvious bots
0.5Default — good balance for most sites
0.7Strict — login forms, payment pages
0.9Very strict — high-value actions only

You can configure the default threshold per site in the dashboard.

On this page