# Verify emails on any website form with the Spaw form helper

One script tag adds live email verification to Webflow, Framer, Squarespace, Carrd or plain HTML forms: typo fixes and dead-address notices, never blocking.

Updated: 2026-09-03

The Spaw form helper is a small script that watches the email inputs you mark, verifies the address when the visitor leaves the field, and renders two things: a "Did you mean …?" correction when the address looks like a typo, and a notice when the address cannot receive mail. It never blocks a submit and never waits for the API, so a slow network or an empty credit balance only means the hint does not appear. It works on any page where you can add custom code, which covers Webflow, Framer, Squarespace, Carrd and a hand-written HTML form alike.

## Add it to a form

1. On the API keys page, create a publishable key and lock it to the domains your form runs on. A publishable key can only run single email lookups from those origins, so it is safe in page source.
2. Give the key a daily credit cap. Once the cap is spent the browser endpoint answers `429 KEY_SPEND_CAP_REACHED` until the next day, and the helper stays quiet.
3. Add the script and mark the input:

```html
<script src="https://spaw.co/spaw-form.js" data-key="pk_live_…" defer></script>

<input type="email" name="email" data-spaw-email>
```

4. For forms open to the public, store a Cloudflare Turnstile site key and secret on the publishable key and add `data-turnstile-site-key` to the script tag. The helper then fetches a fresh single-use token before every lookup and the endpoint refuses lookups without one, so a bot scripting your form cannot spend your credits. Turnstile only shows a challenge when Cloudflare needs one.

## When you cannot set an attribute on the input

Some builders let you add custom code to the page but not attributes to a form field. Mark the field from a short script placed before the helper's script tag. Listeners registered earlier run first, so the input is marked before the helper looks for it:

```html
<script>
  document.addEventListener('DOMContentLoaded', function () {
    document.querySelectorAll('form input[type="email"]').forEach(function (input) {
      input.setAttribute('data-spaw-email', '');
    });
  });
</script>
<script src="https://spaw.co/spaw-form.js" data-key="pk_live_…" defer></script>
```

In Webflow and Framer, paste both tags into the site's custom code section that lands in the head; Squarespace and Carrd take them in the page or site code injection settings. On a plain HTML page, put them anywhere in the document.

## Keep your secret key on the server instead

If you would rather not use a publishable key, point `data-endpoint` at a route you host. The helper posts `{ "email": "…" }` there and expects the API's JSON back unchanged; the route adds your secret key and forwards the request to `POST /api/v1/email`. A five-line proxy in any framework does it; the product page shows Laravel and Node versions. Rate-limit the route, because it spends your credits.

## Enforce your own policy

Every verdict is emitted as a bubbling `spaw:result` event on the input, with the full API response in `event.detail`. The helper itself only hints; the event is where you decide:

```html
<script>
  addEventListener('spaw:result', function (event) {
    var result = event.detail;

    if (result.disposable || result.deliverable === 'undeliverable') {
      document.querySelector('button[type="submit"]').disabled = true;
    }
  });
</script>
```

The response is the same 27-field answer the API gives a server, minus the billing block, so page visitors never see your balance. Branch on `deliverable`, use `did_you_mean` to offer the fix, and read `reason` before refusing anything marked `risky`: a catch-all domain is risky but often a fine address.

## Cost

One credit per answered lookup, charged to the key's owner. Undeliverable answers, repeats within seven days and the free test addresses on `spaw.test` cost nothing and never count toward the key's daily cap. Every account gets 10 free lookups a month.

Reference: https://spaw.co/integrations/website-forms
