# Límite de Netlify Forms: qué pasa a los 100 envíos y cómo salir

> Los planes antiguos de Netlify miden los envíos de formularios por sitio y te suben de nivel automáticamente, y los planes por créditos pueden pausar el sitio, así que lleva el formulario a un backend.

Publicado el 2026-10-25 · https://ikiform.com/es/guides/website-builder-forms/netlify-forms-limit

En los planes antiguos de Netlify, cada sitio incluye 100 envíos de formulario al mes, y superarlos sube automáticamente el sitio a un nivel de Forms de pago. En los planes por créditos de las cuentas creadas desde septiembre de 2025, los formularios son gratis, pero un equipo gratuito que se queda sin créditos tiene todos sus sitios pausados, formularios incluidos. Llevar el formulario a Ikiform significa quitar los atributos de Netlify y poner el `action`, en HTML puro o en cualquier framework.

## Qué cambia en Netlify

Netlify no es un creador de sitios; es un hosting con formularios integrados. Eso determina tanto el límite como la salida. El límite que se aplica depende de cuándo se creó tu cuenta:

| Cuenta | Qué dice la documentación de Netlify | Qué significa para un formulario con mucho tráfico |
| --- | --- | --- |
| Planes antiguos, creados antes del 4 de septiembre de 2025 | Forms Level 0 incluye 100 envíos y 10 MB de subidas por sitio y mes. Superarlo sube el sitio a Forms Level 1, con 1.000 envíos, cobrado al final del ciclo de facturación. Por encima, los paquetes de uso extra añaden 500 cada vez | Una ola de spam puede pasar un sitio a un nivel de pago sin que nadie lo decida. En el nivel antiguo gratuito, alcanzar un límite pausa todos los sitios de la cuenta |
| Planes por créditos, creados desde entonces | Los envíos de formularios son gratis e ilimitados, sin niveles | El formulario en sí no cuesta nada. Pero cuando un equipo gratuito gasta sus créditos mensuales, Netlify pausa todos sus proyectos, y los proyectos pausados no reciben envíos de formularios |

La propia documentación de Netlify deja claro que la subida de nivel antigua es automática y que no puedes volver a bajar mientras el uso esté por encima del nivel inferior. Comprueba el tipo de plan de tu equipo y el uso de formularios del sitio en el panel de Netlify antes de decidir nada.

El segundo motivo por el que la gente se va no tiene nada que ver con las cifras. Netlify Forms funciona leyendo tu HTML desplegado:

- Los formularios se detectan al desplegar. Un formulario renderizado por React, Vue o Svelte no existe en ese HTML, así que mantienes una copia estática oculta para que la encuentre el build, y envías a ella con un campo `form-name`.
- Con Next.js, el adaptador OpenNext necesita esa copia como archivo estático en `public/`, y el envío debe ir a ese archivo estático, no a una página de Next.js. El build falla si `data-netlify` aparece en código React sin esa copia.
- Los envíos deben ser urlencoded o multipart. No se acepta JSON.
- El formulario solo funciona mientras el sitio esté desplegado en Netlify. Cambiar de hosting significa mover los formularios.

Diagrama: Cómo sube en un mes el uso de formularios de un sitio de Netlify con plan antiguo, y qué cambia enviar a Ikiform

1. En un plan antiguo, un sitio empieza el mes en Forms Level 0 con 100 envíos incluidos.
2. Llega el envío 101. La documentación de uso de Netlify describe el uso del sitio, así que una racha de spam puede ser lo que lo haga superar el límite.
3. Netlify sube el sitio a Forms Level 1, con 1.000 envíos, y lo cobra al final del ciclo.
4. Por encima del Level 1, los paquetes de uso extra añaden 500 envíos cada vez.
5. Con el formulario enviando a Ikiform, la página sigue en Netlify pero el envío va al endpoint de Ikiform.
6. Netlify Forms nunca recibe el envío, así que no hay nada que contar ni que subir de nivel.

El hosting se queda en Netlify. Solo se mueve el destino del formulario, y con él la medición.

## Mueve el formulario, stack por stack

Antes de cambiar código, crea un formulario de Ikiform por cada nombre de formulario de Netlify y pon su **Honeypot field** en `bot-field`. Así tu input oculto actual sigue funcionando como honeypot, sin renombrarlo. Elige tu stack:

**HTML**

El HTML puro en Netlify es lo que menos cambios necesita. Borra los atributos de Netlify y el input `form-name`, apunta `action` al endpoint y pasa la ruta de agradecimiento a `_redirect` como URL completa. El input `bot-field` se queda como honeypot.

**Antes** (`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>
```

**Después** (`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**

En Netlify, un formulario de Next.js solo funcionaba con Netlify Forms mediante una copia estática en `public/`, como `public/__forms.html`, a la que enviaba tu componente. Borra ese archivo, quita cualquier ajuste `NETLIFY_NEXT_VERIFY_FORMS` y envía desde el componente a Ikiform. El formulario también envía sin JavaScript, gracias a su `action`.

`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**

Una página estática de Astro no necesita nada de JavaScript. Quita `data-netlify` del formulario, pon el endpoint como `action` y construye la redirección a partir de `site` en `astro.config.mjs`. La página puede seguir prerenderizada.

`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**

Una app de TanStack Start en Netlify renderiza los formularios en React, algo que la detección de Netlify al desplegar no podía ver. Envía en su lugar mediante una server function y quita la copia estática oculta. Define `IKIFORM_SECRET_KEY` en las variables de entorno del sitio en Netlify. La función reenvía la cabecera `Origin` del navegador, así que los envíos desde `localhost` cuentan como pruebas gratuitas antes de que tu espacio de trabajo tenga plan.

`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**

Con React Router en modo framework, el `action` de la ruta reenvía el envío. El `FormData` pasa sin cambios, así que `bot-field` llega a la comprobación del honeypot de Ikiform, y la cabecera `Origin` del navegador va con él para que los envíos desde `localhost` cuenten como pruebas. Quita la copia estática que mantenías para 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**

Una página de SvelteKit en Netlify puede enviar directamente desde el navegador, sin una form action propia. El atributo `action` hace que el formulario funcione antes de la hidratación. Borra cualquier copia prerenderizada del formulario que añadieras para 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**

En Nuxt, el componente envía desde el navegador con `$fetch`, así que no hay ninguna server route que desplegar. `$fetch` lanza un error ante una respuesta que no sea `2xx`, y el envoltorio de error de Ikiform está en el `data` del error. Quita el formulario estático oculto de `public/` y el campo `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**

Una single-page app de React en Netlify enviaba datos urlencoded a `/` con un campo `form-name`, y necesitaba una copia estática en `index.html` para la detección. Ahora envía el `FormData` al endpoint. Solo cambia la petición:

**Antes** (`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(),
});
```

**Después** (`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);
```

Borra el `<form netlify>` oculto de `index.html` cuando ya no envíe nada a Netlify.

**Vue**

El mismo envío desde el navegador en un componente de un solo archivo de Vue. Quita de `index.html` el formulario oculto que permitía a Netlify detectarlo.

`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>
```

> Las versiones de TanStack Start y React Router envían desde tu servidor. Las versiones de servidor envían con una clave secreta, así que Ikiform se salta **Allowed domains** y su verificación humana. Entonces todos los envíos vienen de la IP de tu servidor, y el límite Standard de 5 por minuto por visitante cuenta a todos tus visitantes juntos. Elige el [límite de frecuencia](https://ikiform.com/es/docs/rate-limits.md) Relaxed o Custom para un formulario que envías a través de un servidor, y guarda `IKIFORM_SECRET_KEY` en variables de entorno solo de servidor.

Todas las versiones mantienen los mismos nombres de campo que tenía Netlify, así que los emails de notificación y las columnas del CSV te resultarán familiares. La [comparativa con Netlify Forms](https://ikiform.com/alternatives/netlify-forms) tiene la correspondencia completa de atributos, incluidos `data-netlify-recaptcha` y los inputs de archivo.

## Previews de despliegue y dominios permitidos

Netlify da a cada pull request su propia dirección, como `deploy-preview-42--your-site.netlify.app`. No es un subdominio de `your-site.netlify.app`, así que listar la dirección de tu sitio en **Allowed domains** no cubre las previews, y los envíos desde una preview acaban en spam con `origin_mismatch`.

- Añade `your-site.netlify.app` y tu dominio propio para producción.
- Añade un host de preview concreto mientras lo pruebas, y luego quítalo.
- No añadas `netlify.app` solo. Todos los sitios de Netlify podrían enviar a tu formulario.
- O apunta las previews a un segundo formulario de Ikiform sin dominios permitidos, mediante una variable de entorno, y mantén estricta la producción.

## Haz el cambio sin perder envíos

1. Descarga como CSV los envíos pasados de cada formulario desde la sección **Forms** del sitio. Ikiform no tiene importación.
2. Despliega el nuevo formulario en una preview y envía una prueba. Revisa los nombres de campo en el panel de Ikiform.
3. Fusiona a producción y envía otra prueba desde el dominio real.
4. Sustituye cualquier webhook saliente de Netlify por un [webhook](https://ikiform.com/es/docs/webhooks.md) de Ikiform. Netlify firma con un token JWS; Ikiform usa las cabeceras de Standard Webhooks, así que tu verificador también cambia.
5. Cuando no haya llegado ningún envío a Netlify durante unos días, desactiva la detección de formularios en los ajustes de Forms del sitio.

> Netlify acepta subida de archivos y pasa Akismet por cada envío. La subida de archivos todavía no está disponible. Un envío con un archivo recibe `422 files_not_supported`. Si un formulario necesita archivos, deja ese formulario en Netlify Forms y mueve el resto.

## Comprueba que funciona en Netlify

1. En **Allowed domains** del formulario, añade el dominio de tu sitio, y `localhost` mientras desarrollas. Déjalo vacío para aceptar envíos desde cualquier lugar.
2. Despliega una preview, añade su host y envía el formulario desde ella.
3. Abre **Submissions** en el panel. El nuevo envío está ahí con todos los campos que enviaste.
4. Confirma que los campos son `email`, `topic` y `message`, sin `form-name` y sin `bot-field`.
5. Abre la pestaña **Forms** del sitio en Netlify y confirma que la prueba no está ahí.
6. Envía una vez con `bot-field` relleno. Se guarda como spam y no envía nada.
7. Revisa la bandeja de entrada de cada destinatario de las notificaciones. Cada uno recibe un email con los campos, y **Reply** va a quien envió el formulario cuando este tiene un campo `email`.

## Errores comunes

| Problema | Qué hacer |
| --- | --- |
| Aparece un campo `form-name` en Ikiform | El input oculto `form-name` sigue en el formulario, o tu código aún lo pone. Quítalo; Ikiform identifica el formulario por la URL. |
| El build de Next.js falla mencionando formularios | Aún hay un atributo `netlify` o `data-netlify` en tu código React. Quítalo junto con `public/__forms.html`. |
| Las previews envían a spam | El host de la preview no está en **Allowed domains**. Añádelo mientras pruebas, o usa un segundo formulario para las previews. |
| Todos los envíos se marcan como spam, incluso los reales | **Honeypot field** sigue siendo `_gotcha` mientras tu input es `bot-field`, o al revés. Haz que coincidan. |
| `422 files_not_supported` | El formulario tiene un `<input type="file">` con un archivo elegido. La subida de archivos aún no está disponible; quita el input o pide un enlace. |
| `429 rate_limited` | Un visitante envió más de lo que permite el límite de frecuencia del formulario. Standard permite 5 por minuto por visitante. Espera lo que indique `Retry-After`, o elige Relaxed o Custom para formularios que envían desde una IP compartida. |

## Preguntas

### ¿Qué pasa cuando un sitio de Netlify supera los 100 envíos de formulario?

En los planes antiguos, Netlify sube el sitio a Forms Level 1, que incluye 1.000 envíos al mes, y lo cobra al final del ciclo de facturación. En el nivel antiguo gratuito, alcanzar un límite pausa todos los sitios de la cuenta hasta que mejoras el plan.

### ¿Son gratis los Netlify Forms en los nuevos planes por créditos?

La documentación de Netlify dice que los envíos de formularios son gratis e ilimitados en los planes por créditos. El problema es el propio sitio: cuando un equipo gratuito se queda sin créditos mensuales, sus proyectos se pausan y no reciben envíos de formularios.

### ¿Puedo seguir alojando en Netlify y usar Ikiform para los formularios?

Sí. A Ikiform no le importa dónde esté alojada la página. Quita los atributos de Netlify del formulario, pon su action apuntando a tu endpoint de Ikiform, y Netlify Forms deja de verlo.

### ¿Sigo necesitando un formulario estático oculto para React o Next.js?

No. Esa copia solo existe para que el paso de despliegue de Netlify encuentre el formulario. Ikiform recibe envíos en una URL, así que borra la copia y envía desde tu componente.

### ¿Ikiform es gratis?

No, no hay plan gratuito. Probar es gratis: puedes enviar 50 envíos de prueba al mes desde localhost antes de pagar. Para pasar a producción, Pro empieza en 6 $/mes por 500 envíos, o puedes pagar una sola vez 49 $ por 10.000 envíos o 149 $ por 50.000 envíos, con créditos que nunca caducan.

## Más guías

- [Más allá de los formularios del creador](https://ikiform.com/es/guides/website-builder-forms.md): Cuando los formularios de Webflow, Netlify, Carrd o Framer chocan con un tope o les falta algo, conserva el formulario que diseñaste y apúntalo a un backend de formularios.
- [Límite de envíos de Webflow](https://ikiform.com/es/guides/website-builder-forms/webflow-submission-limit.md): El plan gratuito Starter de Webflow deja de recoger envíos tras 50 por sitio y los sitios exportados no tienen ninguno, así que apunta el Form Block a Ikiform.
- [Formularios de Framer](https://ikiform.com/es/guides/website-builder-forms/framer-forms.md): Los formularios de Framer ya envían a email, Sheets o un webhook; añade Ikiform como webhook para tener envíos guardados y filtrados, avisos al equipo y más destinos.
- [Formularios de Carrd](https://ikiform.com/es/guides/website-builder-forms/carrd-forms.md): El formulario de contacto de Carrd solo te avisa por email y los formularios personalizados necesitan Pro Plus, así que usa Send to URL en Plus o un embed HTML en Standard para guardar cada envío.
