CatchForm

HTML Form to Email

Send form submissions directly to your email without building a backend server. Just HTML, nothing else.

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

That is the whole integration. Replace YOUR-TOKEN with the token from your form, and submissions start arriving by email. No JavaScript, no build step, no server of your own.

Overview

This guide shows the simplest way to add a working contact form to any static site. No JavaScript, no build step, no backend infrastructure — just plain HTML.

Why HTML Forms Need a Backend to Send Email

A common misconception is that HTML can send email by itself. Here's what actually happens when someone submits a form in a browser: the browser collects the form data and makes an HTTP request to a server. That's it. Browsers cannot and do not send email directly.

You might have seen the mailto: attribute or protocol, which looks like it sends email. In reality, it just opens your email client on your device (if one is configured). When someone clicks a mailto: link, the browser passes it to your operating system's email application, and you have to click "send" yourself. Nothing is automatically delivered, and the email address is exposed in your page's HTML source code for any bot to scrape.

To actually send an email when someone submits a form, you need a server — something that receives the form data and hands it off to a mail service. This is what we mean by a "form backend."

Do I Need PHP for a Contact Form?

No. PHP is one way to do it, not the only way. The classic approach was a small contact.php file that calls mail(), and on most modern hosting PHP is not even an option.

Netlify, Vercel, Cloudflare Pages, GitHub Pages and S3 buckets run no PHP at all. Uploading a .php file to them does nothing: it is served as plain text or not served at all. Full walkthrough: contact form without PHP

The Form Action: Your Bridge to Email

Every form has an action attribute that tells the browser where to send the data:

<form action="https://example.com/receive-form" method="POST">
  ...
</form>

The action URL must point to a server that knows how to handle form submissions. When someone clicks "send," the browser makes a POST request to that URL with all the form data in the request body. The server receives it, processes it, and can then send an email based on that data.

CatchForm is that backend. You give each form a unique token, and the form's action points to CatchForm's endpoint. When data arrives, CatchForm validates it, stores it, and delivers it to your email inbox.

Step 1: Create a Form

Sign up for a free CatchForm account (no credit card required). You'll get a unique token for each form. Keep this token private — anyone with it can submit to your form.

During setup, provide the email address where you'd like to receive submissions. We'll send you a confirmation link.

Step 2: Add the HTML Form

Paste this code into your HTML page where you want the form to appear:

<form action="https://catchform.dev/f/YOUR-TOKEN"
      method="POST"
      style="display: flex; flex-direction: column; gap: 1rem; max-width: 400px;">

  <input type="hidden" name="_gotcha" value="">

  <div>
    <label for="email" style="display: block; margin-bottom: 0.25rem; font-weight: 500;">
      Email
    </label>
    <input type="email" id="email" name="email" required
           style="width: 100%; padding: 0.5rem; border: 1px solid #ddd; border-radius: 4px;">
  </div>

  <div>
    <label for="message" style="display: block; margin-bottom: 0.25rem; font-weight: 500;">
      Message
    </label>
    <textarea id="message" name="message" required rows="5"
              style="width: 100%; padding: 0.5rem; border: 1px solid #ddd; border-radius: 4px; font-family: inherit;"></textarea>
  </div>

  <button type="submit"
          style="padding: 0.5rem 1rem; background-color: #4f46e5; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: 600;">
    Send
  </button>

</form>

Replace YOUR-TOKEN with the token from your form's settings.

Step 3: What Happens After Submission

When someone clicks "send," their browser makes a POST request to CatchForm with the form data. Here's the journey that data takes behind the scenes:

  1. Form is located. CatchForm looks up your form using the token in the action URL. If the form doesn't exist or has been deactivated, you'll get a 404 error. This prevents submissions to forms that are no longer active.
  2. Plan limit is checked. Every plan has a monthly submission limit — 100 on Free, 1,000 on Starter and 10,000 on Pro. If your account has already reached this month's limit, the submission is rejected with a 429 (too many requests) error.
  3. Spam protection runs. CatchForm uses a honeypot field (the hidden input in your form named _gotcha) to catch bots. If a bot fills this field, the submission is rejected with a 422 error and marked as spam.
  4. Submission is stored. If all checks pass, CatchForm saves a copy of the submission in its database. This gives you a permanent record that you can view in your dashboard, even if your email filters send the message to spam.
  5. Email is sent. An email with all the form data is delivered to your inbox — but only if you've verified that email address. This prevents anyone from setting up a form that sends email to an arbitrary address. The email includes a "Reply-To" header set to the visitor's email address (detected from a field named email, Email, or e-mail, if its value is a valid address), so you can reply directly in your email client.
  6. Response is sent to the browser. If you configured a success redirect URL in your form's settings, the visitor's browser is redirected there. If no redirect was configured, a regular form submission from a browser leads to a thank-you page hosted by CatchForm, while a programmatic request (such as fetch() or curl) receives a JSON response with {"success": true}, which is useful for JavaScript-based forms that don't do a full page reload. You can also override the redirect URL per-submission by including a hidden input with name="_redirect", as long as it points to the same domain as your configured redirect.

How CatchForm Compares to Mailto Links

You might wonder why you need a form backend when you could just use a mailto: link. Here are the real differences:

Aspect Mailto: Link CatchForm (Form Backend)
Requires email client Yes — visitor must have a mail app No — works on any device
Visitor sends the email Yes — user clicks "send" in their client No — server sends automatically
Email is stored Only in visitor's Sent folder Yes — you have a permanent record
Spam filtering None — raw user input Yes — honeypot field, spam never reaches your inbox
Email address visible Yes — in page HTML No — only on the server
Validation None Email address verified before sending

In short: mailto: is a fallback for when you want to let someone email you directly. A form backend is the professional choice because it actually sends the email, stores it, and protects your inbox from spam.

CatchForm is not the only form backend, and mailto: is not the only thing worth comparing it with. If you are choosing between hosted services, we keep side-by-side pages on CatchForm vs Formspree and CatchForm vs FormSubmit — including the things each of them does that we do not.

Customization

Custom Field Names

Change the name attribute on any input to customize what you see in your email. Add as many fields as you need:

<input name="phone" type="tel">
<input name="company" type="text">
<textarea name="comments"></textarea>

Success Redirect

If you do not configure anything, a submission sent from a browser lands on a plain thank-you page hosted by CatchForm. To send visitors to a page on your own site instead, set the redirect URL when you create the form or later in its settings. If you want to override it per-submission (for A/B testing or multiple forms on one page):

<input type="hidden" name="_redirect" value="/thank-you">

The redirect URL must be on the same domain as your form's configured redirect URL. This protects against using CatchForm as a redirect service.

Spam Protection

The line <input type="hidden" name="_gotcha" value=""> is a honeypot field. Bots will try to fill it; if they do, we reject the submission as spam. Keep it in your form.

Common Patterns

Newsletter Signup

<form action="https://catchform.dev/f/YOUR-TOKEN" method="POST">
  <input type="hidden" name="_gotcha" value="">
  <input name="email" type="email" placeholder="your@email.com" required>
  <button type="submit">Subscribe</button>
</form>

Contact Form with File Upload

<form action="https://catchform.dev/f/YOUR-TOKEN" method="POST" enctype="multipart/form-data">
  <input type="hidden" name="_gotcha" value="">
  <input name="name" type="text" required>
  <input name="email" type="email" required>
  <textarea name="message" required></textarea>
  <input name="file" type="file" accept=".pdf,.jpeg,.png,.gif">
  <button type="submit">Send</button>
</form>

File uploads are available on the Starter and Pro plans. Remember to use enctype="multipart/form-data" when uploading files.

Get Started

Not sure how your host handles forms? See the Static site contact form guide for a host-by-host breakdown.

Ready to add a contact form? Sign up for free and get your first 100 submissions included.