All docs
4 min read

Plain HTML

No framework, no build, no JS. Drop a form on any page and you're done.

The four lines

<form action="https://formspring.io/f/r2EdO-orF-3S" method="POST">
  <input name="email" type="email" required />
  <textarea name="message" required></textarea>
  <button>Send</button>
</form>

That's it. The browser handles validation. Formspring accepts the POST, returns a 200 HTML page, you're done.

With a thank-you redirect

Add a hidden field. Formspring 303s the user to that URL after a successful submission:

<form action="https://formspring.io/f/r2EdO-orF-3S" method="POST">
  <input type="hidden" name="_redirect" value="https://example.com/thanks" />
  <input name="email" type="email" required />
  <textarea name="message" required></textarea>
  <button>Send</button>
</form>

The redirect target must be an absolute URL on a domain you've added to the form's allowlist (set in Form settings → Domains).

Honeypot

Add a hidden field bots will fill but humans won't. We drop submissions where it's not empty.

<form action="https://formspring.io/f/r2EdO-orF-3S" method="POST">
  <input type="text" name="_gotcha" tabindex="-1" autocomplete="off"
         style="position:absolute;left:-9999px;" aria-hidden="true" />

  <input name="email" type="email" required />
  <textarea name="message" required></textarea>
  <button>Send</button>
</form>

Don't use display: none — some bots ignore styles entirely or scrape the rendered DOM. Move the field offscreen instead.

Native validation

The browser handles required fields, email format, pattern matching, and min/max lengths.

<input name="email" type="email" required />
<input name="phone" type="tel" pattern="[0-9 +()-]{6,}" />
<input name="age" type="number" min="18" max="120" />
<textarea name="message" required minlength="10" maxlength="1000"></textarea>

The browser surfaces errors automatically; no JS. Add novalidate to the form if you want to skip browser validation and rely entirely on Formspring's server-side validation.

Multiple checkboxes / multi-select

Use the same name for related checkboxes. Formspring receives an array.

<fieldset>
  <legend>Interested in</legend>
  <label><input type="checkbox" name="interests[]" value="forms" /> Forms</label>
  <label><input type="checkbox" name="interests[]" value="webhooks" /> Webhooks</label>
  <label><input type="checkbox" name="interests[]" value="ai" /> AI features</label>
</fieldset>

The submission's payload.interests will be a JSON array.

File upload

<form action="https://formspring.io/f/r2EdO-orF-3S" method="POST" enctype="multipart/form-data">
  <input name="email" type="email" required />
  <input name="attachment" type="file" />
  <button>Send</button>
</form>

enctype="multipart/form-data" is required for file uploads; without it the browser sends only filenames, not bytes. Files are stored, scanned, and exposed as signed URLs in webhooks.

What plain HTML can't do

  • Inline error rendering (the user gets redirected on failure too unless you add JS).
  • Optimistic UI / loading state.
  • Any kind of multi-step flow.

For any of those, pick a framework recipe — Next.js, SvelteKit, Astro, or just vanilla React.

What's next