All resources
Static site forms

Astro Contact Form Without a Backend (2026)

Add a working contact form to any Astro site in minutes — no server, no API routes, no reCAPTCHA. Copy-paste HTML plus spam protection and email alerts.

The ShipMyForm team

· 3 min read

To add a contact form to an Astro site without a backend, point a normal HTML <form> at a hosted form endpoint and let it handle the submission. Astro builds to static files, so there's no server to receive the post yourself — a form backend is the piece that receives it, filters spam, and emails you. Here's the whole thing:

astro
---
// src/pages/contact.astro
---
<form action="https://shipmyform.com/f/YOUR_FORM_ID" method="POST">
  <label>
    Email
    <input type="email" name="email" required />
  </label>
  <label>
    Message
    <textarea name="message" required></textarea>
  </label>
  <button type="submit">Send message</button>
</form>

Replace YOUR_FORM_ID with the ID from your form backend and you have a working contact form. That's the five-minute version. The rest of this guide covers success handling, spam, and doing it with fetch if you want to stay on the page.

Don't want to hand-write the markup? Generate it — honeypot and Turnstile included — with the free contact form generator, then paste the result into your .astro page.

1. Create the form endpoint

You need a URL to send submissions to. With ShipMyForm, create a form and copy its endpoint — it looks like https://shipmyform.com/f/abc123. Every field's name attribute (email, message) becomes a field you receive.

2. Show a thank-you page

By default the browser follows the response to a thank-you page. Point it wherever you like with a hidden _redirect field:

astro
<form action="https://shipmyform.com/f/YOUR_FORM_ID" method="POST">
  <input type="hidden" name="_redirect" value="https://your-site.com/thanks" />
  <input type="email" name="email" required />
  <textarea name="message" required></textarea>
  <button type="submit">Send message</button>
</form>

Create src/pages/thanks.astro with a confirmation message and you're done — this works with zero JavaScript, which is the Astro way.

3. Submit without leaving the page (optional)

If you'd rather show an inline success state, submit with fetch and ask for JSON back. Astro ships almost no client JS, so add a tiny inline script:

astro
<form id="contact" action="https://shipmyform.com/f/YOUR_FORM_ID" method="POST">
  <input type="email" name="email" required />
  <textarea name="message" required></textarea>
  <button type="submit">Send</button>
  <p id="status" hidden>Thanks — we'll be in touch.</p>
</form>

<script>
  const form = document.getElementById("contact");
  form.addEventListener("submit", async (event) => {
    event.preventDefault();
    const res = await fetch(form.action, {
      method: "POST",
      body: new FormData(form),
      headers: { Accept: "application/json" },
    });
    if (res.ok) {
      form.reset();
      document.getElementById("status").hidden = false;
    }
  });
</script>

The Accept: application/json header is what makes the backend return { ok: true } instead of redirecting.

4. Block spam

Static contact forms get scraped and hit by bots, but you can stop most of them without a CAPTCHA. The simplest, zero-friction defense is a honeypot — a hidden field real people never fill. If it's filled, the submission is a bot.

Add a honeypot field the backend knows to check:

astro
<!-- visually hidden; keep it out of the tab order -->
<input type="text" name="_gotcha" tabindex="-1" autocomplete="off" style="display:none" />

ShipMyForm checks the honeypot and rate-limits submissions automatically, and you can turn on Cloudflare Turnstile if a form gets targeted — no reCAPTCHA puzzles for your visitors.

Keep secrets out of the client:

Everything here is safe to ship in a static build — there are no API keys in the page. The form endpoint is public by design and only accepts submissions from your allowed domains.

5. Get notified

Submissions land in an inbox, and you can turn on an email notification so every message hits your inbox. From there, route to Slack, Google Sheets, or a webhook without touching your Astro code.

Why not an Astro API route?

Astro can run server endpoints if you add an adapter and switch to server output. That's real work — and you still have to write spam filtering, storage, and email yourself. For a contact form, a hosted backend keeps your site static and skips all of that. If you're weighing the trade-off, read what a form backend is and when you need one.

Next steps

Frequently asked questions

Can you have a contact form on an Astro site?
Yes. Astro output is static by default, so you point a normal HTML form at a hosted form backend. The backend receives the submission and emails it to you — no server or API route needed.
Do I need Astro server output (SSR) for a contact form?
No. A hosted form backend works with a fully static Astro build. You only need SSR if you want to process the submission in your own server code.
How do I stop spam on an Astro contact form?
Add a hidden honeypot field and let the backend score submissions, then optionally enable Cloudflare Turnstile. ShipMyForm checks the honeypot and rate-limits submissions automatically.

Related guides