Skip to main content
Before you turn enforcement on in production, confirm two things: your integration fires on bot traffic and it doesn’t fire on real users. This page walks through the patterns we recommend.

Test vs live keys

Foil issues separate test and live key pairs.
  • Test keys are prefixed pk_test_* / sk_test_*; live keys are pk_live_* / sk_live_*.
  • Sessions created with test keys are tagged in the dashboard so you can filter integration traffic out of real metrics.
  • Test and live keys are not interchangeable. A sealed token issued under a test publishable key cannot be verified with a live secret key - verification fails locally with a FoilTokenVerificationError. Keep the environments fully separate.
  • Everything else - verdicts, scoring, phases, fingerprinting - behaves identically across environments.

What verdicts to expect

An unmodified automation runner should land on bot every time. Stealth variants still land on bot but with lower confidence, and real user traffic should land on human. If you’re seeing consistently different verdicts than these, something is off in the integration - usually the sealed token isn’t reaching the verifier, or getSession() is being called against a different Foil.start() instance than the one your page initialized.

Runnable Playwright example

This asserts end-to-end that a bot gets blocked at signup:
Run it with npx playwright test against your local dev server. If the assertion passes, your block path is wired correctly. Flip it to expect(response.status()).toBe(200) and run against your staging build to verify the allow path for manually-driven sessions. For Puppeteer, Selenium, or WebDriverIO, the pattern is the same - launch, navigate, submit, assert the response. Foil detects them all.

Forcing an inconclusive verdict

inconclusive is Foil saying “not enough signal either way.” The easiest way to produce one on purpose is to call getSession() immediately on page load, before any user interaction:
Use this to test whatever challenge flow you serve on ambiguous sessions - CAPTCHA, email verification, step-up auth. If your integration treats inconclusive identically to human, you’re leaving coverage on the table; see Verdicts & scoring for the recommended policy split.

Debugging common issues

What’s next