CatchForm

Static Site Contact Form

A static site has no server that could receive a form. This page shows what each common host does with a submission, and gives you one form that works on all of them.

Copy this
<form action="https://catchform.dev/f/YOUR-TOKEN" method="POST">
  <input type="hidden" name="_gotcha" value="">
  <input name="name" type="text" required>
  <input name="email" type="email" required>
  <textarea name="message" required></textarea>
  <button type="submit">Send</button>
</form>

Works on any host, because the form posts to CatchForm and not to the server that serves your page. Replace YOUR-TOKEN with the token of your form.

Why a Static Site Has No Form Out of the Box

A static site is a folder of files that the server hands out as they are. When a visitor submits a form, the browser sends a POST request to the address in the form's action. On a static host nothing is waiting for that request: there is no program that accepts the data, checks it, stores it or sends an email. The browser can send the request, but nobody is there to take it.

The fix is not to make the static host do more. It is to point the form at something that does receive posts. The sections below show how each common host handles that situation.

Host by Host

The table covers the five hosts people most often deploy static sites to. Hosts change their products over time, so check the host's current docs before you rely on any of this.

Host Built-in form handling Runs your server code
Netlify Yes, Netlify Forms Only if you add functions yourself
Vercel No ready-made form product Yes, through server functions you write
Cloudflare Pages No intake or storage of submissions Yes, through Pages Functions you write
GitHub Pages No No
S3 / CloudFront No No

Netlify

Netlify is the one host in this list with a form product of its own. Netlify Forms is built into the platform. If your site is already on Netlify and you receive a modest number of submissions, it is a reasonable choice, and there is no need to move the site just to change where forms go.

CatchForm makes more sense when the host may change later, or when you need something Netlify Forms does not give you. Both products send email notifications and export submissions as CSV, so the comparison comes down to where the form lives and what else you need. The details are in CatchForm vs Netlify Forms.

Vercel

Vercel has no form product. To receive submissions there you write a serverless function that accepts the POST, checks it and delivers it, and you deploy and maintain that code together with the rest of the project. An external endpoint such as CatchForm takes that code out of your project, and the form stays plain HTML.

Cloudflare Pages

Cloudflare Pages serves the site and can run your code through Pages Functions. It does not take in or keep form submissions for you, so a form handled there means a Pages Function you write yourself, with its own spam checks and its own email delivery.

GitHub Pages

GitHub Pages serves files and runs nothing on the server. A form on a GitHub Pages site can only post to an address somewhere else, so its action has to point to an external endpoint. The site itself cannot receive the submission.

S3 / CloudFront

An S3 bucket behind CloudFront returns files and runs nothing on the server. You can build a form backend from API Gateway, Lambda and an email service, but that is your own backend to operate, which is the work a static site is meant to avoid. An external endpoint is the shorter route.

The Universal Way: a Plain Form With an External Action

A form whose action points to an external endpoint works on all five hosts above, for one reason: the POST is received by that endpoint and never by your host. The host only serves the page that contains the form. Nothing has to be configured on the host, so the deployment stays what it was: a folder of files.

Other external endpoints work the same way. To compare them with CatchForm, see CatchForm vs Formspree or CatchForm vs FormSubmit.

<form action="https://catchform.dev/f/YOUR-TOKEN" method="POST">
  <input type="hidden" name="_gotcha" value="">

  <label for="contact-name">Name</label>
  <input id="contact-name" name="name" type="text" required>

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

  <label for="contact-message">Message</label>
  <textarea id="contact-message" name="message" required></textarea>

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

Nothing in this form depends on the host. It is ordinary HTML with a fixed action, so you can move the site to another host and the form keeps working. If you are replacing an old contact.php, the Contact form without PHP guide walks through that move.

The hidden input is a honeypot. Visitors never see it, so they leave it empty, but bots that fill in every field fill it too, and a submission with a value in that field is rejected as spam. The field's name comes from the honeypot configuration of the application, which is why the snippets on this page always show the name in use. Copy it from here rather than from an older copy of the form.

Using a Static Site Generator

If you build the site with a generator, put the form in a component or template so it is written once and rendered on every page. The HTML it produces is the same, and the output stays static.

For Astro, Contact form for Astro shows the form as a reusable component.

For Hugo, Contact form for Hugo shows the same form as a partial.

What Happens After Someone Submits

What the visitor sees depends on whether a return address is configured and on how the request was made:

  • No return address configured, and a regular submission from a browser: the visitor lands on a thank-you page hosted by CatchForm on catchform.dev. That page shows neither your form's identifiers nor the sender's data.
  • No return address configured, and a programmatic request such as fetch or curl: the response is the JSON object {"success": true}.
  • Return address configured in the form settings (Redirect after submit): the visitor is redirected to that address, and this applies to browser and programmatic requests alike. You can also set the address when you create the form.

For a step-by-step walkthrough of the browser side of a submission, see HTML form to email.

Get Started

See pricing and create your form, then copy its endpoint into the action attribute shown above. You can start with 100 submissions a month and no credit card.

File uploads are available on the Starter and Pro plans.