Skip to main content

Contact form without page reload (fetch)

By Maxime Branger · Published on

Why add JavaScript

A classic HTML form sends the visitor to another page after submission. With fetch , the page does not change: you show the confirmation yourself, and the form is cleared. This tutorial starts from the form in the HTML contact form without PHP or a server (2026 tutorial) tutorial. If you do not have an AirMess URL yet, start there.

Step 1: the form

The form is the same, with an id to find it and a role="status" paragraph to hold the messages:

<form id="contact-form" action="https://airmess.fr/api/submit/YOUR_TOKEN" method="POST">
  <label for="name">Name</label>
  <input id="name" name="name" type="text" required>

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

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

  <button type="submit">Send</button>
  <p id="contact-status" role="status"></p>
</form>

Step 2: submit with fetch

Just before </body> :

<script>
  const form = document.querySelector('#contact-form');
  const status = document.querySelector('#contact-status');

  form.addEventListener('submit', async (e) => {
    e.preventDefault();
    const button = form.querySelector('button');
    button.disabled = true;
    status.textContent = 'Sending…';

    try {
      const res = await fetch(form.action, {
        method: 'POST',
        body: new FormData(form),
      });
      if (!res.ok) throw new Error(String(res.status));
      form.reset();
      status.textContent = 'Thank you, your message has been sent.';
    } catch {
      status.textContent = "Sending failed. Please try again in a moment.";
    } finally {
      button.disabled = false;
    }
  });
</script>

new FormData(form) sends all the form fields, including the token of a CAPTCHA if there is one. The role="status" makes screen readers read out the confirmation message, and disabling the button while sending prevents double submissions.

Without JavaScript (blocked script, loading error), the form still works: the browser falls back to a classic submission.

Troubleshooting

If fetch fails with a 403 error in the console, your domain is not in the form's list of allowed origins. Remember this for your local tests too. To block bots, turn on hCaptcha in the form settings.