---
title: "Academy Article"
canonical_url: "https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam"
locale: en
meta:
  "og:title": "Academy Article"
---

[Go to home](https://academy.laioutr.com/en)

- [Hosting and operations](https://academy.laioutr.com/en/bereiche/hosting-and-operations)

- [Laioutr Cloud](https://academy.laioutr.com/en/leitfaeden/laioutr-cloud)

- [Protect forms from bots and spam](https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam)

# Protect forms from bots and spam

Bot protection checks selected storefront actions such as a newsletter sign-up or a login before they run. A bot protection app is installed for this and the actions to protect are listed in the project configuration.

## Before you start

<dl>

<dt>Plan</dt>
<dd>Any plan</dd>

<dt>Role</dt>
<dd>Developer with access to the project configuration</dd>

<dt>Duration</dt>
<dd>7 min</dd></dl>

### Prerequisites

- Access to the project's laioutrrc.json
- For Cloudflare Turnstile: a Cloudflare account with a Turnstile widget

Last reviewed on October 15, 2026

Open forms attract spam quickly: newsletter sign-ups with addresses nobody owns, or scripts trying passwords against the login. **Bot protection** lets the server refuse such requests while real visitors notice nothing.

Laioutr provides the mechanism, and an installed **provider app** answers whether a person sent the request. The options are the **Cloudflare Turnstile** app for any hosting, **Vercel BotID** for storefronts on Vercel, or a custom provider. A project uses exactly one.

Only actions listed in the project configuration are checked. The check runs before the request body is read, so a rejected bot causes no call to the commerce backend. With `whenUnavailable`, the project decides what happens when the provider is down: `open` lets the action run and logs a warning, `closed` refuses it.

Protect actions that visitors trigger, such as form submits or clicks. Actions that a page needs in order to render are not suitable.

## Step by step

1. 1 ### Step 1: Choose the provider app Choose Cloudflare Turnstile for any hosting or Vercel BotID for storefronts on Vercel.
2. 2 ### Step 2: Create the Turnstile widget For Turnstile, create a widget in **Managed** mode in the Cloudflare dashboard and add every storefront hostname, including previews.
3. 3 ### Step 3: Add the app Add the app with its site key and secret key to the project's apps in `laioutrrc.json`.
4. 4 ### Step 4: List the actions Add the actions under `config.botProtection.actions`, for example `newsletter/subscribe` and `ecommerce/auth/login`. Copy the identifiers from the API reference, because a typo protects nothing.
5. 5 ### Step 5: Set the outage behaviour Keep `whenUnavailable` at `open`, or set it to `closed` for especially critical actions.
6. 6 ### Step 6: Show a message and deploy Handle rejected requests in the form with a clear message and deploy the storefront.

## Check the result

A normal form submit works without any visible check. In a test environment with the Turnstile test key that always fails, the request is rejected and the error message appears.

## Frequently asked questions

Do real visitors notice anything?

Usually not. Turnstile loads only on the first protected action and shows a challenge only when Cloudflare asks for confirmation.

What happens when the provider is down?

With `open`, the action runs and the server logs a warning; with `closed`, it answers 503. A missing or invalid proof is refused in both cases.

Does Turnstile need consent?

The app adds no consent integration. Whether consent is needed is up to the storefront operator, based on Cloudflare's own information.

Why does a protected action fail while the page renders?

Only a browser can produce a proof. A protected action during server-side rendering is therefore always refused.

## Related

- [Find, install and configure apps](https://academy.laioutr.com/en/artikel/find-install-and-configure-apps)6 min

  Apps are listed in the Cockpit catalogue under Apps, installed per environment and set up under Configuration. The storefront uses them from the next deployment onwards.
- [Tracking and consent built into the components](https://academy.laioutr.com/en/artikel/tracking-and-consent-built-into-the-components)6 min

  Laioutr components send events such as page view, product view, add to cart and purchase through one analytics layer. Each event only reaches the destinations the visitor has consented to.
- [Start and check a deployment](https://academy.laioutr.com/en/artikel/start-and-check-a-deployment)5 min

  A deployment rebuilds the storefront of an environment and puts changes to apps, versions and configuration live. It is started in Cockpit under Deployments with Deploy; the status and build log show whether it worked.
- [Sending email with the Mailer essentials app](https://academy.laioutr.com/en/apps/sending-email-mailer-essentials)10 min

  The Mailer essentials app sends the transactional email of a Laioutr project, such as contact requests, order confirmations or the confirmation of receipt from the Legal app. Mail goes out through an SMTP account or services such as SendGrid, Amazon SES or Mailgun.

## [Laioutr Cloud](https://academy.laioutr.com/en/leitfaeden/laioutr-cloud)

Search this guide

1. [Hosting and edge delivery](https://academy.laioutr.com/en/artikel/hosting-and-edge-delivery)4 min
2. [Connect a custom domain](https://academy.laioutr.com/en/artikel/connect-a-custom-domain)6 min
3. [Password-protect the storefront until launch](https://academy.laioutr.com/en/artikel/password-protect-the-storefront-until-launch)5 min
4. [Deliver images through the Laioutr CDN](https://academy.laioutr.com/en/artikel/deliver-images-through-the-laioutr-cdn)4 min
5. [Deliver videos through the Video CDN](https://academy.laioutr.com/en/artikel/deliver-videos-through-the-video-cdn)6 min
6. [Protect forms from bots and spam](https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam)7 min
7. [Deliver the storefront as a progressive web app](https://academy.laioutr.com/en/artikel/deliver-the-storefront-as-a-progressive-web-app)5 min

## Structured Data

```json
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@id": "https://academy.laioutr.com/#website",
      "@type": "WebSite",
      "inLanguage": "en",
      "name": "Default",
      "url": "https://academy.laioutr.com/",
      "translationOfWork": {
        "@id": "https://academy.laioutr.com/#website"
      }
    },
    {
      "@id": "https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam#webpage",
      "name": "Academy Article",
      "url": "https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam",
      "@type": [
        "WebPage",
        "FAQPage"
      ],
      "breadcrumb": {
        "@id": "https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam#breadcrumb"
      },
      "isPartOf": {
        "@id": "https://academy.laioutr.com/#website"
      },
      "mainEntity": [
        {
          "@id": "https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam#/schema/question/1"
        },
        {
          "@id": "https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam#/schema/question/2"
        },
        {
          "@id": "https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam#/schema/question/3"
        },
        {
          "@id": "https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam#/schema/question/4"
        }
      ],
      "potentialAction": [
        {
          "@type": "ReadAction",
          "target": [
            "https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam"
          ]
        }
      ]
    },
    {
      "@id": "https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam#breadcrumb",
      "@type": "BreadcrumbList",
      "itemListElement": [
        {
          "@type": "ListItem",
          "name": "Home",
          "item": "https://academy.laioutr.com/en",
          "position": 1
        },
        {
          "@type": "ListItem",
          "name": "Hosting and operations",
          "item": "https://academy.laioutr.com/en/bereiche/hosting-and-operations",
          "position": 2
        },
        {
          "@type": "ListItem",
          "name": "Laioutr Cloud",
          "item": "https://academy.laioutr.com/en/leitfaeden/laioutr-cloud",
          "position": 3
        },
        {
          "@type": "ListItem",
          "name": "Protect forms from bots and spam",
          "item": "https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam",
          "position": 4
        }
      ]
    },
    {
      "@id": "https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam#/schema/question/1",
      "@type": "Question",
      "inLanguage": "en",
      "name": "Do real visitors notice anything?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "<p>Usually not. Turnstile loads only on the first protected action and shows a challenge only when Cloudflare asks for confirmation.</p>"
      }
    },
    {
      "@id": "https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam#/schema/question/2",
      "@type": "Question",
      "inLanguage": "en",
      "name": "What happens when the provider is down?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "<p>With <code>open</code>, the action runs and the server logs a warning; with <code>closed</code>, it answers 503. A missing or invalid proof is refused in both cases.</p>"
      }
    },
    {
      "@id": "https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam#/schema/question/3",
      "@type": "Question",
      "inLanguage": "en",
      "name": "Does Turnstile need consent?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "<p>The app adds no consent integration. Whether consent is needed is up to the storefront operator, based on Cloudflare's own information.</p>"
      }
    },
    {
      "@id": "https://academy.laioutr.com/en/artikel/protect-forms-from-bots-and-spam#/schema/question/4",
      "@type": "Question",
      "inLanguage": "en",
      "name": "Why does a protected action fail while the page renders?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "<p>Only a browser can produce a proof. A protected action during server-side rendering is therefore always refused.</p>"
      }
    }
  ]
}
```
