Spam protection (captcha)
Turn on a human check before a form's final submit to stop bot submissions. Choose Automatic or Strict mode, see what respondents see, and learn how partial answers, webhooks, HubSpot and bookings beh
Spam protection adds a human check, powered by Cloudflare Turnstile, right before a form's final submit. It stops bots from filling your form and flooding your webhooks and HubSpot with junk contacts. It is off by default, and you turn it on form by form.
Step 1: Open the form in the editor, click Connect in the top bar and scroll to the last section, Spam protection (captcha).

Step 2: Turn on Check that respondents are human before the final submit. Two modes appear under the switch, and Automatic: only suspicious visitors see a check (recommended) is selected.

The section now reads Partial answers are still saved in Submissions, but they are not sent to webhooks or HubSpot while protection is on. The next sections explain both halves of that sentence.
Step 3: Pick the mode.

Automatic: only suspicious visitors see a check (recommended)
Nothing, in most cases. A checkbox appears only when Cloudflare finds the visit suspicious.
None.
Strict: everyone sees the verification before sending, plus extra checks
The verification, every time, before the answers are sent.
A hidden field that no person can reach, and a minimum fill time: a form completed less than 2 seconds after the respondent first opened it is refused.
The product's own advice for Strict is Use it if spam still gets through. It adds a visible step for everyone.
Step 4: Click Publish. The setting travels with your draft, like the tracking IDs, and the section says so: Staged with your draft: click Publish to apply it to the live form. Until you publish, the live form keeps its previous setting.
💡 Tip: The editor preview never shows the check. To see it, open the published form in a new tab.
Turning the switch off and back on resets the mode to Automatic.
What respondents see
The check sits right above the button that ends the form, so the page never changes for it:
One page
Right above Submit.
Slides
Right above the button of the last step, or of the last screen when several questions share a screen. See Several questions on one screen.
A finish without a button
On the submitting screen. This covers a single choice or dropdown that moves on by itself, and a reveal screen or a scheduler as the last step.
The check loads once the respondent starts answering and the button is on screen, and it works while they finish, so the answers usually go out without any wait. While the check finishes, the button reads Submitting…. It follows the form's language and its light or dark theme.

If something goes wrong, the answers stay filled in and the message appears next to the button:
We couldn’t verify that you’re human. Please try again.
The check did not pass. The form already retried once on its own before showing it.
We couldn’t complete the security check. Your answers are saved. Please try again.
The check could not run: Cloudflare could not be reached, or the check could not load in the browser. See When the check cannot run.
This form now checks that you’re human. Refresh the page and submit again.
The page was opened before you turned protection on.
On the submitting screen, a check that needs a click shows Confirm you’re human to send your answers., and a failed one offers Try again.
What changes for your integrations
While protection is on, one rule applies to every destination:
A partial submission is still saved and still appears in Submissions, but it is not sent to webhooks or to HubSpot.
A complete submission is verified first, then saved and delivered as usual.
Submission emails do not change: they were already sent for completed submissions only.
Your settings are left exactly as saved. A webhook keeps its Partial submissions box ticked, and turning protection off brings partial deliveries back. Until then, the dashboard marks what is paused:
Webhook card, Trigger on
Paused while spam protection is on, next to Partial submissions. A webhook that only listens to partials also warns This webhook will not fire: it only listens to partial answers, which are paused while spam protection is on.
HubSpot card, How the sync works
Spam protection is on: contacts are created or updated when a respondent completes the form, not from partial answers.
Integrations page, Webhooks table, Events
Complete (partials paused) or Partial submissions (paused).
Build tab, the info popover of the Partial submit point
With spam protection on, partial answers are saved but not sent to integrations.


⚠️ Note: The markers in the Connect tab follow the switch in your draft, so they appear as soon as you turn it on. Deliveries only change once you click Publish. The Webhooks table on the Integrations page always shows the published form.
Send test on the webhook card still posts its sample while partials are paused, so you can keep testing your endpoint.
Scheduler bookings
A booking made from a Scheduler step is also covered. With protection on, Booking sync writes to HubSpot only when one of these is true:
Calendly confirms the invitee through your Calendly connection.
The respondent has already completed the form, and so passed the check.
Otherwise the booking is recorded but the sync is skipped. HubSpot history shows a Skipped row that gives the reason.
When the check cannot run
Sometimes the check cannot run at all: Cloudflare is briefly unreachable, a browser extension blocks it, or the browser is not supported. Nothing is lost:
The answers are saved as a partial submission. Like every partial while protection is on, it is not delivered.
The respondent reads We couldn’t complete the security check. Your answers are saved. Please try again.
When they try again and the check passes, the same submission becomes complete and is delivered.
Submissions sent without the form
The check is verified by the Dapta Forms API, not only by the browser. A script that posts straight to the public submissions endpoint without a valid check is refused and nothing is written. The error codes are listed in Public API & rate limits.
Privacy
The Cloudflare script loads only on forms with protection on, and only once the respondent starts answering. A visitor who only looks at the form sends nothing to Cloudflare.
To verify a check, Dapta Forms sends Cloudflare the check's token and, when it is a public address, the respondent's IP address. Neither is stored with the response.
Refused attempts are recorded without any answers and are not counted in Analytics.
More on what is stored, and what is not, in Security & Privacy.
💡 Tip: Running your own copy of Dapta Forms? Spam protection needs Cloudflare Turnstile keys on your deployment. See Feature flags & environment.
What's next
Webhooks: the partial and complete triggers.
How the sync works & troubleshooting: when a contact is created or updated.
Partial submissions (lead capture point): where the partial submit point sits.
Delivery, retries & history: what happens after a submission.
Last updated