Skip to main content
Before you start:
  • Import t.js from https://cdn.usefoil.com.
  • Use a publishable key (pk_*) in the browser and a secret key (sk_*) on your backend.
  • Keep the secret key server-side only.
  • The browser never receives Foil verdicts, scores, or visitor IDs.

1. Install the server SDK

npm install @abxy/foil-server

2. Load the browser client

Start the client as early as possible on your page. Keep the returned promise for later use.
<script type="module">
  const foilPromise = import("https://cdn.usefoil.com/t.js")
    .then((Foil) =>
      Foil.start({
        publishableKey: "pk_live_your_publishable_key",
      }),
    );

  async function setupFoil() {
    const foil = await foilPromise;
    foil.onError((error) => {
      console.error("Foil error", error.code, error.message);
    });

    // Optional: resolve early if you want fingerprinting ready before the action
    void foil.waitForFingerprint().catch(console.error);
  }

  setupFoil().catch(console.error);
</script>

3. Get a session at action time

Right before signup, login, checkout, or another sensitive action, request a sealed handoff and send it to your backend.
<script type="module">
  const foil = await foilPromise;

  async function submitSignup(formData) {
    const { sessionId, sealedToken } = await foil.getSession();

    const response = await fetch("/api/signup", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        ...formData,
        foil: { sessionId, sealedToken },
      }),
    });

    return response.json();
  }
</script>

4. Verify on your backend

Verify the sealed token with your secret key. This is a local operation — no network call to Foil.
const { safeVerifyFoilToken } = require("@abxy/foil-server");

app.post("/api/signup", async (req, res) => {
  const result = safeVerifyFoilToken(
    req.body.foil.sealedToken,
    process.env.FOIL_SECRET_KEY,
  );

  if (!result.ok || result.data.decision.verdict === "bot") {
    return res.status(403).json({ error: "Blocked" });
  }

  // Proceed with signup
  createAccount(req.body);
  res.json({ success: true });
});

5. Apply policy

Use the verdict to decide what to do:
VerdictAction
humanAllow the request
inconclusiveChallenge (CAPTCHA, email verification)
botBlock or rate-limit
Start in report-only mode (log verdicts without blocking) to understand your traffic before enforcing.

What’s next

Browser SDK

Full SDK API reference

Server verification

Advanced verification patterns

Testing

Test your integration with bot traffic

Going to production

Rollout checklist and monitoring