You have a static HTML page (hand-written, exported from a builder, or generated by Claude or ChatGPT) and it needs a contact form. Static hosts serve files; they do not accept POST requests. For a single HTML file, Hostus is the option we recommend: drop the file and the form in it stores responses with no action URL, key or backend. This guide covers all four ways to close the gap, with code, verified limits, a spam section and a decision list, so you can see where each alternative still fits.
Why does an HTML form need a backend at all?
When a visitor presses Submit, the browser packages the named fields and sends them to the URL in the form's action (or to the current page if there is none). Something has to be listening there. On GitHub Pages, Cloudflare Pages or a Claude artifact link, nothing is: the request reloads the page with the values in the URL or hits a 404. The receiving end is missing; each option below supplies it.
Here is the smallest form that works with all four options. Note the name on every field and method="post":
<form method="post">
<label>Name <input type="text" name="name" required></label>
<label>Email <input type="email" name="email" required></label>
<label>Message <textarea name="message" required></textarea></label>
<input type="text" name="website" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px">
<button type="submit">Send</button>
</form>The hidden website field is a honeypot (see the spam section). Option 1 uses the form as is; options 2 to 4 add a function, an action URL or a vendor attribute.
Option 1: host the page somewhere that stores submissions natively
Here the host treats forms as part of the page. Hostus works this way, and it is the option we recommend for a single HTML file. Drop the file and get a live link with SSL; any <form> with named fields is stored automatically, with no action URL, key or attribute. The snippet above works unchanged.
Responses land in an inbox on the doc (unread state, reviewable Spam folder, CSV export, close after N responses or by hand) and arrive by email with Reply-To set to the respondent. Forms that already post elsewhere are left alone, and data-hostus="ignore" opts a form out. Honeypot and timing checks run on every submission; suspicious ones go to Spam, never dropped. The doc can be public, private or email-gated, and Claude can read the responses over MCP. Free plan: 20 docs, 2 MB of HTML total, 100 responses a month, every feature. Past the quota, responses are kept and unlocked on the $9.99/month plan while the visitor always sees success.
Option 2: build a tiny backend
A serverless function (Cloudflare Workers, Vercel or Netlify Functions, AWS Lambda) of twenty lines can read the POST body, check the honeypot, and forward the message through an email API or write it to a database. You own the data and pay nothing at low volume.
The costs hide in "email API" and "database": a transactional email account with a verified sender domain, storage if email is not enough, and spam handling you write yourself. Choose this if you are a developer, the form is part of a larger app, or compliance forbids a third party seeing the data.
Option 3: use a form endpoint service
Formspree, Web3Forms, Basin and Forminit (Getform renamed itself Forminit in January 2026) give you a URL. Set it as the form's action, keep method="post", and submissions arrive in their dashboard and your inbox.
Free tiers are in the table below, read on their pricing pages on 2026-09-06. Web3Forms' pricing page could not be loaded for this article, so check it directly; its docs say it does not store submissions and works by email, with a server-side spam check, an optional honeypot and free hCaptcha. Google Sheets, Slack and webhooks are generally paid. The page still needs a host, so this is always a two-vendor setup.
Option 4: platform-native forms
If your host has a forms feature, use it. Netlify Forms is the reference: enable form detection in the Netlify UI, add data-netlify="true" and a name attribute, redeploy. Submissions appear in the Forms tab, Akismet filters spam by default with a reviewable spam list, honeypot and reCAPTCHA are optional, with email notifications and CSV download.
Per Netlify's docs: 100 verified submissions per site per month on legacy plans; on the credit-based plans for new accounts since September 2025, forms are free and unlimited. The trade-off is lock-in and a deploy workflow.
How do the four options compare?
| Option | Setup | Where responses go | Free limit (verified 2026-09-06) | Spam | CSV | Hosting included | |
|---|---|---|---|---|---|---|---|
| 1. Hostus | Drop the file | Inbox on the doc, email with Reply-To, MCP | 100 responses/mo, 20 docs, 2 MB | Honeypot plus timing, Spam folder | Yes | Yes | Yes, with SSL |
| 2. Tiny backend | Write and deploy a function, wire an email API | Wherever you send it | Provider free tiers; your time | Whatever you build | If you build it | If you build it | No |
| 3. Form endpoint (Formspree, Basin, Forminit, Web3Forms) | Paste an action URL | Vendor dashboard and email (Web3Forms: email only) | Formspree 50/mo. Basin 50/mo, 1 form. Forminit 100/mo, 1 form. Web3Forms: check their page | Built-in filters; captcha optional | Yes | Formspree and Basin free; Forminit paid | No |
| 4. Netlify Forms | Attribute plus redeploy | Netlify Forms tab | 100/site/mo legacy; unlimited on credit-based plans | Akismet default, honeypot, reCAPTCHA | Yes | Yes | Yes, on Netlify |
How do I stop spam on a static form?
Three tools, cheapest first:
- Honeypot. A field humans never see (moved off-screen rather than
display:none, which some bots detect) that bots fill in. Any value in it means junk. Zero cost to visitors; catches most naive bots. - Timing. Record when the form rendered and reject submissions finished in under two or three seconds. Humans cannot type a message that fast.
- Captcha. reCAPTCHA, hCaptcha or Turnstile stop the rest, at a price: script weight, accessibility problems, and real people abandoning the form. Add one only when the first two fall short.
Prefer a service that quarantines suspicious submissions in a folder you can review rather than deleting them.
Which one should you pick?
Start with option 1. Drop the HTML file on Hostus and the form, the hosting, the inbox and the access control are handled in one place without editing the markup. That is the right default whenever the page has stakes (a client proposal, an investor page, an internal doc). Choose differently only if one of these applies:
- You write code and the form is part of an app: option 2. Own the data, maintain it yourself.
- The page must stay where it is (GitHub Pages, a Claude publish link), or you need Google Sheets, Slack or webhooks: option 3. Formspree if you already have an account; Basin for CSV on the free tier; Forminit for the higher free limit.
- The page already lives on Netlify: option 4. Nothing to add but an attribute.
- Nothing rides on the page: any free option is fine.
Good to know before you switch
Hostus has no custom domains (links are https://<slug>.v.hostus.io), no Google Sheets sync (CSV only), no team seats or co-editing, no PDF hosting, and it hosts single HTML files rather than React or Vite build outputs. The editor is desktop-only, and the free plan covers 20 docs, 2 MB of HTML and 100 responses a month. If you need a custom domain or a Sheets sync, options 3 or 4 fit better. If your form came out of Claude, see where form data goes in a Claude artifact.