Comparison

Best form backend services in 2026: 13 tested with the same requests

Search for the best form backend and most of the lists you find was written by one of the backends. This page was too: we make Formgong. So instead of a ranking, here is what 13 services answered when we sent each of them the same requests, and what their own pages said about the free plan on the same day.

Short answer: There is no single best one. Pick on three things the lists skip: whether the free allowance is monthly or one-off, what happens to a message that arrives over the limit, and whether your code can tell a broken setup from a sent message. Four of the 12 services that answered gave HTTP 200 to a wrong key at least once: Web3Forms, Forminit, FormSubmit and Formspark. The other eight answered every wrong key with an error status.

Formgong·

How we tested

A form backend is the service your form posts to when your site has no server of its own. It takes the POST, keeps the message and sends it to you. Most free plans look alike on a pricing page, so we looked at what you only find out once something goes wrong.

On 16 October 2026 we sent each service the same four kinds of request, with keys we made up, so nothing was stored or delivered. First the placeholder from the service's own docs, the one people forget to replace. Then a random key of the right shape. Then the same request from a server instead of a browser. Then a plain HTML form with no JavaScript, to see what a visitor's browser ends up showing. The rules for passing were written down before the first request. FormKeep answered every request with "Rate Limit Exceeded", in two passes an hour apart. We cannot tell from outside whether that is its answer to an unknown form or a block on our address, so its row is not scored.

The same day we read each service's pricing, docs and privacy pages and quoted them. Where a page said nothing, or two of its pages disagreed, the table says so. We left prices out on purpose: they change more often than anything else here, and each service shows its own.

What each service answered to a wrong key

Made-up keys sent on 16 October 2026 (11:54 to 12:04 UTC). Browser: Chrome 155 on a page at example.com. Server: curl. Bold marks an answer a response.ok check would read as success, or no answer at all.
ServicePlaceholder from its own docsRandom keySame request from a serverPlain HTML form, no JavaScript
Formgong404, unknown_access_key404, unknown_access_key404, about the keyError page: key does not exist
Formspree404, Form not found404, Form not found404, about the formError page: form not found
Web3Forms200, success: true ("It works")400, invalid key403, server calls need a paid planError page: invalid key
Forminit200, "form has been deleted"200, "form has been deleted"200, about the formError page: form deleted
Basin400, endpoint does not exist400, endpoint does not exist400, about the formError page: endpoint locked
FormSubmitNo placeholder (its docs use a real email domain)200, success: "false" as a string200, "open this page through a web server"Error page: address not valid
Formcarry500 (body says 401), form invalid500 (body says 401), form invalid500, about the formError page: form invalid
Formspark200, HTML: replace the placeholder404, form does not exist404, about the formError page: form does not exist
FormBackend404, HTML: form not found404, HTML: form not found404, about the formError page: form not found
Static Forms401, Invalid API key401, Invalid API key401, about the keyError text: Invalid API key
Splitforms404, invalid_access_key404, invalid_access_key404, about the keyError page: invalid key
JotformNo placeholder (no docs page names the endpoint)Unreadable from JavaScript (no CORS headers)404, form couldn't be foundError page: form couldn't be found

Every service showed a visitor some kind of error page when a plain HTML form used a wrong key. The differences are in what JavaScript gets back, and that matters because most forms built today send with fetch. In our study of AI-built sites, 27 of 105 forms told the visitor "thank you" while nothing was delivered, and a 200 answer to a broken setup is one way that happens.

  • Web3Forms answers its own docs placeholder with success: true and "It works". A form shipped with the placeholder still in it looks fine in testing.
  • Forminit answers a form ID that never existed with HTTP 200 and "This form has been deleted". The body says success: false, so code that reads the body is safe and code that checks response.ok is not.
  • FormSubmit returns "success":"false" as a string with HTTP 200. In JavaScript the string "false" is truthy, so if (data.success) passes.
  • Formspark answers its placeholder with a 200 HTML page that explains the mistake. It answers a random ID with a clean 404.
  • Jotform's submit address sends no CORS headers, so a script on your own site cannot read its answer at all. It is built for Jotform's generated forms, not for your own code.

We ran the same tests on seven of these services a week earlier, on 9 October 2026. All seven answered the same way both times.

Free form backends: what the free plan includes

From each service's own pricing, docs and legal pages, read on 16 October 2026.
ServiceFree planA submission over the free limit
Formgong1,000 a month, unlimited forms, email for every submission, Telegram and Google Sheets20% extra is delivered; after that submissions are stored and wait for the next month or an upgrade, up to one more month's worth; then the form answers 429
Formspree50 a month, unlimited forms, 30-day archive, no file uploadsSaved to an Over Limit folder with no notifications; you reprocess them once you have room
Web3Forms250 a month, unlimited forms, no integrations or file uploadsNot stated in the docs we could read (its pricing pages refused our reader)
Forminit100 a month, 1 form, file uploads with 100 MBThe form pauses; submissions are rejected and cannot be recovered
Basin50 a month, 1 form, 30-day retention, file uploadsBasin's own pages disagree: "may be restricted" in the FAQ, "we won't cut you off" on pricing
FormSubmitNo account; "unlimited" submissions, 30-day retentionNo limit published
Formcarry50 a month, 1 form; spam counts toward the 50Held until next month (up to 1,900) while the visitor sees the normal thank-you page
Formspark250 in total, not per month; 10 forms; webhooks, Slack and ZapierA small buffer is held in Overflow, then new submissions are discarded
FormKeep50 a month per form, unlimited forms, email once a dayIgnored and lost; spam counts toward the limit
FormBackend50 a month, 1 form"Not dropped without warning"; held or rejected is not stated
Static Forms250 a month; more than one form needs a paid planRejected with an error; warning emails at 80% and 90%
Splitforms500 in total, not per month; unlimited formsRejected with HTTP 429 and not stored
Netlify FormsUnlimited on Netlify's credit plans, only for sites Netlify buildsIf the project goes over the plan, the whole project pauses
Jotform100 a month, 5 forms, 10,000 form views (a form builder, not a backend)Forms are disabled and show "This Form Has Exceeded Its Allocated Quota"

Two things stand out. Formspark and Splitforms give a fixed number of free submissions that does not come back each month, which suits a form that gets a few messages a year and does not suit a busy one. And the services disagree most about the message that arrives after the limit. Formspree and Formgong keep it for you. Forminit, Static Forms, Splitforms and FormKeep turn it away. Formcarry keeps it but shows the visitor the normal thank-you page, so nobody knows it is waiting.

Headless form backend: what the term means

"Headless" means the backend has no form of its own for you to embed. You write the form in your own HTML, React, Astro or whatever the site uses, and the backend only receives what it sends. Every service on this page works that way except Jotform and Netlify Forms. Jotform is a form builder: you design the form in Jotform and embed it. Netlify Forms reads your HTML when Netlify builds the site, so it only works on sites Netlify hosts.

If you are choosing one for a JavaScript front end or a server, these are the lines in the docs that decide it:

  • JSON in and out. Formgong, Web3Forms, Formcarry, Formspark, Forminit and Splitforms document a JSON request and a JSON answer. Netlify Forms says it "does not support JSON form data at this time". FormBackend's docs show FormData, not a JSON body.
  • Posting from a server. Web3Forms needs a paid plan and an allow-listed server IP, and our curl request got 403. Formcarry's docs say to post from the browser, not from a server. FormKeep's docs warn that requests with a generic user agent are often blocked. Forminit has a separate protected mode with an API key for servers, and Splitforms' docs say a server can post like any other client. In our test 10 of the 12 answered a server request about the key, as they did in the browser; FormSubmit answered with a note about web servers.
  • Webhooks on the free plan. Formspark and Formgong both include a signed webhook on the free plan. Formspree, Web3Forms, Forminit, Basin and Splitforms keep webhooks for paid plans.

Form endpoint service and contact form API: check the answer, not the status

A "form endpoint" or "contact form API" is the same thing seen from code: one URL that takes a POST and tells you whether the message was accepted. The table above is the case for checking both the status and the body. A 200 on its own proved nothing for four of the twelve services that answered.

This is the check we use in Formgong's own snippets. Formgong answers success: true only when the message was stored, and an error status with a code and a readable message otherwise. If you use another service, swap in the success field its docs name.

JavaScript
const res = await fetch("https://formgong.com/submit", {
  method: "POST",
  headers: { Accept: "application/json" },
  body: new FormData(form),
});
let data = null;
try { data = await res.json(); } catch { /* an HTML or text answer is not a success */ }

// Both checks. A 200 alone is not proof: some backends answer 200 to a broken key.
if (res.ok && data?.success === true) {
  showThanks();
} else {
  showError(data?.message ?? "The message was not sent. Please email us instead.");
}

Point it at a form with a wrong key once before you ship. If the visitor would see "thank you", the check is not doing its job. Our free form checker does the same test on a live page.

Where each service keeps your submissions

  • In the EU by default: Formgong (Cloudflare D1 with EU jurisdiction), Forminit (AWS in Ireland), Formcarry (Frankfurt), Formspark (Ireland and Germany).
  • In the EU if you choose it: Static Forms (Frankfurt for accounts that pick EU residency, US otherwise) and Jotform (Frankfurt after you move the account).
  • In the US: Formspree, Web3Forms (US East), FormBackend, Splitforms (EU residency is on its roadmap).
  • Split: Basin lists its database in Canada, files on AWS in the US and backups in Germany.
  • Not stated on their pages: FormSubmit, FormKeep and Netlify Forms.

Storage location is the service's half of the GDPR. Your half is a notice at the form, a lawful basis and a deletion period, and the GDPR contact form template has wording for each.

Which one to pick

  • Your site is on Netlify and email is enough: Netlify Forms. Nothing else to sign up for.
  • You want no account at all: FormSubmit, as long as your code handles its string "false".
  • A form that gets a few messages a year: Formspark's one-off free allowance, with signed webhooks included.
  • Files on the free plan: Forminit or Basin, both with 100 MB of storage. Formgong accepts files on the free plan too, up to 5 MiB each, once you verify your email and add a Turnstile key.
  • Many integrations and a long track record: Formspree.
  • Sending from your own server with an API key: Forminit's protected mode, or Splitforms.
  • EU storage, every message by email at once, Telegram on the free plan, and the rest of the site in one place: Formgong. The same account gives you free website templates with the form already wired in, and an AI help chat that answers visitors from your own pages, with every message landing in one inbox.

What this test does not show

Made-up keys tell you how a service fails, not how it delivers. We did not measure how fast an email arrives, whether it lands in spam, or what really happens at the monthly limit; that needs a real form on each service, and we will add it to this page when we have run it. Docs change too: everything here was read on 16 October 2026, and each service's own page is the final word.

Questions

What is the best form backend?

It depends on the site. Netlify Forms for a site on Netlify, FormSubmit for no account, Formspree for the most integrations, Formgong for EU storage with Telegram and instant email on the free plan. In our 16 October 2026 test, Web3Forms, Forminit, FormSubmit and Formspark answered a wrong key with HTTP 200 at least once; the other eight that answered did not.

Is there a free form backend?

Most have a free plan. Formgong takes 1,000 a month. On 16 October 2026 the others gave: Web3Forms 250, Static Forms 250, Forminit 100, Formspree, Basin, Formcarry, FormKeep and FormBackend 50. Formspark gives 250 and Splitforms 500 in total, not per month. FormSubmit publishes no limit.

What is a headless form backend?

A backend with no form builder: you write the form in your own code and post it to the service's URL. Formgong, Formspree, Web3Forms, Basin, Formcarry, Formspark, Forminit and Splitforms work this way. Jotform is a form builder, and Netlify Forms only works on sites Netlify builds.

What is a form endpoint service?

A service that gives your form one URL to post to and then stores the message and sends it on, usually by email. Point the form's action or your fetch call at that URL and the site needs no server code.

Is there a contact form API I can call from JavaScript?

Yes. Formgong, Web3Forms, Formcarry, Formspark, Forminit and Splitforms accept JSON and answer with JSON. Check both the HTTP status and the success field: in our test four services answered HTTP 200 to a wrong key at least once.

Can I post to a form backend from my server?

With most. In our test 10 of 12 services, Formgong among them, answered a curl request about the key, as they did in the browser. Forminit has a protected mode with an API key. Web3Forms needs a paid plan and an allow-listed IP. Formcarry asks you to post from the browser, and FormKeep warns that generic user agents are often blocked.

Sources

Checked on 16.10.2026 against these public pages: Formspree plans, Formspree: over-limit submissions, Formspree privacy policy, Web3Forms llms.txt, Web3Forms API reference, Web3Forms FAQ, Forminit pricing, Forminit llms.txt, Forminit security, Basin pricing, Basin plan comparison, Basin GDPR, FormSubmit documentation, Formcarry pricing, Formcarry: what every form needs, Formcarry DPA, Formspark limits and plans, Formspark webhooks, Formspark GDPR, FormKeep pricing, FormKeep API docs, FormBackend pricing, FormBackend GDPR, Static Forms pricing, Static Forms DPA, Splitforms docs, Splitforms GDPR, Netlify Forms setup, Netlify Forms usage and billing, Jotform pricing, Jotform: account usage and limits, Formgong docs, Formgong data and location.

← Formgong