Can an HTML form post without any JavaScript?
Yes. A native form with action and method=POST sends a URL-encoded body, which the endpoint reads directly. JavaScript is optional and only changes how the response is handled.
Give a native <form> an action and a method and it already knows how to post. What it has been missing is somewhere to post to. This page is the whole integration: markup you can paste, the response the browser gets, and how to send the visitor to your own thank-you page afterwards.
Paste this, change the key in the action, and the form is connected. There is no script tag anywhere in it.
<form action="https://www.submitharbor.com/api/submit/sh_your_project_key" method="POST">
<label>
Your email
<input type="email" name="email" required />
</label>
<label>
Message
<textarea name="message" required></textarea>
</label>
<!-- Bots fill this in. People never see it. -->
<input type="text" name="website" tabindex="-1" autocomplete="off" hidden />
<button type="submit">Send</button>
</form>Two names are required and three are reserved. Everything else is yours — name them whatever your form needs and they arrive in the inbox under those names.
| Field | Rule |
|---|---|
| Required. Must contain a name, an @, and a dotted domain. | |
| message | Required. At least 3 characters after trimming. |
| Any other field | Optional. Stored as sent, trimmed, up to 5,000 characters. |
| website, _gotcha | Honeypots. If either is filled the submission is accepted and discarded. |
| _redirect | Optional. A URL on the submitting origin or the allow-list to return the browser to. |
Without JavaScript the browser navigates to whatever the endpoint returns, and by default that is a JSON response. Add a hidden _redirect field and a stored submission answers with a 303 to your page instead.
<input type="hidden" name="_redirect" value="https://example.com/thanks" />The target has to be on the origin the form posted from, or on the project's allow-list. An off-site URL is ignored rather than followed, so the field cannot be rewritten by someone else into an open redirect.
The redirect only applies to a submission that was actually stored. On the shared demo key nothing is stored, so the demo answers with JSON even when _redirect is present.
A hidden input is the whole defence, and it costs a visitor nothing — no puzzle, no third-party widget, no extra request.
<input type="text" name="website" tabindex="-1" autocomplete="off" hidden />_gotcha works the same way if you prefer that name. When either arrives populated the endpoint answers 200 with filtered: true and stores nothing, so the bot sees an ordinary success and moves on.
tabindex="-1" and autocomplete="off" keep the field away from keyboard users and password managers, so a real visitor cannot fill it by accident.
| Limit | Value | What happens at the edge |
|---|---|---|
| Request body | 64 KB | Larger declared payloads are rejected with 413. |
| Fields per submission | 20 | Counted after control fields are removed; 422 beyond it. |
| Characters per field | 5,000 | Values are trimmed first, then checked; 422 beyond it. |
| Field name | 1–50 characters | Letters, numbers, underscores, and hyphens only. |
| Submissions per minute | 20 per address, per endpoint | A fixed 60-second window, then 429. |
Worth reading before you build on it. These limits apply today.
Yes. A native form with action and method=POST sends a URL-encoded body, which the endpoint reads directly. JavaScript is optional and only changes how the response is handled.
By default the browser navigates to the endpoint's JSON response. Add a hidden _redirect field pointing at a page on your own site and a stored submission returns a 303 to it instead.
email and message. Every other field is optional and stored under the name you gave it, apart from website, _gotcha, and _redirect, which the endpoint consumes.