How to Add an HTML Contact Form to Any Website

Last updated: March 2026

Every website needs a contact form. A portfolio, a small business site, or a landing page all need a way for visitors to reach you. A simple HTML contact form is the most direct solution.

The problem? Plain HTML forms don't send emails on their own. You need a backend to process submissions and deliver them to your inbox. In this guide, you'll learn how to add a working HTML contact form for your website using plain HTML and a form backend service. The contact form code is ready to copy and paste. No server-side code, no PHP, no Node.js required.

What you need

  • A website (static HTML, WordPress, Astro, Next.js, Carrd, anything)
  • A free FormWit account
  • 5 minutes

HTML form anatomy

Before jumping to code, here's what makes up an HTML contact form. Understanding each piece helps you customize it later.

The form element

The <form> tag wraps all your inputs. It has two critical attributes:

<form action="https://app.formwit.com/api/s/YOUR_FORM_ID" method="POST">
  ...
</form>
  • action - the URL where the form data gets sent. For a form backend, this is the service's endpoint.
  • method - always POST for contact forms. GET puts form data in the URL query string, which exposes it in browser history and server logs.

Labels and inputs

Each form field needs a <label> and an <input> (or <textarea>, or <select>). The label's for attribute must match the input's id:

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

Three attributes matter on every input:

  • id - connects the label to the input for accessibility. Clicking the label focuses the input.
  • name - the key used when the form data is submitted. If you forget name, that field's data never reaches the backend.
  • type - tells the browser what kind of input to render and what validation to apply.

The submit button

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

The type="submit" is technically the default, but being explicit is good practice. Avoid using <input type="submit">. A <button> element is more flexible because you can put HTML inside it (icons, spans for styling).

Input types relevant to contact forms

HTML5 provides input types that handle validation and mobile keyboard behavior for you. Here are the ones you'll use in contact forms:

type="text"

General purpose text input. Use for name, subject, company name, and any other free-text field.

<input type="text" name="name" required />

type="email"

Validates that the value looks like an email address (contains @, has a domain). On mobile, shows a keyboard with the @ symbol prominent.

<input type="email" name="email" required />

type="tel"

Shows a numeric keypad on mobile devices. Does not validate phone number format (phone formats vary too much internationally for a single regex to handle).

<input type="tel" name="phone" />

type="url"

Validates that the value is a URL. Mobile keyboards show "/" and ".com" keys. Useful for "Your website" fields.

<input type="url" name="website" placeholder="https://example.com" />

textarea

Multi-line text input for the message body. Not technically an <input> type, but essential for contact forms.

<textarea name="message" rows="5" required></textarea>

The rows attribute sets the initial visible height. Users can resize vertically unless you set resize: none in CSS (don't do that, it's annoying).

select (dropdown)

Useful for subject/department selection when you want to route messages:

<label for="department">Department</label>
<select id="department" name="department" required>
  <option value="">Choose one</option>
  <option value="sales">Sales</option>
  <option value="support">Support</option>
  <option value="general">General inquiry</option>
</select>

The empty first option with value="" combined with required forces the user to make a selection.

Hidden fields explained

Hidden fields submit data without showing anything to the user. They're useful for adding metadata to your form submissions.

<!-- Redirect after submission -->
<input type="hidden" name="redirect_to" value="https://yoursite.com/thank-you" />

<!-- Track which page the form was submitted from -->
<input type="hidden" name="source_page" value="pricing" />

<!-- Honeypot for spam (hidden via CSS, not type="hidden") -->
<input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off" />

Note the difference: the honeypot uses type="text" with style="display:none", not type="hidden". Most spam bots know to skip type="hidden" fields but will still fill in visible text inputs. Hiding the input with CSS tricks the bot into revealing itself.

FormWit recognizes two special hidden field names:

  • redirect_to - the URL to redirect to after submission
  • _gotcha - honeypot field, submissions with a value here get rejected

All other hidden fields get included in the submission data and notification email, so you can use them to pass along context like page source, campaign ID, or plan selection.

Step 1: Create the HTML form

Start with a standard HTML form. Here's a contact form with name, email, and message fields:

<form action="https://app.formwit.com/api/s/YOUR_FORM_ID" method="POST">
  <label for="name">Name</label>
  <input type="text" id="name" name="name" required />

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

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

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

Replace YOUR_FORM_ID with the endpoint ID from your FormWit dashboard.

Step 2: Set up FormWit

  1. Create a free FormWit account
  2. Click Create Form in your dashboard
  3. Copy the form endpoint URL
  4. Paste it into the action attribute of your HTML form

That's it. When someone submits the form, FormWit receives the data, stores it in your dashboard, and sends you an email notification.

Step 3: Add spam protection

FormWit includes built-in spam filtering on every plan. For extra protection, add a honeypot field:

<input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off" />

Add this inside your form. FormWit automatically rejects any submission where this field has a value.

Form validation with HTML5 attributes

HTML5 provides built-in validation that works in all modern browsers without any JavaScript:

required

The browser prevents submission until the field has a value. The user sees a browser-native error message.

<input type="text" name="name" required />

type-based validation

type="email" checks for a valid email format. type="url" checks for a valid URL. The browser handles the validation and shows an error message if the format is wrong.

minlength and maxlength

Restrict the length of text input. Useful for preventing empty-looking submissions or absurdly long spam messages.

<textarea name="message" required minlength="10" maxlength="5000"></textarea>

pattern

Validate against a regular expression. For example, requiring a phone number in a specific format:

<input type="tel" name="phone" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}"
  title="Format: 123-456-7890" />

The title attribute provides the error message shown when validation fails.

Combining validation attributes

Here's a fully-validated contact form using only HTML attributes:

<form action="https://app.formwit.com/api/s/YOUR_FORM_ID" method="POST">
  <label for="name">Name</label>
  <input type="text" id="name" name="name" required minlength="2" maxlength="100" />

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

  <label for="message">Message</label>
  <textarea id="message" name="message" required minlength="10" maxlength="5000"></textarea>

  <input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off" />

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

All validation happens in the browser before the form is submitted. No JavaScript needed.

Step 4: Style your form

The HTML form above is unstyled. Here's minimal CSS to make it look clean:

form {
  max-width: 500px;
  margin: 0 auto;
}

label {
  display: block;
  margin-bottom: 4px;
  font-weight: 600;
}

input, textarea, select {
  width: 100%;
  padding: 10px;
  margin-bottom: 16px;
  border: 1px solid #ccc;
  border-radius: 6px;
  font-size: 16px;
  font-family: inherit;
  box-sizing: border-box;
}

input:focus, textarea:focus, select:focus {
  outline: none;
  border-color: #4f46e5;
  box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15);
}

button {
  background: #4f46e5;
  color: white;
  padding: 12px 24px;
  border: none;
  border-radius: 6px;
  font-size: 16px;
  cursor: pointer;
}

button:hover {
  background: #4338ca;
}

Two things to note: font-size: 16px on inputs prevents the auto-zoom behavior in iOS Safari. box-sizing: border-box ensures inputs with padding don't overflow their container.

Step 5: Add a custom redirect (optional)

By default, FormWit shows a "Thank you" page after submission. To redirect users to your own thank-you page, add a hidden redirect_to field:

<input type="hidden" name="redirect_to" value="https://yoursite.com/thank-you" />

The redirect_to value must be a valid http or https URL. It is stripped from the stored submission data and overrides any redirect URL configured in the dashboard.

Common pitfalls

  • Missing name attributes: Every input needs a name attribute, or the data won't be submitted. Use name="email", not just id="email".
  • Using GET instead of POST: Always use method="POST" for contact forms. GET exposes form data in the URL.
  • Forgetting the action URL: Without the action attribute pointing to your form backend, the form submits to your own page and nothing happens.
  • No validation: Add required to mandatory fields and use type="email" for email inputs so browsers validate before submission.
  • Duplicate id attributes: If you have two forms on one page, each input's id must be unique across the entire page. Use prefixes like id="contact-name" and id="newsletter-email".
  • Forgetting for/id pairing: A <label> without a matching for attribute doesn't connect to its input. Screen readers won't associate them, and clicking the label won't focus the input.

AJAX submission (optional)

If you want to submit the form without a page reload, use the Fetch API:

const form = document.querySelector('form');

form.addEventListener('submit', async (e) => {
  e.preventDefault();
  const data = new FormData(form);

  const response = await fetch(form.action, {
    method: 'POST',
    body: data,
  });

  if (response.ok) {
    alert('Message sent!');
    form.reset();
  } else {
    alert('Something went wrong. Please try again.');
  }
});

Summary

Adding an HTML contact form to any website takes a few minutes:

  1. Write the HTML form with name, email, and message fields
  2. Point the action attribute to your FormWit endpoint
  3. Add a honeypot field for spam protection
  4. Use HTML5 validation attributes for client-side checks
  5. Style with CSS and optionally submit via AJAX

FormWit's free plan includes unlimited forms, 100 submissions per month, email notifications, and spam protection. Get started free.

Want to see how FormWit stacks up against other HTML form backends? Check our alternatives comparison for a full feature and pricing breakdown.

Related guides: Simple contact form · 5 ways to add a contact form · Send form submissions to email · Free contact form options · Spam protection methods · Copy-paste form templates

Frequently asked questions

What HTML do I need for a contact form?

At minimum: a <form> element with action and method="POST", input fields with name attributes for each piece of data you want to collect, and a submit button. Three fields (name, email, message) plus a honeypot for spam protection covers most use cases.

Do I need JavaScript for the form to work?

No. A plain HTML form with a method="POST" and action pointing to a form backend works without any JavaScript. The browser handles submission natively and redirects to a thank-you page. JavaScript is only needed if you want to submit without a page reload.

How do I add spam protection?

Add a hidden honeypot field: <input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off" />. Bots fill it in, humans never see it, and FormWit automatically rejects submissions where this field has a value. Combined with server-side rate limiting, this blocks most automated spam.

Want to skip the setup?

FormWit gives you a form endpoint in 60 seconds. Free plan, no credit card.

Create Free Form

Need a form fast?

Build one visually with our free HTML form generator — no coding required.

Try the Form Generator →

Connect your HTML form

Add a contact form to your site in 30 seconds. No backend code required.

Try FormWit Free