splitforms.com
guide · ajax submission

Submit Form with AJAX — Working Code for 2026

Submit a form via AJAX (no page reload) using vanilla JS fetch — and the equivalent jQuery $.ajax for legacy codebases. Both POST to splitforms's free /api/submit endpoint.

html
<form id="contact">
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
  <input name="name" required />
  <input name="email" type="email" required />
  <textarea name="message" required></textarea>
  <button type="submit">Send</button>
</form>
<p id="status"></p>

<script>
const form = document.getElementById("contact");
const status = document.getElementById("status");

form.addEventListener("submit", async (e) => {
  e.preventDefault();
  status.textContent = "Sending…";

  try {
    const res = await fetch("https://splitforms.com/api/submit", {
      method: "POST",
      body: new FormData(form),
    });
    const data = await res.json();
    status.textContent = data.success ? "Thanks!" : (data.message || "Error.");
    if (data.success) form.reset();
  } catch (err) {
    status.textContent = "Network error.";
  }
});
</script>

AJAX form submission means intercepting the form's native submit event with JavaScript, POSTing the form data via fetch (or XMLHttpRequest historically), and updating the DOM with the response — all without a page reload. The user sees an inline success or error message rather than the browser navigating to a new page.

Vanilla JS does this in 15 lines. `addEventListener('submit')` catches the submit; `e.preventDefault()` blocks the native form submission; `new FormData(form)` serializes the form fields; `fetch('/api/submit', { method: 'POST', body: formData })` POSTs them. Await the response, parse the JSON, update the status element. Done.

jQuery's `$.ajax` is the legacy equivalent — same mechanics, different syntax. If your codebase already uses jQuery, the jQuery version is fine. If you're starting fresh, use fetch — no dependency, native browser support since ~2017.

splitforms's `/api/submit` returns JSON: `{ success: true, message: 'Submission received' }` on success, `{ success: false, message: '...', code: '...' }` on error. Your UI logic is just `if (data.success) { ... }`. CORS headers are permissive so cross-origin POSTs from any frontend work without preflight gymnastics.

jQuery $.ajax equivalent (for legacy codebases)

javascript
$("#contact").on("submit", function (e) {
  e.preventDefault();
  $("#status").text("Sending…");

  $.ajax({
    url: "https://splitforms.com/api/submit",
    method: "POST",
    data: new FormData(this),
    processData: false,
    contentType: false,
  }).done(function (data) {
    $("#status").text(data.success ? "Thanks!" : (data.message || "Error."));
    if (data.success) $("#contact")[0].reset();
  }).fail(function () {
    $("#status").text("Network error.");
  });
});

How to set this up

Step 01

Intercept the submit event

form.addEventListener('submit', handler) — call e.preventDefault() to block native submission.

Step 02

Serialize fields with FormData

new FormData(form) collects all named fields. No manual serialization required.

Step 03

POST via fetch

fetch(url, { method: 'POST', body: formData }) — fetch sets the correct Content-Type automatically.

Step 04

Update UI from the response

await res.json(), check data.success, render inline status message. Form.reset() on success.

15 lines of vanilla JS, no library, inline status, no page reload.

Frequently asked questions

How do I submit a form using AJAX in 2026?

Use fetch with a FormData body. Add a submit listener that calls e.preventDefault, then `fetch(url, { method: 'POST', body: new FormData(form) })`. ~15 lines of vanilla JS, no jQuery needed.

Why not just use jQuery $.ajax?

fetch is native since Chrome 42 / Firefox 39 (2015). It removes a 90KB dependency, has a cleaner Promise-based API, and is the modern standard. Use $.ajax only if your existing codebase already requires jQuery.

Do I need to set a Content-Type header?

No. fetch with a FormData body sets multipart/form-data automatically, including the boundary string. If you set it manually you'll break the boundary.

How do I handle CORS errors when submitting via AJAX?

Check that the backend allows your origin. splitforms's /api/submit sends Access-Control-Allow-Origin: *, so cross-origin POSTs from any frontend work. If you see CORS errors, you're probably using the wrong URL or your backend doesn't allow your origin.

How do I show a progress bar for file uploads?

fetch doesn't support upload progress (yet). Use XMLHttpRequest if you need it: xhr.upload.addEventListener('progress', e => ...). For typical contact forms with no files, fetch is fine.

How do I handle the response after AJAX submit?

splitforms returns JSON: { success, message, submission_id }. Parse with res.json(), check data.success, render an inline message. Don't redirect — that defeats the no-reload UX.

Related guides

AJAX submission

Submit Form with JavaScript — Vanilla JS Reference

HTML forms

HTML Form — How to Build and Submit Forms in HTML

HTML forms

HTML Form Action — What It Does and How to Use It

Ship the form, not the backend.

Free for 1,000 submissions/month. Email delivery, AI spam filtering, signed webhooks, real dashboard — all on the free plan. No credit card.

Get a free access key →