The short answer
Formspree and RG Forms both let a static site accept form submissions without a server, and they differ mainly in where the data lives and how much product sits around it. Formspree is a mature, full-featured platform: submissions are stored in Formspree's system, you manage them in its dashboard, and it offers plain HTML form posts without JavaScript, file uploads, integrations and workflow features on paid plans. RG Forms stores submissions in a Google Sheet inside your own Google account, via an Apps Script endpoint it provisions for you, and is free with no paid tier — but it has fewer features and requires JavaScript. Choose Formspree for a full product with support behind it; choose RG Forms when data ownership and zero cost matter more than breadth of features.
Side by side
| Formspree | RG Forms | |
|---|---|---|
| Where submissions are stored | Formspree’s platform, viewable in their dashboard | A Google Sheet in your own Drive |
| Cost | Free tier with a monthly submission allowance; paid plans for more volume and features | Free — there’s no server for anyone to bill for |
| Works without JavaScript | Yes — a plain action= POST with a redirect is supported | No — the integration is a fetch call |
| File uploads | Yes, on paid plans | No — text fields only |
| Integrations | Slack, Zapier, webhooks, CRM connections and more | Anything that reads a Google Sheet; the script itself is editable |
| Spam protection | Built-in filtering plus captcha options | Honeypot, plus Cloudflare Turnstile verified server-side |
| Notification email sends from | Formspree’s infrastructure | Your own Google account |
| Support | A company with a support team | GitHub issues and the docs |
| If the vendor goes away | Export your submissions and migrate | Nothing changes — the endpoint is in your account |
The architectural difference
Formspree works the way almost every SaaS works: your form posts to their servers, they store it, they show it to you, they email you. That’s a sound model and it’s what makes the richer features possible — dashboards, workflows, integrations and file handling all need a platform behind them.
RG Forms has no servers to put anything on. When you sign in with Google, it creates a Drive folder, a Google Sheet and an Apps Script web app in your account, and hands you the URL. Submissions go from your visitor’s browser to your script to your spreadsheet. We never see them, which is simultaneously the main feature and the main limitation.
Choose Formspree when
You need it to work without JavaScript. Formspree supports a plain HTML form post with a redirect. RG Forms doesn’t — a fetch is required.
You need file uploads. Résumés, photos, documents. RG Forms handles text only.
You want a dashboard for a non-technical client. A spreadsheet is a fine interface for most people, but a purpose-built submissions inbox with search, tagging and export is better if that’s the daily workflow.
You want integrations that already exist. Slack notifications, CRM pushes and Zapier connections are configuration in Formspree; with RG Forms you’d be editing Apps Script or building on top of the Sheet.
You want a support contract. There’s a company on the other end with an incentive to answer.
Choose RG Forms when
The data has to belong to the site owner. Handing a client a Google Sheet in their own Drive is a cleaner boundary than an account on a service you control — and it survives you.
Cost has to be zero, permanently. Not a free tier with a submission ceiling — free because nobody is hosting anything on your behalf.
You want no vendor dependency at all. The endpoint is an Apps Script deployment in your account with no reference to rgforms.com. If this site vanished tonight, your form would still be taking submissions tomorrow.
Your team lives in spreadsheets. Sorting, filtering, adding a “replied?” column, sharing with a colleague, charting by month — all free, all familiar, no export step.
What the RG Forms integration looks like
<form id="contact-form">
<label>Name <input name="name" required /></label>
<label>Email <input type="email" name="email" required /></label>
<label>Message <textarea name="message" required></textarea></label>
<!-- Honeypot: humans never see it, bots fill it in -->
<input type="text" name="_hp" tabindex="-1" autocomplete="off"
style="position:absolute;left:-9999px" aria-hidden="true" />
<button type="submit">Send</button>
<p id="form-status" role="status"></p>
</form>
<script>
const ENDPOINT = "https://script.google.com/macros/s/AKfycb.../exec";
const form = document.getElementById("contact-form");
const status = document.getElementById("form-status");
form.addEventListener("submit", async (event) => {
event.preventDefault();
status.textContent = "Sending…";
const res = await fetch(ENDPOINT, {
method: "POST",
// text/plain avoids the CORS preflight Apps Script can't answer
headers: { "Content-Type": "text/plain" },
body: JSON.stringify({
tab: "contact",
fields: Object.fromEntries(new FormData(form)),
}),
});
const data = await res.json();
status.textContent =
data.result === "success" ? "Thanks — we'll be in touch." : "Something went wrong.";
if (data.result === "success") form.reset();
});
</script>Common questions
Can I use both?
Yes, and it’s not unusual — a job application form with file uploads on one service, and a contact form writing to a spreadsheet on the other. They’re just two endpoints.
Is RG Forms free because it’s a trial?
No. There is no paid tier and no infrastructure to pay for — your endpoint runs on Google’s free Apps Script quota inside your own account. That’s the whole business model, or lack of one.
How do I migrate from Formspree?
Export your existing submissions from their dashboard, create an RG Forms project with matching fields, paste the exported rows into the Sheet, then swap the endpoint URL in your form. The markup barely changes.
Which handles spam better?
Formspree has years of aggregated signal across many sites, which is a genuine advantage for filtering. RG Forms relies on a honeypot plus server-side Turnstile verification — effective, and it happens inside your own script, but it isn’t learning from anyone else’s traffic.
More answers in the full FAQ.