Skip to content
FitMyKB

FitMyKB Verify

Add a CAPTCHA to a Node.js and Express app

A small human() function checks the token with siteverify using Node's built-in fetch, before your route creates the account.

Keys

Put the secret in FMK_SECRET (an .env file or your host's settings). Only the site key goes in your HTML.

The server

human() posts the token to siteverify with a five-second timeout. The route refuses the request until it passes. If our server can't be reached the code lets people in; return false instead if you prefer to block.

JavaScript · server.js
// server.js (npm install express). Node 18+ has fetch built in.
import express from "express";

const app = express();
app.use(express.urlencoded({ extended: false }));
app.use(express.json());

async function human(token) {
  try {
    const reply = await fetch("https://captcha.fitmykb.com/siteverify", {
      method: "POST",
      body: new URLSearchParams({ secret: process.env.FMK_SECRET, response: token ?? "" }),
      signal: AbortSignal.timeout(5000),
    }).then((r) => r.json());
    return reply.success === true;
  } catch {
    return true; // FitMyKB unreachable: let people in (or return false to block)
  }
}

app.post("/signup", async (req, res) => {
  if (!(await human(req.body["fmk-captcha-response"]))) {
    return res.status(400).send("Please tick the box to show you are human.");
  }
  // Create the account here.
  res.redirect("/welcome");
});

app.listen(3000);

The form

Load api.js and place the box inside the form. A normal form post sends fmk-captcha-response with the other fields.

HTML · the form
<form method="post" action="/signup">
  <input name="email" type="email" required>
  <input name="password" type="password" required>
  <div class="fmk-captcha" data-sitekey="YOUR_SITE_KEY"></div>
  <button>Create account</button>
</form>
<script src="https://captcha.fitmykb.com/api.js" async defer></script>

JSON APIs and SPAs

Send the token in the JSON body under the same name; express.json() is already set up for it. Fastify, Koa and Next.js API routes read it from the body the same way.

Score

The reply also has a score from 0 to 1. Use it to ask borderline sign-ups to confirm their e-mail first instead of refusing them.

Get free keys · Full developer docs

Questions

Good questions

Anything else? Read the docs or ask us.

Does it work with TypeScript?

Yes: the same code, with token typed as string.