Guide
Astro contact form (no backend needed)
Astro renders to static HTML by default, which means an Astro contact form is just a plain HTML form with the right action attribute. You don't need a server endpoint or an Astro integration - paste the snippet into a .astro page and you're done.
The snippet
---
// src/pages/contact.astro
---
<form action="https://formhook.app/f/YOUR_API_KEY" method="POST">
<label>
Email
<input type="email" name="email" required />
</label>
<label>
Message
<textarea name="message" required></textarea>
</label>
<input type="text" name="_gotcha" tabindex="-1" autocomplete="off" hidden />
<input type="hidden" name="_redirect" value="https://example.com/thanks" />
<button type="submit">Send</button>
</form>How it works
Because Astro ships static HTML by default, there's nothing client-side to wire up. The form's action POSTs straight to formhook.app/f/YOUR_API_KEY, where YOUR_API_KEY comes from your form's settings in the Formhook dashboard. The _gotcha field is a honeypot - bots fill it, humans don't see it, and anything with content there is silently dropped. The _redirect field sends users to a thank-you page after a successful POST, and the URL is validated against your allowed-origins list.
Show a thank-you page after submitting
A static Astro form leaves the page when it is submitted, so create a page such as src/pages/thanks.astro and point a hidden _redirect input at it. Use the full URL, for example https://example.com/thanks. The value has to be an absolute URL whose origin is in the form's Allowed origins; otherwise Formhook ignores it and the visitor sees a JSON response. If you set site in astro.config.mjs, you can build the value with new URL("/thanks", Astro.site).
Show the result without leaving the page
To keep the visitor on the page, add a small <script> to the component that intercepts the submit event, sends the fields with fetch as JSON, and writes a message into a status element. Astro ships that script to the browser as it is, so no framework or island is needed. The pattern is shown in the Next.js guide and explained, with accessible status messages, in AJAX form submission. JSON submissions don't use _redirect.
Allowed origins for dev, previews and production
Add every origin the form is served from to Allowed origins, with exact scheme, host and port: http://localhost:4321 for astro dev, your production domain with https://, and the preview domain of your host if you test there. If a submission fails with origin_not_allowed, that list is the first place to look.
The same setup works on Cloudflare Pages, GitHub Pages, Netlify and Vercel, because the browser posts straight to Formhook and your host never sees the submission.
Using it from an Astro endpoint
Static pages need nothing else. If your site runs in server or hybrid mode and you'd rather send the submission from an endpoint or an Astro action, call Formhook from server code with an X-Auth-Token header, generated under your form's settings and kept in a server-only environment variable. Server requests carry no Origin header, so without that token they are rejected. Details are in the docs.
Spam and privacy
Keep the hidden _gotcha field: bots fill it and those submissions are dropped silently. Rate limits apply per IP and per form, and Cloudflare Turnstile is a per-form switch in the dashboard; this guide compares the options. For EU visitors, add a short notice under the form. The GDPR contact form guide has wording you can adapt.
What happens next
- Submission appears in your Formhook dashboard within a second.
- Push notification fires on every device you've enabled it on.
- Reply directly from the dashboard (Pro and above) without leaking your real email address.
Ship your Astro contact form today.
Sign up free, create a form, paste the API key. Five minutes.
Start freeFree tier: 5 forms · 250 submissions/month · No credit card.
Astro contact form - FAQ
Do I need an Astro integration or a server adapter?
Can I have multiple contact forms across different Astro pages?
How do I show a thank-you page after submission?
Guides for other frameworks
Migrating from Formspree? See how Formhook compares.