Skip to content
← All frameworks
html · Framer

Visual builder

Framer form handling without a backend

Framer can publish a beautiful site fast, but its form handling is tied to Framer's own infrastructure. To own where the data goes - and keep it in the EU - send submissions to Formward, an EU-hosted form backend. You either set the form's submit/action URL to your Formward endpoint, or drop in an Embed with a plain HTML form.

The most reliable route across Framer versions is an Embed (HTML) element containing the form below. It posts directly to Formward with a standard browser submit, so it does not depend on Framer's form component or any connected service.

EU-hosted · Framer for the design, Formward for the data: submissions are received in Sweden, so your EU site keeps an EU-only data path.

The Framer example

Copy this into your project and replace <FORM_ID> with the id of a form you create in the Formward dashboard.

html

<!-- Add a Framer "Embed" (HTML) element and paste this in.
     A standard POST submits straight to Formward - no Framer backend. -->
<form action="https://forms.formward.eu/f/<FORM_ID>" method="POST">
  <input type="email" name="email" placeholder="Email" required />
  <textarea name="message" placeholder="Message" required></textarea>

  <!-- Honeypot: keep empty. -->
  <input type="text" name="_gotcha" tabindex="-1" autocomplete="off"
    style="display:none" aria-hidden="true" />

  <button type="submit">Send</button>
  <p>We only use your details to reply. <a href="/privacy">Privacy policy</a></p>
</form>

<!-- If you use Framer's native Form element instead, set its
     submit URL / action to: https://forms.formward.eu/f/<FORM_ID> (method POST),
     and add a hidden field named "_gotcha". -->

Success and error handling

  • A standard HTML submit needs no JavaScript and no Framer service: the browser POSTs to Formward, which replies with a 302 redirect or your thank-you page.
  • Inside an Embed, the form is plain HTML, so it behaves identically wherever the Framer site is published.
  • Keep the hidden _gotcha field empty; Formward uses it to drop obvious bots before they reach your inbox.

Spam protection

Every example above includes the _gotcha honeypot field. It is hidden from real users and must stay empty. When a bot fills it, Formward files the submission as spam and still answers with a normal success response, so the bot learns nothing and nothing reaches your inbox. Rate limits and the origin allowlist are checked on Formward's side as well. For a stricter gate, switch on Cloudflare Turnstile in the form's settings and add the widget; it adds a cf-turnstile-response field that Formward verifies on receipt. Turnstile is optional, and Cloudflare is a US provider, listed as such in the sub-processor register. The spam docs have the widget markup.

The JSON response

A standard POST gets a 302 redirect (or your thank-you page). Send the Accept: application/json header - as every fetch() example above does - and Formward returns JSON instead:

HTTP/1.1 200 OK
Content-Type: application/json

{ "ok": true, "id": "3f2a9c1e-...", "files": 0, "success": { "title": "Thank you!", ... } }

files is the number of uploaded files stored and success carries the confirmation text from the form's settings. When you set a redirect URL for the form, the reply also has a redirect field your code can send the visitor to. On failure the body is { ok: false, error } with a 4xx status: 422 when required consent is missing or a field is too long, 403 when a Turnstile check fails, 429 for too many submissions from one address, 402 when the account is over its allowance and its Over limit folder is full. See responses and redirects for the full table and the AJAX docs for CORS.

Other frameworks

Collect your first Framer submission

Create a form, paste the snippet, and keep every submission in the EU. GDPR-clean from the first POST.