Get your free splitforms access key
Sign up at splitforms.com, verify your email, and copy your access key from the dashboard. No credit card required.
Contact form · Astro
Astro's zero-JS-by-default philosophy pairs perfectly with the splitforms endpoint. Use a pure HTML form for static pages, an Astro Action for SSR, or a React/Vue/Svelte island for client-side interactivity. Same backend, three patterns, zero hydration cost when you don't need it.

No server, API route, or SDK. Your Astro form posts straight to one endpoint.
Every submission is emailed to you and saved to a searchable dashboard — spam filtered before it reaches you.
It's your own Astro markup and styles. Splitforms is only the backend, so nothing constrains how the form looks.
Copy-paste ready
Replace YOUR_ACCESS_KEY with the key from your dashboard — that's the whole integration. No SDK to install, no build step, just the astro you already write.
---
const ACCESS_KEY = import.meta.env.PUBLIC_SPLITFORMS_KEY;
---
<form action="https://splitforms.com/api/submit" method="POST">
<input type="hidden" name="access_key" value={ACCESS_KEY} />
<input type="text" name="name" placeholder="Name" required />
<input type="email" name="email" placeholder="Email" required />
<textarea name="message" placeholder="Message" required />
<input type="checkbox" name="botcheck" style="display:none" tabindex="-1" />
<button type="submit">Send</button>
</form>How to add it
To add a contact form to a Astro website you need three things: a free splitforms access key, the astro snippet above, and your key pasted into it. No backend, server, or SDK — the form posts to one URL and every submission lands in your inbox and dashboard.
Sign up at splitforms.com, verify your email, and copy your access key from the dashboard. No credit card required.
Copy the Astro code example into your project and replace YOUR_ACCESS_KEY with the key from step 1.
Submissions arrive in the splitforms dashboard within seconds. Free includes owner email notification attempts; Pro adds Slack, Discord, Sheets, or any signed webhook URL.
Where submissions go
Every submission is emailed to you and saved to a searchable dashboard — spam filtered before it ever reaches you. Search, export to CSV, or forward it to a webhook or Slack on Pro.

No backend needed
Your Astro form posts standard FormData to one URL. Splitforms validates the access key, runs its spam checks, and forwards it to your email — so there's no server, API route, or database for you to build or maintain.

Best practices
The difference between a form that works in the demo and one that survives launch traffic — the production-tested defaults, in priority order.

How SplitForms works
splitforms receives the submission, filters spam, saves it to your dashboard and emails you — then, on paid plans, sends it on to your webhooks and integrations. No backend infrastructure to build.

Point your form to your unique SplitForms endpoint. That's it.

We instantly capture and organize every submission in your inbox.

Send data to email, spreadsheets, CRMs, webhooks, and 7,000+ apps.

No credit card required. Set up in under 60 seconds.
Connect & automate
On paid plans, submissions can also go to Slack, Discord, Google Sheets, Notion, Airtable, Zapier or any signed webhook — and splitforms works on the platforms you build on, from WordPress and Shopify to Next.js. With Stripe connected, your forms can take payments too.

Questions
Paste the snippet above into any .astro page or component. Set PUBLIC_SPLITFORMS_KEY in your .env file. That's it — no install, no astro:integrations, no adapter changes.
Yes — both. In SSG (output: 'static') the form posts directly to splitforms.com from the browser. In SSR (output: 'server' or 'hybrid') you can additionally use Astro Actions to keep the key server-side. Pick whichever fits.
If you're using Astro Actions, render result?.error?.message from Astro.getActionResult(actions.contact). A pure HTML submission uses splitforms's built-in error page; use fetch or an Astro Action when you need a custom inline error state.
Yes. Build the form as a React/Vue/Svelte component, hydrate with client:visible or client:idle, and use the framework-specific snippet from the matching /forms/<framework> page.
Add a hidden redirect field pointing at /thanks for a native POST — splitforms sends the browser there after success, free on every plan — or set a default in Dashboard → Form settings → Redirect for when no hidden field is present. With Astro Actions, render success state from result.data or navigate in your action instead.
No. The default snippet uses zero JavaScript — it's a vanilla <form action method=POST>. JavaScript only runs if you choose the island pattern or wire up custom client-side validation.
Astro mirrors Vite's env-var convention: only variables prefixed with PUBLIC_ are exposed to client-side code (and to .astro files when output: 'static'). If you write import.meta.env.SPLITFORMS_KEY, you'll get undefined at build time. Rename to PUBLIC_SPLITFORMS_KEY.
If you wrap the form in <MyForm client:load />, you ship a full React/Preact runtime just for one form. Use client:visible (load when scrolled into view) or client:idle (load after main thread is free) instead. For zero-JS forms, skip the island entirely and use a plain HTML form action.
If your action throws, Astro 5's behavior is to render an error page rather than return the error to your form. Wrap the splitforms fetch in try/catch and return { success: false, message } from the action — your form component can then render the message.
If you've enabled <ViewTransitions /> in your layout, navigating to /contact and back may re-mount the form mid-submission. Add data-astro-reload to the form's submit anchor or guard with if (status === 'loading') return at the top of your handler.
If output: 'static' in astro.config.mjs, you can't have a server endpoint at all — your form must POST directly to splitforms.com. That's the recommended setup. Switch to output: 'server' or 'hybrid' only if you genuinely need a server-side proxy.
Astro requires the --- fence at the top of .astro files for any frontmatter (imports, Astro.props, env reads). If you write const accessKey = import.meta.env.PUBLIC_SPLITFORMS_KEY; without the surrounding fence, Astro treats the line as plain text in the rendered HTML — you'll see the JavaScript leak into the page above your form. The build doesn't error; it just renders nonsense. Always wrap any logic in --- and reference values via {accessKey} in the template body.
Astro's whole pitch is shipping zero JavaScript by default. A native contact form on Astro means either (a) building a form with no submission target — useless — or (b) standing up an API endpoint via output: 'server' or 'hybrid', which means writing a Node/Bun/Deno handler, picking an email provider, writing your own honeypot logic. Astro 5 added typed Actions, but they're a wrapper around the same underlying fetch — you still deliver the email yourself. The result: every Astro contact-form tutorial ends with 'now configure SendGrid'. Splitforms is the SendGrid-replacement that doesn't require an account, an API key for the email provider, or DNS records for SPF/DKIM.
Astro deploys cleanly to Vercel, Netlify, Cloudflare Pages, GitHub Pages, and any static host with output: 'static'. For Astro Actions (Pattern B), you need output: 'server' or 'hybrid' and a matching adapter (@astrojs/vercel, @astrojs/netlify, @astrojs/cloudflare). On Cloudflare Pages with the Cloudflare adapter, the Action runs in a Worker — keep the splitforms fetch tight (no extra proxying) to stay under the 10ms CPU budget on the free plan. The PUBLIC_ prefix is mandatory for env vars exposed to client-rendered .astro files; vars without it are silently undefined. Lock the key to your *.pages.dev and custom domain.
Simple pricing
Free is $0 for 500 submissions in total (a one-time allowance). Paid plans are metered monthly: Starter is $1/month for 1,000, Pro is $5/month for 5,000, and the 3-Year plan is $59 for the first three years, then $59/year, for 15,000 a month.
For side projects and indie devs.
For builders who want every paid feature for $1/month.
For agencies and growing products.
Pay $59. 3 years sorted.
No credit card required on Free • Cancel anytime