Skip to content
FormSubmit
Fundamentals

Static Website Forms: 5 Ways to Add a Form Without a Backend

Static website forms need somewhere to send data. Compare mailto, form backends, serverless functions, platform forms and embeds, plus a step-by-step example.

FormSubmit Team

5 min read

Static website forms on a plain HTML page sending submissions to a hosted endpoint

Static website forms need an external service to receive submissions, because static hosts only serve files and cannot run code when someone clicks submit. The simplest fix is to point your form's action at a hosted form backend; alternatives include a serverless function, your host's built-in forms, or an embedded form builder. The mailto: trick technically works but is unreliable.

This guide explains why forms on static sites break, compares the five options, and walks through adding a working contact form in a few minutes.

Why static sites cannot process forms

A static site is a folder of HTML, CSS, JavaScript and images. Hosts like GitHub Pages, Cloudflare Pages or an S3 bucket return those files when a browser asks for them. That is all they do.

Processing a form takes more. When a visitor submits, something has to:

  • Accept an HTTP POST request
  • Parse the fields and any uploaded files
  • Check for spam
  • Send an email or store the data somewhere
  • Respond with a redirect or a message

With no backend, there is nothing to do those steps. That is why a form on a static host that posts to its own page often returns a 405 "Method Not Allowed" error, or simply reloads with nothing sent.

Five ways to add a form to a static website

1. A mailto form

Setting action="mailto:you@example.com" asks the visitor's computer to open an email app with the form data. It needs no service at all, but it fails for anyone without a configured mail client, gives no confirmation and exposes your address to scrapers. We cover this in detail in mailto form vs form backend.

2. A hosted form backend

You keep your form markup and set its action to a URL provided by a form backend service. The service handles spam, storage, email notifications and integrations. It works on every static host and with every static site generator. See what is a headless form backend for how the request flow works.

3. A serverless function

Hosts like Netlify, Vercel and Cloudflare let you deploy functions next to your static files. You write the handler, connect a transactional email provider and add your own spam checks. Full control, more maintenance.

4. Platform forms

Some hosts, Netlify being the best-known example, can detect forms in your HTML at deploy time and collect submissions for you. It is quick if you already host there, but the form only works on that platform.

5. An embedded form builder

Tools like Google Forms, Typeform or Tally host the form and let you embed it, often in an iframe. Good for surveys and multi-step flows, but the form does not inherit your site's styles and lives partly outside your page.

Static website forms: comparing the options

OptionSetup effortWorks on any hostReliable deliverySpam protectionDesign control
mailto formMinimalYesNoNoneFull
Hosted form backendLowYesYesBuilt inFull
Serverless functionMedium to highOnly hosts with functionsDepends on your setupYou build itFull
Platform formsLowOnly that hostYesVaries by platformFull
Embedded form builderLowYesYesBuilt inLimited

For most static site contact forms, a hosted backend gives the best balance: no backend code to maintain, and the form stays native HTML that you can style however you like.

Step by step: a static site contact form

Here is the full process using a hosted endpoint. It works on any host because the browser posts directly to the service.

  1. Create a form with a form backend service and copy its endpoint URL.
  2. Add the HTML below to your page, replacing YOUR_FORM_ID.
  3. Make sure every field has a name attribute; unnamed fields are not sent.
  4. Deploy your site and submit a test entry.
  5. Check your inbox (and spam folder the first time) for the notification.
html
<form action="https://formsubmit.app/f/YOUR_FORM_ID" method="POST">
  <label for="name">Name</label>
  <input id="name" type="text" name="name" autocomplete="name" required>

  <label for="email">Email</label>
  <input id="email" type="email" name="email" autocomplete="email" required>

  <label for="message">Message</label>
  <textarea id="message" name="message" rows="5" required></textarea>

  <input type="hidden" name="_subject" value="New message from the website">
  <input type="hidden" name="_redirect" value="https://example.com/thanks">
  <input type="text" name="_gotcha" tabindex="-1" autocomplete="off" style="display:none">

  <button type="submit">Send message</button>
</form>

The three control fields are optional: _subject sets the notification subject, _redirect sends visitors to your own thank-you page, and _gotcha is a honeypot that silently catches bots. The full list is in the control fields docs.

Optional: submit without a page reload

If you want an inline success message, intercept the submit and use fetch:

js
const form = document.querySelector("form");

form.addEventListener("submit", async (e) => {
  e.preventDefault();
  const res = await fetch(form.action, {
    method: "POST",
    body: new FormData(form),
    headers: { Accept: "application/json" },
  });
  const result = await res.json();
  form.innerHTML = result.ok
    ? "<p>Thanks, your message was sent.</p>"
    : "<p>Something went wrong. Please try again.</p>";
});

A JSON response looks like { "ok": true, "id": "…" } on success or { "ok": false, "error": { "code", "message" } } on failure.

Hosting notes

The HTML form above behaves the same everywhere, but each host has its own quirks.

  • GitHub Pages: pure static hosting with no functions or form handling, so a hosted endpoint is the practical choice. Custom domains work as usual.
  • Netlify: offers built-in forms and functions. If you use a third-party endpoint instead, make sure Netlify's form detection is not also trying to handle the same form.
  • Vercel: static and framework sites can use serverless functions, or post to an external endpoint with no configuration.
  • Cloudflare Pages: supports Pages Functions for custom handlers; external endpoints work without changes.
  • Amazon S3 (with or without CloudFront): static files only. S3 does not accept form posts to your bucket, so an external endpoint is required.

Handling files and integrations

Static forms can do more than send email. With a form backend you can accept uploads by adding enctype="multipart/form-data" to the form and an input type="file"; see file uploads for limits. You can also forward submissions to tools like Google Sheets or Slack, or to your own API via webhooks, all without writing server code.

Get your static form live

FormSubmit is a headless form backend built for exactly this case: point your static website forms at a FormSubmit endpoint and you get spam protection, email notifications, uploads and integrations on every plan, including Free. Build a form visually with the free form generator, or follow the HTML contact form guide for more detail.

Last updated .

Frequently asked questions

Can a static website have a contact form?

Yes. The form itself is plain HTML; you only need to point its action at something that can process the POST request, such as a hosted form backend, a serverless function or your host's built-in form handling.

Why does my form return a 405 error on a static host?

Static hosts serve files and usually do not accept POST requests to your pages. Point the form's action at a form endpoint or function instead of your own page URL.

Does GitHub Pages support forms?

GitHub Pages only serves static files, so it cannot process submissions itself. Forms on GitHub Pages work by posting to a third-party form backend.

Is a mailto form good enough for a static site?

Usually not. It depends on the visitor having a configured email app, gives no confirmation that anything was sent and exposes your address to scrapers.

Related resources

Keep reading

Your form backend is 60 seconds away

Sign up with Google or email, create a form, paste the endpoint. Free forever for small sites — no credit card.