Skip to content
Antisy
Documentation · Step-by-step guide

Step-by-step guide: setting up bot protection on a form

Setting up bot protection, from creating the site to a protected form, in order. Each step says what to do and what you should see; the detail is on the page that holds it, and if in doubt, that page prevails.

What this guide covers

It follows the simple call to POST /v1/siteverify, which suits a low-stakes form (contact, newsletter) and every language. It does not tie the token to an account: a login or a sign-up needs the Node SDK, which is not published yet and which this guide therefore does not describe. The pilot page says what is handed over to the earliest clients.

Before you start the setup

  • Your pages are served over HTTPS.
  • You can change the CSP policy of your pages, if they have one.
  • You have an account on the dashboard (in French), which is in French, created from your invitation: access is for now by waiting list.
  • You know each host name that carries a form: www.exemple.ch and exemple.ch are two names.

Step 1. Create the site and the keys

  1. Create your account from the invitation and confirm your e-mail address: until it is confirmed, the dashboard does not offer to add a site. Right after creating the account, turn on two-step verification, which is mandatory: have an authenticator app ready on your phone.
  2. Choose “Ajouter un site” (add a site): a name, then the host name of your pages.
  3. On creation, the dashboard shows only once a “Secret de signature (base64)” (signing secret) and a “Sel (base64)” (salt). They are for the Node SDK, which this path does not use; copy them into your secrets manager anyway before leaving the page: they will never be shown again.
  4. Open the “Clés” (keys) tab of the site. The “Identifiant public du site” (public site identifier, 32 characters) is the site key: it is the one the tag carries. Choose “Créer une clé” (create a key), with the environment “Production” and the use “Vérification serveur” (server-side verification). The key (64 characters) is shown only once.
  5. In the “Paramètres” (settings) tab, check the “Noms d’hôte” (host names): the list must contain each of the names of your pages (declared host names). Do it before step 2: as soon as the tag is in place, a page served under an undeclared name receives tokens that the verification refuses, collection on or off.

No prefix says what type a key is: note it down on creation, and count the characters before pasting a key into a page. At the end of the step, you have the site key and a verification secret. A site starts with “Collecte du navigateur” (browser collection) off: this is intended, see step 6. The detail is on the page on keys and test environments.

Step 2. Put the script on the page

  1. The tag, in the <head> of each page that carries a form. data-site takes the site key, never a secret of 64 characters (the tag).
  2. The CSP policy, if you have one: try it first as Content-Security-Policy-Report-Only; the violations reported name the directive to complete. A page that enforces Trusted Types adds the antisy policy to its directive (CSP policy).
  3. The form: nothing to write. A POST form sent to your own site is covered as it is. On submission, the script holds the submission, fills in the hidden antisy-token field (it creates it if it does not exist) and resumes the submission, after 6 seconds at most: if Antisy does not answer, the form is sent anyway, without a token (the field is then missing, or empty if it already existed).
  4. The forms the script does not cover are sent without a token. A POST to another origin (a subdomain is one) or a GET is covered with the data-antisy attribute. A submission by fetch or by form.submit(), or to another window, needs antisy.token() from the page. The full list is in which forms are covered.
  5. A form you do not protect (a search sent by POST, a newsletter form present on every page) is marked data-antisy="off" (leave a form out).
  6. If your page already called antisy.token() for a POST form sent to your site, remove the call, or set data-antisy="off" if you keep control: otherwise the page makes a second deposit and the first submission is slower (antisy.token()).

What to look for

In the network console of the browser, a request from the script to api.antisy.com, then, in the POST request sent to your server, the antisy-token field filled in, with a value that starts with ar1.. If it is empty or missing: if the script does not run.

Step 3. Verify the token server side

  1. The “Vérification serveur” secret from step 1 goes in an environment variable of your server, and leaves it only in the body of the request, nowhere else (the request).
  2. Copy the example for your language: curl and Node in the quick start, PHP, Python and Go on the page verify a token. Each applies the same rules: check the token before the call, accept only on success at true, wait 3 seconds at most, follow no redirect.
  3. Do not send remoteip: it is ignored.
  4. Make a single call per token: a token is valid for 60 seconds and can be verified only once. To be able to replay a call that may have succeeded without your having read the response, generate an idempotency_key (a UUID) on your server before the first call, and send it from that first call; then send the same request again, with the same key, within 60 seconds. A key added only to the second call recovers nothing: if the first one succeeded, the token is already used, and the response is a refusal (timeout-or-duplicate). The examples cited above send no key; never take it from the visitor’s request (validity period and single use).

Step 4. Choose what to do in an outage

What your server does when Antisy does not answer is your choice, route by route. The examples apply the rule of the page when the API does not answer.

Outage, deadline exceeded, 5xx response

The examples let the submission through and log it: an outage at Antisy must not cost you your visitors.

429, or a 503 that carries Retry-After

The examples let it through by default. But an attacker can cause these responses by volume, and that is when their submissions get through with yours. For a sensitive form, refuse: for the 429, put deny in the constant of the example; for the 503 that carries Retry-After, which the examples treat like any 5xx response, add this case before the one of the 5xx, with the same value (verify a token). It is the protective choice, at the cost of refusing a few legitimate visitors during a saturation.

400, 401, 413, 415 and any other 4xx

Never let it through: it is a fault of your call. Log it as a bug to fix, and refuse the submission, which has not been verified.

Step 5. Test with a test key

  • In “Clés”, create a key with the environment “Test (non comptée dans les statistiques)” (test, not counted in the statistics) and the use “Vérification serveur”. A site carries at most 2; those of your whole organisation share 1,000 calls a day and, to date, 2,500 a month.
  • The two dummy site keys “allow” and “deny” give a verdict known in advance. In a development page, put one of them in data-site in place of the public site identifier: the script returns a fixed token, which your server verifies with the test secret, with no host name to declare. Without a real browser (continuous integration), the recipe on the page test keys gives the same token.

A test key never goes into production

Its token is public: a bot gets through with it. The dashboard marks each test key “Test”, but the string of the key does not say so. Keep your test secrets in environment variables that say so, separate from those of production (the safeguard).

Step 6. Go into production

  1. Put on your server the “Production” secret created in step 1 in place of the test secret. To change a secret without an interruption, follow create, copy, revoke.
  2. Read again, line by line, the list “Before turning collection on” on the page if the script does not run.
  3. Turn on “Collecte du navigateur” (“Paramètres” tab). The dashboard asks you to tick each check before “Allumer la collecte” (turn collection on). Once it is on, a missing token no longer gets through, whatever the verification mode: a form that the script does not cover and whose page has not called antisy.token() is refused, and a blocked script refuses every visitor, humans included. During the pilot, turning it on is decided with Antisy; if the dashboard shows “Tenue par Antisy” (held by Antisy), it does not offer to turn it on: write to support.
  4. Make one submission by hand through each protected form, from your page: each must be accepted. The verdict can be read in the “Événements” (events) tab. If one is refused, see step 8.
  5. If real visitors are refused, check the declared host names first (step 1). While collection is on, the button “Éteindre la collecte” (turn collection off) acts in one click, at any time, and changes nothing else: it only rescues the submissions without a token. A refusal with a token present (undeclared host name, a device too slow to finish the computation) does not depend on it. Then write to support.

The verification mode of the site (“Strict” (Strict), “Équilibré” (Balanced), “Permissif” (Permissive)) is also set in “Paramètres”: it only changes the point at which a doubtful visitor does not get through (how strictly to refuse). The verdict remains allow or deny, and what never gets through, whatever the mode, is on the page what never gets through.

Step 7. Read the dashboard

A site has four tabs: “Aperçu” (overview), “Événements” (events), “Clés” (keys) and “Paramètres” (settings).

Aperçu (overview)
The volume of verifications over the period, the volumes that “Passent” (get through) and that “Ne passent pas” (do not get through), and “Refus par catégorie” (refusals by category).
Refus par catégorie (refusals by category)

Two categories only: “Jeton absent ou invalide” (token missing or invalid) and “Autres refus” (other refusals). The totals are rounded to the nearest ten (the table says “environ”, about), not published under 20 (“moins de 20”, fewer than 20), and published 48 hours after the end of the day: a day not yet published shows “Publié 48 h après la fin du jour” (published 48 h after the end of the day), nothing is broken.

The two columns do not add up exactly and say nothing about any one verification.

Événements (events)
The recent verifications, with the verdict, the timestamp, the type of event and the family of the browser. To find a precise attempt again, keep in your logs the event_id of the response of the verification: support will need it.

Step 8. A real visitor is refused

Antisy gives no reason for a refusal, neither in the response nor in the dashboard. You proceed by elimination, from the most frequent to the rarest.

  1. Did the token leave? In the network console, is the antisy-token field (or the x-antisy-token header) filled in in the request sent to your server? If not: if the script does not run (CSP policy, ad blocker, page served over HTTP, form not covered).
  2. Is the host name of the page declared? From a name missing from the list (a forgotten www., or the bare domain), the antisy-token field leaves filled in, looking like a real token, and the verification refuses it, collection on or off (declared host names).
  3. Does your server read the right field, with the right secret? The field is called antisy-token and is passed on as it arrived, without truncating it. A missing or refused secret (missing-input-secret, invalid-input-secret) makes every visitor refused: log these codes (error codes).
  4. Did the visitor leave the page open for a long time, or send twice? An expired or already verified token returns timeout-or-duplicate. Your refusal message should say “try again”: a new attempt obtains a fresh token.
  5. Is the device very slow? A device that does not finish the background computation in time is refused as for an invalid token; a new attempt draws a new computation (if the script does not run).
  6. Your allow list does not exempt from the token: an invalid, replayed or expired token is refused even for an allowed identifier, and so is a missing token when collection is on.
  7. The “Permissif” (Permissive) mode of “Paramètres” refuses less; go back to “Équilibré” (Balanced) if bots get through.
  8. If the problem persists, write to support, below.

Who to contact

Write to support@antisy.com. Include:

  • the approximate date and time, with the time zone;
  • the host name of the page;
  • the event_id of the response of the verification: it is with it that Antisy finds an attempt again;
  • what you have already checked among the steps above.

Never send a key, a secret or a visitor’s personal data (e-mail address, password): Antisy does not need them.

Support also does, at your written request, what the dashboard does not: replace a signing secret, lost or to be changed, and set or remove an allow list or a block list for your site.

Ready to open: the setup checklist

  • Site created, host names declared, secrets copied (step 1).
  • Tag and CSP policy in place; each form is covered, marked data-antisy, handled by antisy.token() or left out with data-antisy="off" (step 2).
  • Server-side verification in place, with the secret in the body of the request (step 3).
  • What to do in an outage chosen, route by route (step 4).
  • Trial made with a test key, which is no longer on the production server (steps 5 and 6).
  • Collection on, one submission by hand through each protected form accepted (step 6).
  • The support address is known to your teams (step 8).