# Batas Netlify Forms: apa yang terjadi di 100 kiriman, dan jalan keluarnya

> Paket Netlify lama menghitung kiriman formulir per situs dan meng-upgrade Anda otomatis, dan paket kredit bisa menjeda situs, jadi pindahkan formulir ke backend.

Terbit 2026-10-25 · https://ikiform.com/id/guides/website-builder-forms/netlify-forms-limit

Di paket lama Netlify, setiap situs mendapat 100 kiriman formulir per bulan, dan melewatinya meng-upgrade situs ke level Forms berbayar secara otomatis. Di paket berbasis kredit untuk akun yang dibuat sejak September 2025, formulir gratis, tetapi tim gratis yang kehabisan kredit akan dijeda semua situsnya, termasuk formulir. Memindahkan formulir ke Ikiform berarti menghapus atribut Netlify dan mengatur `action`, di HTML biasa atau framework apa pun.

## Apa yang berbeda di Netlify

Netlify bukan site builder; ia host dengan formulir bawaan. Itu membentuk batasnya sekaligus jalan keluarnya. Batas mana yang berlaku tergantung kapan akun Anda dibuat:

| Akun | Apa kata dokumentasi Netlify | Apa artinya bagi formulir yang ramai |
| --- | --- | --- |
| Paket lama, dibuat sebelum 4 September 2025 | Forms Level 0 mencakup 100 kiriman dan 10 MB upload per situs per bulan. Melewatinya meng-upgrade situs ke Forms Level 1, dengan 1.000 kiriman, ditagih di akhir siklus penagihan. Setelah itu, paket penggunaan tambahan menambah 500 sekaligus | Gelombang spam bisa memindahkan situs ke level berbayar tanpa ada yang memutuskannya. Di tier gratis lama, mencapai batas menjeda setiap situs di akun |
| Paket berbasis kredit, dibuat sejak saat itu | Kiriman formulir gratis dan tanpa batas, tanpa level | Formulirnya sendiri tidak berbiaya. Tetapi saat tim gratis menghabiskan kredit bulanannya, Netlify menjeda semua proyeknya, dan proyek yang dijeda tidak menerima kiriman formulir |

Dokumentasi Netlify sendiri jelas menyatakan upgrade lama terjadi otomatis dan Anda tidak bisa turun lagi selama penggunaan di atas level yang lebih rendah. Periksa jenis paket tim Anda dan penggunaan formulir situs di dashboard Netlify sebelum memutuskan apa pun.

Alasan kedua orang pindah tidak ada hubungannya dengan angka. Netlify Forms bekerja dengan membaca HTML yang Anda deploy:

- Formulir ditemukan saat deploy. Formulir yang dirender React, Vue, atau Svelte tidak ada di HTML itu, jadi Anda menyimpan salinan statis tersembunyi agar ditemukan build, dan mengirim ke sana dengan field `form-name`.
- Dengan Next.js, adapter OpenNext butuh salinan itu sebagai file statis di `public/`, dan post harus pergi ke file statis itu, bukan ke halaman Next.js. Build gagal jika `data-netlify` muncul di kode React tanpa salinan itu.
- Kiriman harus urlencoded atau multipart. JSON tidak diterima.
- Formulir hanya berfungsi selama situs di-deploy di Netlify. Pindah host berarti memindahkan formulir.

Diagram: Bagaimana penggunaan formulir situs Netlify lama naik dalam sebulan, dan apa yang diubah dengan mengirim ke Ikiform

1. Di paket lama, situs memulai bulan di Forms Level 0 dengan 100 kiriman termasuk.
2. Kiriman ke-101 tiba. Dokumentasi penggunaan Netlify menggambarkan penggunaan situs, jadi lonjakan spam bisa menjadi pendorongnya melewati batas.
3. Netlify meng-upgrade situs ke Forms Level 1, dengan 1.000 kiriman, dan menagihnya di akhir siklus.
4. Setelah Level 1, paket penggunaan tambahan menambah 500 kiriman sekaligus.
5. Dengan formulir mengirim ke Ikiform, halaman tetap di Netlify tetapi post pergi ke endpoint Ikiform.
6. Netlify Forms tidak pernah menerima post, jadi tidak ada yang perlu dihitung atau di-upgrade.

Hosting tetap di Netlify. Hanya tujuan formulir yang pindah, dan bersama itu penghitungannya.

## Pindahkan formulir, per stack

Sebelum mengubah kode apa pun, buat satu formulir Ikiform per nama formulir Netlify dan atur **Honeypot field**-nya ke `bot-field`. Dengan begitu input tersembunyi yang sudah ada tetap berfungsi sebagai honeypot, tanpa ganti nama. Pilih stack Anda:

**HTML**

HTML biasa di Netlify butuh perubahan paling sedikit. Hapus atribut Netlify dan input `form-name`, arahkan `action` ke endpoint, dan pindahkan path halaman terima kasih ke `_redirect` sebagai URL lengkap. Input `bot-field` tetap sebagai honeypot Anda.

**Sebelum** (`contact.html`)

```html
<form name="contact" method="POST" action="/thanks" data-netlify="true" netlify-honeypot="bot-field">
  <input type="hidden" name="form-name" value="contact" />
  <p hidden><input name="bot-field" /></p>
  <label>Email <input type="email" name="email" required /></label>
  <label>Topic
    <select name="topic">
      <option value="question">A question</option>
      <option value="bug">Something is broken</option>
      <option value="work">Working together</option>
    </select>
  </label>
  <label>Message <textarea name="message" required></textarea></label>
  <button type="submit">Send</button>
</form>
```

**Sesudah** (`contact.html`)

```html
<form method="post" action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx">
  <input name="bot-field" type="text" tabindex="-1" autocomplete="off" hidden />
  <label>Email <input type="email" name="email" required /></label>
  <label>Topic
    <select name="topic">
      <option value="question">A question</option>
      <option value="bug">Something is broken</option>
      <option value="work">Working together</option>
    </select>
  </label>
  <label>Message <textarea name="message" required></textarea></label>
  <input type="hidden" name="_redirect" value="https://your-site.netlify.app/thanks" />
  <button type="submit">Send</button>
</form>
```

**Next.js**

Di Netlify, formulir Next.js hanya berfungsi dengan Netlify Forms lewat salinan statis di `public/`, seperti `public/__forms.html`, yang menjadi tujuan kiriman komponen Anda. Hapus file itu, hapus pengaturan `NETLIFY_NEXT_VERIFY_FORMS` jika ada, dan kirim dari komponen ke Ikiform. Formulir juga bisa mengirim tanpa JavaScript, berkat `action`-nya.

`app/contact/contact-form.tsx`:

```tsx
"use client";

import { type FormEvent, useState } from "react";

const ENDPOINT = "https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx";

export function ContactForm() {
  const [state, setState] = useState<"idle" | "sending" | "sent">("idle");
  const [error, setError] = useState("");

  async function onSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setState("sending");
    setError("");
    try {
      const response = await fetch(ENDPOINT, {
        method: "POST",
        headers: { Accept: "application/json" },
        body: new FormData(event.currentTarget),
      });
      const result = await response.json();
      if (result.ok) return setState("sent");
      setError(result.error.fields?.message?.[0] ?? result.error.fields?.email?.[0] ?? result.error.message);
    } catch {
      setError("Couldn't send. Check your connection and try again.");
    }
    setState("idle");
  }

  if (state === "sent") return <p role="status">Thanks. We read every message and reply within a day.</p>;

  return (
    <form action={ENDPOINT} method="post" onSubmit={onSubmit}>
      <input name="bot-field" type="text" tabIndex={-1} autoComplete="off" hidden />
      <label htmlFor="email">Email</label>
      <input id="email" name="email" type="email" required />
      <label htmlFor="topic">Topic</label>
      <select id="topic" name="topic" defaultValue="question">
        <option value="question">A question</option>
        <option value="bug">Something is broken</option>
        <option value="work">Working together</option>
      </select>
      <label htmlFor="message">Message</label>
      <textarea id="message" name="message" required />
      {error ? <p role="alert">{error}</p> : null}
      <button disabled={state === "sending"}>{state === "sending" ? "Sending" : "Send"}</button>
    </form>
  );
}
```

**Astro**

Halaman Astro statis sama sekali tidak butuh JavaScript. Hapus `data-netlify` dari formulir, atur endpoint sebagai `action`, dan susun redirect dari `site` di `astro.config.mjs`. Halaman bisa tetap di-prerender.

`src/pages/contact.astro`:

```astro
---
const endpoint = "https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx";
const thanksUrl = new URL("/thanks", Astro.site).href;
---

<form method="post" action={endpoint}>
  <input name="bot-field" type="text" tabindex="-1" autocomplete="off" hidden />
  <label for="email">Email</label>
  <input id="email" name="email" type="email" required />
  <label for="topic">Topic</label>
  <select id="topic" name="topic">
    <option value="question">A question</option>
    <option value="bug">Something is broken</option>
    <option value="work">Working together</option>
  </select>
  <label for="message">Message</label>
  <textarea id="message" name="message" required></textarea>
  <input type="hidden" name="_redirect" value={thanksUrl} />
  <button>Send</button>
</form>
```

**TanStack Start**

Aplikasi TanStack Start di Netlify merender formulir di React, yang tidak bisa dilihat deteksi saat deploy Netlify. Kirim lewat server function, dan buang salinan statis tersembunyi. Atur `IKIFORM_SECRET_KEY` di environment variable situs di Netlify. Function meneruskan header `Origin` dari browser, jadi post dari `localhost` dihitung sebagai uji gratis sebelum workspace Anda punya paket.

`src/routes/contact.tsx`:

```tsx
import { createFileRoute } from "@tanstack/react-router";
import { createServerFn, useServerFn } from "@tanstack/react-start";
import { getRequestHeader } from "@tanstack/react-start/server";
import { type FormEvent, useState } from "react";

const sendMessage = createServerFn({ method: "POST" })
  .validator((data: unknown) => {
    if (!(data instanceof FormData)) throw new Error("Expected form data");
    return {
      email: String(data.get("email") ?? "").trim(),
      topic: String(data.get("topic") ?? "question"),
      message: String(data.get("message") ?? "").trim(),
      "bot-field": String(data.get("bot-field") ?? ""),
    };
  })
  .handler(async ({ data }) => {
    const origin = getRequestHeader("origin");
    const response = await fetch("https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx", {
      method: "POST",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
        Authorization: `Bearer ${process.env.IKIFORM_SECRET_KEY}`,
        ...(origin ? { Origin: origin } : {}),
      },
      body: JSON.stringify(data),
    });
    const result = await response.json();
    return result.ok ? { sent: true, error: "" } : { sent: false, error: String(result.error.message) };
  });

export const Route = createFileRoute("/contact")({ component: Contact });

function Contact() {
  const send = useServerFn(sendMessage);
  const [state, setState] = useState({ sent: false, error: "" });
  const [pending, setPending] = useState(false);

  async function onSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setPending(true);
    try {
      setState(await send({ data: new FormData(event.currentTarget) }));
    } catch {
      setState({ sent: false, error: "Couldn't send. Try again." });
    } finally {
      setPending(false);
    }
  }

  if (state.sent) return <p role="status">Thanks. We read every message and reply within a day.</p>;

  return (
    <form method="post" onSubmit={onSubmit}>
      <input name="bot-field" type="text" tabIndex={-1} autoComplete="off" hidden />
      <label htmlFor="email">Email</label>
      <input id="email" name="email" type="email" required />
      <label htmlFor="topic">Topic</label>
      <select id="topic" name="topic" defaultValue="question">
        <option value="question">A question</option>
        <option value="bug">Something is broken</option>
        <option value="work">Working together</option>
      </select>
      <label htmlFor="message">Message</label>
      <textarea id="message" name="message" required />
      {state.error ? <p role="alert">{state.error}</p> : null}
      <button disabled={pending}>{pending ? "Sending" : "Send"}</button>
    </form>
  );
}
```

**React Router**

Dengan React Router di framework mode, `action` route meneruskan post. `FormData` diteruskan tanpa perubahan, jadi `bot-field` sampai ke pemeriksaan honeypot Ikiform, dan header `Origin` dari browser ikut terbawa agar post dari `localhost` dihitung sebagai uji. Hapus salinan statis yang Anda simpan untuk Netlify.

`app/routes/contact.tsx`:

```tsx
import { data, Form, useNavigation } from "react-router";
import type { Route } from "./+types/contact";

export async function action({ request }: Route.ActionArgs) {
  const form = await request.formData();
  const origin = request.headers.get("origin");
  const response = await fetch("https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx", {
    method: "POST",
    headers: {
      Accept: "application/json",
      Authorization: `Bearer ${process.env.IKIFORM_SECRET_KEY}`,
      ...(origin ? { Origin: origin } : {}),
    },
    body: form,
  });
  const result = await response.json();
  if (result.ok) return { sent: true, error: "" };
  return data({ sent: false, error: String(result.error.message) }, { status: response.status });
}

export default function Contact({ actionData }: Route.ComponentProps) {
  const sending = useNavigation().state === "submitting";
  if (actionData?.sent) return <p role="status">Thanks. We read every message and reply within a day.</p>;

  return (
    <Form method="post">
      <input name="bot-field" type="text" tabIndex={-1} autoComplete="off" hidden />
      <label htmlFor="email">Email</label>
      <input id="email" name="email" type="email" required />
      <label htmlFor="topic">Topic</label>
      <select id="topic" name="topic" defaultValue="question">
        <option value="question">A question</option>
        <option value="bug">Something is broken</option>
        <option value="work">Working together</option>
      </select>
      <label htmlFor="message">Message</label>
      <textarea id="message" name="message" required />
      {actionData?.error ? <p role="alert">{actionData.error}</p> : null}
      <button disabled={sending}>{sending ? "Sending" : "Send"}</button>
    </Form>
  );
}
```

**SvelteKit**

Halaman SvelteKit di Netlify bisa mengirim langsung dari browser, tanpa form action buatan Anda. Atribut `action` membuat formulir tetap berfungsi sebelum hydration. Hapus salinan formulir yang di-prerender yang Anda tambahkan untuk Netlify.

`src/routes/contact/+page.svelte`:

```svelte
<script lang="ts">
  const ENDPOINT = "https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx";

  let sent = $state(false);
  let sending = $state(false);
  let error = $state("");

  async function send(event: SubmitEvent) {
    event.preventDefault();
    sending = true;
    error = "";
    try {
      const response = await fetch(ENDPOINT, {
        method: "POST",
        headers: { Accept: "application/json" },
        body: new FormData(event.currentTarget as HTMLFormElement),
      });
      const result = await response.json();
      if (result.ok) sent = true;
      else error = result.error.message;
    } catch {
      error = "Couldn't send. Check your connection and try again.";
    }
    sending = false;
  }
</script>

{#if sent}
  <p role="status">Thanks. We read every message and reply within a day.</p>
{:else}
  <form method="post" action={ENDPOINT} onsubmit={send}>
    <input name="bot-field" type="text" tabindex="-1" autocomplete="off" hidden />
    <label for="email">Email</label>
    <input id="email" name="email" type="email" required />
    <label for="topic">Topic</label>
    <select id="topic" name="topic">
      <option value="question">A question</option>
      <option value="bug">Something is broken</option>
      <option value="work">Working together</option>
    </select>
    <label for="message">Message</label>
    <textarea id="message" name="message" required></textarea>
    {#if error}<p role="alert">{error}</p>{/if}
    <button disabled={sending}>{sending ? "Sending" : "Send"}</button>
  </form>
{/if}
```

**Nuxt**

Di Nuxt komponen mengirim dari browser dengan `$fetch`, jadi tidak ada server route yang perlu di-deploy. `$fetch` melempar error pada jawaban non-`2xx`, dan envelope error Ikiform ada di `data` milik error itu. Hapus formulir statis tersembunyi dari `public/` dan field `form-name`.

`app/components/ContactForm.vue`:

```vue
<script setup lang="ts">
const ENDPOINT = "https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx";
const sent = ref(false);
const sending = ref(false);
const error = ref("");

async function send(event: Event) {
  sending.value = true;
  error.value = "";
  try {
    await $fetch(ENDPOINT, {
      method: "POST",
      headers: { Accept: "application/json" },
      body: new FormData(event.target as HTMLFormElement),
    });
    sent.value = true;
  } catch (failure) {
    const data = (failure as { data?: { error?: { message?: string } } }).data;
    error.value = data?.error?.message ?? "Couldn't send. Check your connection and try again.";
  } finally {
    sending.value = false;
  }
}
</script>

<template>
  <p v-if="sent" role="status">Thanks. We read every message and reply within a day.</p>
  <form v-else :action="ENDPOINT" method="post" @submit.prevent="send">
    <input name="bot-field" type="text" tabindex="-1" autocomplete="off" hidden />
    <label for="email">Email</label>
    <input id="email" name="email" type="email" required />
    <label for="topic">Topic</label>
    <select id="topic" name="topic">
      <option value="question">A question</option>
      <option value="bug">Something is broken</option>
      <option value="work">Working together</option>
    </select>
    <label for="message">Message</label>
    <textarea id="message" name="message" required></textarea>
    <p v-if="error" role="alert">{{ error }}</p>
    <button :disabled="sending">{{ sending ? "Sending" : "Send" }}</button>
  </form>
</template>
```

**React**

SPA React di Netlify mengirim data urlencoded ke `/` dengan field `form-name`, dan butuh salinan statis di `index.html` untuk deteksi. Kini ia mengirim `FormData` ke endpoint. Hanya request-nya yang berubah:

**Sebelum** (`ContactForm.tsx`)

```tsx
const body = new URLSearchParams(new FormData(event.currentTarget) as unknown as Record<string, string>);
body.set("form-name", "contact");
await fetch("/", {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: body.toString(),
});
```

**Sesudah** (`ContactForm.tsx`)

```tsx
const response = await fetch("https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx", {
  method: "POST",
  headers: { Accept: "application/json" },
  body: new FormData(event.currentTarget),
});
const result = await response.json();
if (!result.ok) setError(result.error.message);
```

Hapus `<form netlify>` tersembunyi dari `index.html` setelah tidak ada lagi yang mengirim ke Netlify.

**Vue**

Post sisi browser yang sama di single-file component Vue. Hapus formulir tersembunyi dari `index.html` yang memungkinkan Netlify mendeteksinya.

`src/components/ContactForm.vue`:

```vue
<script setup lang="ts">
import { ref } from "vue";

const ENDPOINT = "https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx";
const state = ref<"idle" | "sending" | "sent">("idle");
const error = ref("");

async function send(event: Event) {
  state.value = "sending";
  error.value = "";
  try {
    const response = await fetch(ENDPOINT, {
      method: "POST",
      headers: { Accept: "application/json" },
      body: new FormData(event.target as HTMLFormElement),
    });
    const result = await response.json();
    if (result.ok) {
      state.value = "sent";
      return;
    }
    error.value = result.error.message;
  } catch {
    error.value = "Couldn't send. Check your connection and try again.";
  }
  state.value = "idle";
}
</script>

<template>
  <p v-if="state === 'sent'" role="status">Thanks. We read every message and reply within a day.</p>
  <form v-else :action="ENDPOINT" method="post" @submit.prevent="send">
    <input name="bot-field" type="text" tabindex="-1" autocomplete="off" hidden />
    <label for="email">Email</label>
    <input id="email" name="email" type="email" required />
    <label for="topic">Topic</label>
    <select id="topic" name="topic">
      <option value="question">A question</option>
      <option value="bug">Something is broken</option>
      <option value="work">Working together</option>
    </select>
    <label for="message">Message</label>
    <textarea id="message" name="message" required></textarea>
    <p v-if="error" role="alert">{{ error }}</p>
    <button :disabled="state === 'sending'">{{ state === "sending" ? "Sending" : "Send" }}</button>
  </form>
</template>
```

> Versi TanStack Start dan React Router mengirim dari server Anda. Versi sisi server mengirim dengan secret key, jadi Ikiform melewati **Allowed domains** dan pemeriksaan manusianya. Setiap post lalu datang dari IP server Anda, dan batas Standard 5 per menit per pengunjung menghitung semua pengunjung Anda bersama-sama. Pilih [rate limit](https://ikiform.com/id/docs/rate-limits.md) Relaxed atau Custom untuk formulir yang Anda kirim lewat server, dan simpan `IKIFORM_SECRET_KEY` di environment variable khusus server.

Setiap versi mempertahankan nama field yang sama seperti di Netlify, jadi email notifikasi dan kolom CSV terasa familier. [Perbandingan Netlify Forms](https://ikiform.com/alternatives/netlify-forms) berisi pemetaan atribut lengkap, termasuk `data-netlify-recaptcha` dan input file.

## Deploy preview dan allowed domains

Netlify memberi setiap pull request alamatnya sendiri, seperti `deploy-preview-42--your-site.netlify.app`. Itu bukan subdomain dari `your-site.netlify.app`, jadi mencantumkan alamat situs Anda di **Allowed domains** tidak mencakup preview, dan post dari preview masuk ke spam dengan `origin_mismatch`.

- Tambahkan `your-site.netlify.app` dan domain kustom Anda untuk produksi.
- Tambahkan host preview tertentu selama Anda mengujinya, lalu hapus.
- Jangan tambahkan `netlify.app` saja. Setiap situs di Netlify akan diizinkan mengirim ke formulir Anda.
- Atau arahkan preview ke formulir Ikiform kedua tanpa allowed domains, lewat environment variable, dan jaga produksi tetap ketat.

## Beralih tanpa kehilangan kiriman

1. Unduh kiriman lama setiap formulir sebagai CSV dari bagian **Forms** situs. Ikiform tidak punya fitur import.
2. Deploy formulir baru ke preview dan kirim uji. Periksa nama field di dashboard Ikiform.
3. Merge ke produksi dan kirim uji lagi dari domain live.
4. Ganti outgoing webhook Netlify dengan [webhook](https://ikiform.com/id/docs/webhooks.md) Ikiform. Netlify menandatangani dengan token JWS; Ikiform memakai header Standard Webhooks, jadi verifier Anda juga berubah.
5. Setelah tidak ada post yang sampai ke Netlify selama beberapa hari, matikan deteksi formulir di pengaturan Forms situs.

> Netlify menerima upload file dan menjalankan Akismet di setiap kiriman. Upload file belum didukung. Kiriman dengan file mendapat `422 files_not_supported`. Jika formulir butuh file, biarkan formulir itu di Netlify Forms dan pindahkan sisanya.

## Pastikan berfungsi di Netlify

1. Di **Allowed domains** formulir, tambahkan domain situs Anda, ditambah `localhost` selama pengembangan. Biarkan kosong untuk menerima kiriman dari mana saja.
2. Deploy preview, tambahkan host-nya, dan kirim formulir dari sana.
3. Buka **Submissions** di dashboard. Kiriman baru ada di sana dengan setiap field yang Anda kirim.
4. Pastikan field-nya `email`, `topic`, dan `message`, tanpa `form-name` dan tanpa `bot-field`.
5. Buka tab **Forms** situs di Netlify dan pastikan uji tadi tidak ada di sana.
6. Kirim sekali dengan `bot-field` terisi. Kiriman itu disimpan sebagai spam dan tidak mengirim apa pun.
7. Cek inbox setiap penerima notifikasi. Masing-masing mendapat email berisi field, dan **Reply** terkirim ke pengirim formulir jika formulir punya field `email`.

## Hal yang sering menjebak

| Masalah | Yang harus dilakukan |
| --- | --- |
| Field `form-name` muncul di Ikiform | Input `form-name` tersembunyi masih ada di formulir, atau kode Anda masih mengaturnya. Hapus; Ikiform mengenali formulir dari URL. |
| Build Next.js gagal dengan menyebut forms | Atribut `netlify` atau `data-netlify` masih ada di kode React Anda. Hapus bersama `public/__forms.html`. |
| Post dari preview masuk ke spam | Host preview tidak ada di **Allowed domains**. Tambahkan selama Anda menguji, atau gunakan formulir kedua untuk preview. |
| Setiap post ditandai spam, bahkan yang asli | **Honeypot field** masih `_gotcha` sementara input Anda `bot-field`, atau sebaliknya. Samakan keduanya. |
| `422 files_not_supported` | Formulir punya `<input type="file">` dengan file yang dipilih. Upload file belum didukung; hapus input itu atau minta link sebagai gantinya. |
| `429 rate_limited` | Satu pengunjung mengirim melebihi rate limit formulir. Standard mengizinkan 5 per menit per pengunjung. Tunggu sesuai `Retry-After`, atau pilih Relaxed atau Custom untuk formulir yang mengirim dari satu IP bersama. |

## Pertanyaan

### Apa yang terjadi saat situs Netlify melewati 100 kiriman formulir?

Di paket lama, Netlify meng-upgrade situs ke Forms Level 1, yang mencakup 1.000 kiriman per bulan, dan menagihnya di akhir siklus penagihan. Di tier gratis lama, mencapai batas menjeda setiap situs di akun sampai Anda upgrade.

### Apakah Netlify Forms gratis di paket berbasis kredit yang baru?

Dokumentasi Netlify menyatakan kiriman formulir gratis dan tanpa batas di paket berbasis kredit. Masalahnya ada di situs itu sendiri: saat tim gratis kehabisan kredit bulanan, proyeknya dijeda dan tidak menerima kiriman formulir.

### Bisakah saya tetap hosting di Netlify dan memakai Ikiform untuk formulir?

Bisa. Ikiform tidak peduli di mana halaman di-host. Hapus atribut Netlify dari formulir, atur action-nya ke endpoint Ikiform Anda, dan Netlify Forms berhenti melihatnya.

### Apakah saya masih butuh formulir statis tersembunyi untuk React atau Next.js?

Tidak. Salinan itu hanya ada agar langkah deploy Netlify bisa menemukan formulir. Ikiform menerima post di sebuah URL, jadi hapus salinannya dan kirim dari komponen Anda.

### Apakah Ikiform gratis?

Tidak, tidak ada paket gratis. Pengujian gratis: Anda bisa mengirim 50 kiriman uji per bulan dari localhost sebelum membayar. Untuk go live, Pro mulai $6/bln untuk 500 kiriman, atau Anda bisa bayar sekali untuk 10.000 kiriman seharga $49 atau 50.000 kiriman seharga $149, dengan kredit yang tidak pernah kedaluwarsa.

## Panduan lainnya

- [Melampaui formulir builder](https://ikiform.com/id/guides/website-builder-forms.md): Saat formulir Webflow, Netlify, Carrd, atau Framer mentok di batas atau kekurangan fitur, pertahankan formulir yang Anda desain dan arahkan ke backend formulir.
- [Batas kiriman Webflow](https://ikiform.com/id/guides/website-builder-forms/webflow-submission-limit.md): Paket gratis Starter Webflow berhenti mengumpulkan setelah 50 kiriman formulir per situs dan situs yang diekspor tidak mendapat apa-apa, jadi arahkan Form Block ke Ikiform.
- [Formulir Framer](https://ikiform.com/id/guides/website-builder-forms/framer-forms.md): Formulir Framer sudah mengirim ke email, Sheets, atau webhook; tambahkan Ikiform sebagai webhook untuk kiriman yang tersimpan dan tersaring, notifikasi tim, dan lebih banyak tujuan.
- [Formulir Carrd](https://ikiform.com/id/guides/website-builder-forms/carrd-forms.md): Formulir kontak Carrd hanya mengirim email ke Anda dan formulir kustom butuh Pro Plus, jadi gunakan Send to URL di Plus atau embed HTML di Standard untuk menyimpan setiap kiriman.
