Why migrate (the actual reasons)
People migrate from Formspree for three concrete reasons:
- You hit the 50/month free tier cap. Most personal sites blow through it after one Reddit / HN post.
- You don't want to pay $10/month for webhooks. Splitforms includes them free.
- You want better spam filtering. Formspree uses keyword filters; Splitforms uses AI classification (see this benchmark).
If none of those apply to you and your forms work fine, you don't need to migrate. Formspree is reliable software. The reason to switch is feature parity at much lower cost.
Step 1: Sign up for Splitforms (1 minute)
- Go to splitforms.com/login
- Enter your email, get the 6-digit code, paste it
- Copy the auto-generated access key from the dashboard
That's your authentication. You'll paste this into your form's HTML. No credit card, no plan to pick — the free tier is forever.
Step 2: Export Formspree submissions (1 minute)
Splitforms doesn't import historical data — it starts fresh. Before you cut over, save your past Formspree submissions:
- Open your Formspree dashboard
- Click your form
- Click Export (top right)
- Choose CSV, download
- Save the file somewhere safe (Drive, Dropbox, password manager)
You can keep your Formspree account active during the migration. Don't cancel it until you've verified Splitforms is receiving submissions.
Step 3: Update form HTML (2 minutes — the actual migration)
Find every place on your site that has a Formspree action URL. The pattern looks like:
<!-- BEFORE: Formspree -->
<form action="https://formspree.io/f/xyzabc123" method="POST">
<input type="text" name="name" required />
<input type="email" name="email" required />
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form>Change two things: the action URL, and add a hidden access_key input.
<!-- AFTER: Splitforms -->
<form action="https://splitforms.com/api/submit" method="POST">
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<input type="text" name="name" required />
<input type="email" name="email" required />
<textarea name="message" required></textarea>
<!-- Optional: spam honeypot -->
<input type="checkbox" name="botcheck" style="display:none" tabindex="-1" />
<button type="submit">Send</button>
</form>That's the entire HTML migration. Field names stay identical. name, email, message still mean the same thing. Reply-to, redirect, subject — same conventions.
If you have multiple forms
Find them all with grep:
# In your project root
grep -r "formspree.io" .
# Output:
# ./pages/contact.tsx: action="https://formspree.io/f/abc123"
# ./components/Footer.tsx: action="https://formspree.io/f/def456"
# ./public/contact.html: action="https://formspree.io/f/abc123"Update each one. Tip: if you have many forms, create one Splitforms form per Formspree form so each has its own access key, dashboard, and stats. Or use a single key with form names baked into a hidden form_id field — your call.
Step 4: Move webhooks and integrations (1 minute, if applicable)
If your Formspree form posts to Slack, Discord, Zapier, or a custom webhook, recreate that in Splitforms:
- Splitforms dashboard → Integrations → Webhooks
- Click Add webhook
- Paste the same URL you used in Formspree (Slack incoming webhook URL, etc.)
- Save
Webhooks are free on Splitforms. The signature header changes from X-Formspree-Signature to X-Splitforms-Signature. If you verify signatures on your webhook receiver, update that code:
// BEFORE: verifying Formspree signature
const sig = req.headers["x-formspree-signature"];
// AFTER: verifying Splitforms signature
const sig = req.headers["x-splitforms-signature"];
// HMAC scheme is the same: HMAC-SHA256 of body with shared secretStep 5: Test and cut over
- Open your live site, navigate to the form
- Submit a test message
- Check your inbox — within 5 seconds you should see the notification email
- Check your Splitforms dashboard at splitforms.com/dashboard/submissions — the submission should be there too
- Done. Real visitor submissions are now flowing to Splitforms.
You can leave your Formspree account active for 30 days as a safety net. After 30 days of confirmed working Splitforms submissions, cancel Formspree.
Field mapping cheat sheet
Most of Formspree's special fields work identically in Splitforms. The few exceptions:
| Formspree | Splitforms | Notes |
|---|---|---|
_subject | subject | Drop the underscore prefix |
_replyto | replyto | Drop the underscore prefix |
_next | redirect | Renamed |
_cc | (set in dashboard) | Configured per-form, not per-submission |
_format | (automatic) | Splitforms auto-detects JSON vs form-encoded |
_gotcha | botcheck | Honeypot field renamed |
If you don't use any of these, the migration is even simpler — you literally only change the action URL.
Gotchas to avoid
- Caching. If you deploy the new HTML but your CDN cache still serves the old form, traffic will keep going to Formspree until cache invalidates. Purge your CDN after deploy.
- Multiple forms with one key. If you use a single Splitforms access key across many forms, you can't see per-form stats. Either create one form per page in Splitforms, or use a hidden
form_idfield for filtering. - Test domain restrictions. If you set Allowed Domains in Splitforms' security settings, your localhost dev tests will be rejected. Either skip the restriction during development or include localhost in the allow-list.
- Don't cancel Formspree immediately. Wait 30 days. Some browsers cache form HTML; some users have stale tabs open. The cost of running both for a month is < $1.
What you save (typical numbers)
Annualized savings for typical usage tiers:
| Submissions/month | Formspree | Splitforms | Annual savings |
|---|---|---|---|
| 50 | $0 (free tier) | $0 (free tier) | $0 — but get more headroom |
| 500 | $10/mo Personal | $0 (free tier) | $120 |
| 2,000 | $10/mo Personal | $5/mo Pro | $60 |
| 5,000 | $40/mo Pro | $5/mo Pro | $420 |
| 15,000 | $40/mo Pro | $59 4-Year (avg $1.23/mo) | ~$465 |
Tech support / troubleshooting the cut-over
- Submissions still flowing to Formspree after the deploy. Your CDN cached the old HTML. Purge the page cache (Cloudflare, Vercel, Netlify) and reload in an incognito window.
- splitforms returns 401. Wrong access key, leading whitespace, or the key is locked to a different domain. Re-copy from the dashboard and check Allowed Domains.
- Webhook signature verification failing. The header changed from
X-Formspree-SignaturetoX-Splitforms-Signature. The HMAC scheme is the same; just update the header name in your verifier. - Honeypot suddenly catching real users. Formspree's
_gotchadefaults differ from splitforms'botcheck. Confirm the field name and addautocomplete="off"to dodge password managers. - Localhost dev rejected. Allowed Domains is set. Either disable it during dev or include
localhostin the allow-list.
Next steps and where to get help
- Side-by-side feature comparison: splitforms vs Formspree.
- If you are still evaluating: best free form backend services 2026.
- Deliverability check after migration: contact form not working.
- Docs and API contract: /docs, /api-reference.
- Plan, security, and EU residency questions: /faq.
FAQ
Will my form's field names change?
No. Formspree and Splitforms both pass through whatever field names you set in HTML. If your form has fields named `name`, `email`, `message`, those names stay identical. The only required change is the form's `action` URL and adding an `access_key` hidden input.
Do my existing past submissions migrate?
No — past submissions stay in Formspree (it's their data). Splitforms starts collecting fresh from the moment you switch the form's action URL. If you need historical data preserved, export from Formspree first (CSV download is on every plan) and keep a copy.
What about my Formspree webhooks / integrations?
Splitforms has free webhooks (Formspree paywalls them at $10/month) so you'll save money. You'll need to recreate webhook configs in the Splitforms dashboard — the URL syntax is the same, but the event signature header changes from `X-Formspree-Signature` to `X-Splitforms-Signature`. Update your webhook receiver to accept both during the migration window.
How long does the migration take?
About 5 minutes per form. The longest part is finding all the places on your site that reference your old Formspree URL. Use grep on your codebase: `grep -r 'formspree.io' .` will find them all.
Will deliverability change?
Splitforms uses your custom-configured SMTP (Gmail App Password, AWS SES, or your own server) so deliverability is whatever you configure. Formspree uses their own SMTP infrastructure which is reliable but you don't control. If anything, Splitforms gives you more control over deliverability.
Why migrate at all? Formspree works fine.
Three reasons most people migrate: (1) free-tier limit — Formspree gives 50/month vs splitforms' 1,000/month; (2) cost — Formspree's $10 plan covers 1,000 submissions, splitforms' $5 plan covers 5,000; (3) features — splitforms includes webhooks, AI spam classification, and MCP for AI agents on the free tier, all of which Formspree paywalls.
Will redirects, _next, _subject, _replyto still work?
Drop the underscore prefix and it works. _next becomes redirect, _subject becomes subject, _replyto becomes replyto, _gotcha becomes botcheck. The cheat sheet in this article covers every Formspree special field.
How do I roll back if something breaks?
Keep your Formspree account active during the migration window. If splitforms returns errors, change the form's action URL back to formspree.io/f/<id> in your HTML and redeploy. The data path is just an HTML attribute — there is no migration to unwind on either side.
Where do I get help mid-migration?
The /faq covers the most common cut-over issues. /docs and /api-reference document the splitforms request contract and webhook envelope. Email support@splitforms.com with the form URL and access key prefix if a submission silently fails.