Putting a form on a website costs nothing now. There are at least three ways to do it without paying anyone, and all three will have a working contact form live in under an hour. The part that goes wrong is later: six weeks in, someone asks what happened to the enquiry from the person at the trade show, and the honest answer is that it went to an inbox and then to whoever read it first.
That is not a small gap. It is the difference between a form that collects and a form that a business can run on. So it is worth choosing the free route with the second problem in mind rather than only the first.
Three shapes, and the trade they each make
The free options fall into three families. They differ in who hosts the form, who receives the data, and what is left behind afterwards.
Embed a hosted form
You build the form in a tool, the tool gives you an iframe or a script tag, and you paste it into a page. Google Forms, Tally, Jotform, Cognito Forms and Fillout all work this way, and all of them have free tiers.
What you get is the fastest path and the most features for nothing: conditional logic, file uploads, multi page flows, validation that already works on a phone. What you give up is control of the markup. The embedded form is someone else's HTML in a frame, so it will not inherit your site's typefaces or spacing without whatever theming options the vendor exposes, and on free tiers it usually carries the vendor's mark.
The free caps differ sharply here. Tally lists unlimited forms and unlimited submissions on its free plan under a fair use policy. Fillout's free plan allows unlimited forms and unlimited seats with 1,000 responses a month. Jotform's free Starter plan allows 5 forms and 100 monthly submissions, with 500 submissions stored in total. Cognito Forms allows unlimited forms with 100 entries a month.
Point your own HTML at a form backend
This route keeps the form in your own markup and sends the submission to a service that turns it into email. Formspree, Web3Forms and FormSubmit all do this, and the setup is genuinely one attribute.
<form action="https://formsubmit.co/[email protected]" method="POST">
<input type="text" name="name" required>
<input type="email" name="email" required>
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form>
FormSubmit needs no registration at all: point the action at an address, submit once, and confirm the verification email that arrives. Web3Forms works the same way with an access key instead of an address, and its free tier allows 250 submissions a month across unlimited forms and unlimited domains, with honeypot and hCaptcha spam protection included. Formspree's free tier is 50 submissions a month with a 30 day archive, which their plans page describes as being for testing and development rather than production use.
This is the right route when the form has to look exactly like the rest of the page, because it is the rest of the page. It is the wrong route when the form needs logic, because you are writing that logic yourself.
Use a plugin, if the site runs WordPress
Contact Form 7 is free, has been installed on a very large number of sites, and its own documentation contains the sentence that should decide how you use it: Contact Form 7 does not store submitted messages anywhere. The author is explicit about the consequence, which is that a mail server problem or a mistake in the mail configuration loses the message permanently.
The fix is also free. Flamingo, written by the same author, saves every message through contact forms into the WordPress database, and it is a separate plugin you have to install deliberately. A large number of WordPress sites run Contact Form 7 without it and have no record of anything ever submitted, which nobody discovers until the day the mail stops arriving.
The same three routes, side by side
| Route | Setup | Form looks like your site | Record kept | Typical free cap |
|---|---|---|---|---|
| Embedded hosted form | Paste an iframe | Vendor theming only | Yes, in the vendor dashboard | Responses per month, or forms |
| Form backend for your HTML | One action attribute | Exactly, it is your markup | Dashboard, often 30 days | 50 to 250 submissions a month |
| WordPress plugin | Install and configure | Yes, via the theme | Only if a storage plugin is added | None on the plugin itself |
Three details that decide how the form feels
Whichever route you take, the same three mechanics separate a form that converts from one that people abandon halfway.
What happens after submit. The default on a form backend is a vendor hosted thank you page, which means the visitor leaves your site at the exact moment they were most engaged. Every service in this article supports a redirect to a page you control, usually through a hidden input, and it is the single highest value five minutes of configuration available. A thank you page on your own domain can also carry the next step: what happens now, when to expect a reply, what to read meanwhile.
Height on a phone. An embedded form in a fixed height iframe produces a scrollbar inside a scrollbar, which is the most reliable way to lose a mobile visitor. Most vendors ship a script tag alongside the raw iframe that resizes the frame to fit its contents; use it rather than the plain iframe. Tools that show one question per screen sidestep the problem entirely, because the frame never needs to be tall.
Whether the email field is named correctly. This sounds trivial and is not, for reasons that appear in the next section but one. Several services key their reply behaviour and their duplicate detection on a field literally named email, so renaming it to your-email or contact quietly turns those features off.
The cost that is not on any pricing page
Spam is what turns a free form into a maintenance job. Any form that sits on a public page and posts to a known endpoint will be found by bots within days.
The free tiers vary in what they give you. Web3Forms includes honeypot protection and hCaptcha on its free plan and puts reCAPTCHA and Cloudflare Turnstile behind the paid tier. Formspree includes spam filtering from the Personal tier. Contact Form 7 ships a honeypot only if you add another plugin, and the common approach is to bolt on a CAPTCHA integration.
The honeypot is the cheapest thing that works and costs nothing on any route: add a field that is hidden with CSS, and discard any submission where it is filled in. It stops the crude bots, which are most of them. Whatever else you do, do that.
A related detail on the form backend route that catches people out: the access key or target address sits in the page source, visible to anyone. Web3Forms addresses this directly in their documentation, and the mitigations are domain restriction and CAPTCHA rather than secrecy. Treat the endpoint as public, because it is.
Where every free route loses the thread
All three families end in the same place, which is an inbox. That is fine while one person is responsible for the form and not fine the moment a second person is.
Netlify Forms shows the problem in a single concrete detail worth quoting, because it is the same on nearly every route. Its notification emails are sent from a service address, and replies to a notification go back to that service address rather than to the person who filled in the form. The documented workaround is to include an input named email in the form, which sets the reply address on the notification so a reply reaches the submitter. Useful, and also a good illustration of what these tools are: a pipe from a page to a mailbox, with no opinion about what happens after delivery.
Once the mail arrives, nothing tracks any of the following. Who is dealing with this one. Whether it has been answered. What was said. Whether the same person has submitted three times. Whether the enquiry from March was ever resolved. Those questions are answered by forwarding, by asking across the room, and eventually by nobody.
The second symptom is duplicated replies. Two people see the same notification, both assume the other is busy, and the enquirer gets two different answers on the same day, or none.
The third symptom is slower and worse. Because the record lives in individual mailboxes, it leaves when people do. A team that has run a contact form for three years through two staff changes usually cannot produce the enquiries from the first year at all, and often cannot produce last quarter's either, because the archive that mattered belonged to whoever was reading the notifications at the time.
What keeping track actually requires
The fix is not a better notification. It is moving the unit of work from the message to the response itself.
In practical terms that means each submission carries three things that an email cannot: an owner, so it is clear who is dealing with it; a stage, so its state is visible without asking; and a history, so the replies that have gone out are attached to the response rather than sitting in one person's sent items. Notifications still go out, and they can go to Slack, Teams, Chatwork or Discord instead of only email, but they point at a shared record rather than being the record.
This category is where free tiers diverge most. Some tools treat stages and ownership as a workflow feature reserved for higher paid tiers, so the free plan gives you unlimited responses and no way to share the work. Others include them from the free tier and cap the number of people instead. The features page shows what the second shape looks like in practice, and the use cases cover the intakes where the difference shows up soonest: applications, enquiries, event sign ups and grant programmes.
For a site that genuinely only needs a contact form read by one person, none of this is worth paying for. A form backend and a honeypot will serve for years. The line is crossed when a second person has to answer, or when someone starts asking about submissions from last quarter.
What to do first
Put the form up this week using whichever of the three routes matches the site, and add a honeypot field at the same time. Then check the one thing people skip: confirm that a record exists somewhere other than an inbox, which on WordPress means installing Flamingo alongside Contact Form 7, and on a form backend means knowing how long the archive keeps data. If more than one person will answer what arrives, look at a form tool that holds an owner and a status against each response; the demo runs without an account, and Halict keeps forms and responses unlimited on its free tier and prices by how many people are using it.
Q1. What is the easiest way to add a form to a website for free?
Pointing your own HTML form at a form backend is the shortest path if the page already exists. FormSubmit requires no registration at all: set the form action to their endpoint with your email address, submit once, and confirm the verification email. Web3Forms works the same way with an access key and allows 250 submissions a month free.
Q2. Does Contact Form 7 save the messages people send?
No. The Contact Form 7 documentation states that it does not store submitted messages anywhere, which means a mail server problem or a mail configuration mistake loses them permanently. Installing Flamingo, a free plugin by the same author, saves every message into the WordPress database.
Q3. How do you stop spam on a free website form?
A honeypot field is the cheapest defence and works on every route: add a field hidden with CSS and discard any submission where it is filled in. Beyond that, free tiers differ. Web3Forms includes honeypot and hCaptcha on its free plan and reserves reCAPTCHA and Cloudflare Turnstile for paid tiers.
Q4. Why can't I reply directly to a form notification email?
Because the notification is sent by the form service, not by the person who filled in the form, so the reply address is the service. Netlify documents the standard fix: include an input named email in the form so the notification carries a reply address that reaches the submitter. Not every service does this automatically.
Q5. Is an embedded form or a form backend better for a website?
An embedded form gives you validation, conditional logic, file uploads and a dashboard without writing anything, at the cost of the form being someone else's markup in a frame. A form backend keeps the form as part of your own page and styling, at the cost of building any logic yourself. Pick on whether appearance or features matter more for that particular page.
