Troubleshooting

Most issues come down to an incorrect access key, a missing allowed domain, or expecting JSON when a browser redirect happens. This page walks you through the most common problems and how to fix them.

Step 1: Get a readable error message

When debugging, always send Accept: application/json so you receive a JSON error response instead of a redirect. This gives you the exact error message and HTTP status code.

debug.fetch.js
const res = await fetch("https://api.w3forms.com/submit", {
  method: "POST",
  headers: { Accept: "application/json" },
  body: new FormData(document.querySelector("form")),
});

const data = await res.json();
console.log(res.status, data);

Check the browser console for the status code and error message. Common status codes: 400 (bad request — missing key, invalid domain, quota exceeded), 405 (wrong HTTP method), 429 (rate limited).

Common errors

"Invalid access key" (400)

The access_key field is missing, misspelled, or the key does not match any form. Verify the hidden input is named exactly access_key (not accessKey or api_key). Copy the key directly from the dashboard — do not retype it manually.

"Domain not allowed" (400)

Your site's domain is not in the form's Allowed Domains list. Go to Form → Settings → Allowed Domains and add your domain (e.g., yoursite.com). Include all variants you use: www.yoursite.com and yoursite.com are treated as separate domains. localhost is allowed by default during development.

"Quota exceeded" (400)

You have reached your plan's monthly submission limit. New submissions are rejected until the next billing cycle. Check your usage in the dashboard and upgrade your plan if needed.

"Method not allowed" (405)

The form is using GET instead of POST. Ensure your form tag has method="POST". W3Forms only accepts POST requests.

"Rate limited" (429)

Too many requests from the same IP address in a short period. This is a protection against abuse. Wait a few seconds and try again. If you're testing rapidly, slow down between submissions.

Redirect vs JSON response

By default, a browser form POST receives a redirect response (303) to your configured success URL. If your JavaScript code expects JSON data, it will fail because it receives HTML instead.

Fix: Add Accept: application/json to your fetch headers. This tells W3Forms to return a JSON response instead of redirecting. See the Quick Start for a fetch example.

File upload issues

  • Files not received — Ensure your form has enctype="multipart/form-data". Without this, browsers send files as text, which fails.
  • File too large — Check your plan's file size limits. Free plans have lower limits than Pro and Business.
  • Using fetch — When sending files via JavaScript, use new FormData(form) as the body. Do not set the Content-Type header manually — the browser sets it automatically with the correct multipart boundary.

CORS errors

If you see a CORS error in the browser console, it usually means the request is being blocked before it reaches W3Forms. Common causes:

  • A browser extension or proxy is modifying the request headers.
  • You're setting Content-Type: application/json without actually sending JSON. For FormData, do not set Content-Type — the browser handles it.
  • Your domain is not in Allowed Domains. The API returns 400 which the browser reports as a CORS error if the error response lacks CORS headers.

Quick checklist

  • Hidden field named exactly access_key with a valid key.
  • Form uses method="POST".
  • Production domain added to Allowed Domains.
  • enctype="multipart/form-data" if uploading files.
  • Accept: application/json header if expecting JSON response.
  • Not manually setting Content-Type when using FormData.

Still stuck?

Check request and response formats in the API Reference, confirm your form matches the Quick Start, or email us at support@w3forms.com with your form ID and the error message.