# Introduction

Welcome to the documentation for [Web3Forms](https://web3forms.com/)

Web3Forms is a simple tool to set up Contact Forms for Static Websites. Receive form submissions directly in your email inbox without any server or back-end code. Its free! Web3Forms is perfect for static / JAM Stack websites. Start receiving submissions by creating an [Access Key](https://web3forms.com/#start)

Start this documentation by clicking the links below or choose your topic from the left side.

{% content-ref url="/pages/-MTfItec4l25rz-K1JL1" %}
[Customizations](/getting-started/customizations)
{% endcontent-ref %}


# Installation

## Step 01: Get Access Key

First step is to get an Access Key from Web3Forms. [Create Access Key](https://web3forms.com/#start)

Once you submit the form, you will get the Access key in your Email. Copy that key so that we can use this later.

## Step 2: Create HTML Form

Create a form in your website with our form endpoint inside action attribute. Following is a simple example on how it should look like:

{% tabs %}
{% tab title="Basic Example" %}

```html
<form action="https://api.web3forms.com/submit" method="POST">

    <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE">

    <input type="text" name="name" required>
    <input type="email" name="email" required>
    <textarea name="message" required></textarea>
    <input type="hidden" name="redirect" value="https://web3forms.com/success">
    <button type="submit">Submit Form</button>

</form>
```

{% endtab %}

{% tab title="Advanced Example" %}

```html
<form action="https://api.web3forms.com/submit" method="POST">

    <!-- REQUIRED: Your Access key here. Don't worry this can be public -->
    <!-- Create your Access key here: https://web3forms.com/ -->
    <!-- <input type="hidden" name="apikey" value="YOUR_ACCESS_KEY_HERE"> -->
    <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE">

    <!-- Optional: Can be type="hidden" or type="text" for subject -->
    <input type="hidden" name="subject" value="New Submission from Web3Forms">
  
    <!-- Optional: From Name you want to see in the email
          Default is "Notifications". you can overwrite here -->
    <input type="hidden" name="from_name" value="Your Website Name">
  
    <!-- Optional: To send the form submission as CC email -->
    <input type="hidden" name="ccemail" value="partner@example.com">

    <!-- Optional: default replyto will be "email" (if available), 
         you may overwrite here -->
    <input type="hidden" name="replyto" value="customer@example.com">

    <!-- Required: if submitting without Javascript 
         (because by default web3form outputs json) -->

    <!-- If javascript, use "window.location.hash" for redirects -->
    <input type="hidden" name="redirect" value="https://web3forms.com/success">

    <!-- Optional: But Recommended: To Prevent SPAM Submission. 
         Make sure its hidden by default -->
    <input type="checkbox" name="botcheck" id="" style="display: none;">
    
    <!-- Webhooks: Send your form data to Notion, Google Sheets or Zapier.
         This feature available to PRO & Starter Plan users only -->
    <input type="hidden" name="webhook" value="WEBHOOK_URL_HERE" />

    <!-- Google reCaptcha v3: To Prevent SPAM Submission.PRO Plan only -->
    <input type="hidden" name="recaptcha_response" id="recaptchaResponse">
    
    <!-- Attachments: Make sure the <form> has enctype="multipart/form-data"
         This feature available to PRO Plan users only -->
    <input type="file" name="attachment" />

    <!-- Custom Form Data: 
     Then you can include your own form data you wish to receive in email. -->
    <input type="email" name="email" required>
    <input type="text" name="First Name" required>
    <input type="text" name="Phone Number" required>
    <textarea name="message" cols="30" rows="10" required></textarea>

    <button type="submit">Submit Form</button>

</form>
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Make sure you added \`name\` attribute, form action URL and the \`access\_key\` to make the form work as expected
{% endhint %}

## Step 3: Add your Access Key

Add your access key to start receiving email submissions.

```html
<input type="hidden" name="apikey" value="YOUR_ACCESS_KEY_HERE">
```

## Step 4: Done

That's it. Run your code on a browser and it should work. This is a simple starting example. However you can customize it with unlimited possibilities. Checkout other pages to know more.


# Customizations


# Email Subject line

Customize your notification email subject

## `subject`

There are two ways you can setup Email Subject.

## 1. Pre-defined Subject

You can add a pre-defined subject by adding a form `input` with `type="hidden"` along with your subject in `value`. See the code below.

```markup
<input type="hidden" name="subject" value="New Submission from Web3Forms">
```

## 2. User Generated Subject

In this case, the subject can be filled by the website visitor. For that, you can use an input `type="text"`. See Code below.

```markup
<input type="text" name="subject" />
```

{% hint style="info" %}
The Name attribute must be called `subject`
{% endhint %}

### 3. Custom Subject with User Input Value

You can also customize the subject value to include user submitted value such as their first name. This will be easier to manage in emails when you have multiple emails coming from different users.

Below is a **javascript** example for creating custom subject. For react, [check this example](/how-to-guides/js-frameworks/react-js/react-js).

<pre class="language-javascript"><code class="lang-javascript">const form = document.getElementById('form');
const result = document.getElementById('result');

form.addEventListener('submit', function(e) {
    e.preventDefault();
    
    const formData = new FormData(form);
    
    // Get the name input value
<strong>    const name = formData.get('name');
</strong>    
    // Create a custom subject
<strong>    const subject = `${name} sent a message from website`;
</strong>    
    // Append the custom subject to the form data
    formData.append('subject', subject);
    
    const object = Object.fromEntries(formData);
    const json = JSON.stringify(object);
    
    result.innerHTML = "Please wait...";

    fetch('https://api.web3forms.com/submit', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        },
        body: json
    })
    .then(async (response) => {
        let json = await response.json();
        if (response.status == 200) {
            result.innerHTML = json.message;
        } else {
            console.log(response);
            result.innerHTML = json.message;
        }
    })
    .catch(error => {
        console.log(error);
        result.innerHTML = "Something went wrong!";
    })
    .then(function() {
        form.reset();
        setTimeout(() => {
            result.style.display = "none";
        }, 3000);
    });
});
</code></pre>


# Success / Thank You Page

You can customize the success / thank you page as you like. See the options below.

{% hint style="info" %}
Tip: To use your own thank you page, visit [Custom Redirection](/getting-started/customizations/redirection) page.
{% endhint %}

<figure><img src="/files/FPg3MGSUb3MQnyfTcfUU" alt="" width="375"><figcaption><p>Default Success Page</p></figcaption></figure>

### Fix Stale Form Data after clicking "Go Back"

You might have noticed, after successful form submission, the user will show success page as shown above. However, once user clicked the "Go Back" button, the contact form fileds will still show the form data. it will not clear. In that case, make sure you add the following code to fix that.

```html
<script>
    window.onload = function() {
        // Reset the form fields when the page loads
        document.getElementById("form").reset();
    };
</script>
```

### Redirect to your your own Website / URL

To redirect the success page to your own website or another different URL, please use the custom redirection. See this guide [Custom Redirection](/getting-started/customizations/redirection)for more details.

### Show Success Message on the Same Page (Do not redirect)

To skip redirection after the contact form submission and instead, if you want to show a success message on the same page, you can use the Javascript Method or similar. See [HTML & JavaScript](/how-to-guides/html-and-javascript)page for sample code.


# Custom Redirection

Customize Success Redirection to your website after form submission

## `redirect`

{% hint style="danger" %}
This can be only used if you are using the Default HTML Form without Javascript.

If you are using JavaScript or any other front-end Technology, Please use appropriate redirection method instead. [See Javascript Example](/how-to-guides/html-and-javascript)
{% endhint %}

By default, Web3Forms redirects to our website after form submission, However if you have a custom URL on your website if you want to redirect after a successful form redirection, you can use the `redirect` option. You can set any URL you want. This could be a page on your website or a different website. See the code below. Make sure its an absolute URL with `https://` not relative.

#### Examples

```html
<!-- Default URL -->
<input type="hidden" name="redirect" value="https://web3forms.com/success">

<!-- Custom URL -->
<input type="hidden" name="redirect" value="https://yourwebsite.com/thanks.html">

<!-- Redirect to another website (Requires a Paid Plan) -->
<input type="hidden" name="redirect" value="https://partnerwebsite.com/someaction/">
```

{% hint style="info" %}
Cross domain redirection requires a paid plan. Free users must use same domain for redirection.
{% endhint %}

Also, make sure you provide full URL as the value instead of relative URL

```html

<!-- ❌ Wrong. This won't work -->
<input type="hidden" name="redirect" value="/thanks.html">

<!-- ✅ Correct. Full URL with https:// -->
<input type="hidden" name="redirect" value="https://yourwebsite.com/thanks.html">

```

{% hint style="info" %}
The Input type should be `hidden` and the name should be `redirect`
{% endhint %}


# Captcha & SPAM

Prevent bots and spammers using your forms to send emails.

Web3Forms provides variety of spam prevention methods.

First of all, we do run a server-side spam check on all form submissions. So even if you have not implemented any client side spam check, you will receive less spam because of our server side spam check.

However, to block more spam, we recommend adding one of the following server side spam check. Please click on each guide to see more detailed instructions.

* [hCaptcha](/getting-started/customizations/spam-protection/hcaptcha)
* [Honeypot](/getting-started/customizations/spam-protection/spam-protection)
* [Google reCaptcha](/getting-started/pro-features/recaptcha-integration) (Pro only)


# hCaptcha

hCaptcha is the privacy friendly alternative to Google reCaptcha. Used by Cloudflare, Shopify & more..

<figure><img src="/files/h1iTX7AaTlgBdyUvTbWY" alt="" width="306"><figcaption><p>hCaptcha checkbox</p></figcaption></figure>

<figure><img src="/files/LlsePCfwSUO3bOYBYuwh" alt="" width="375"><figcaption><p>hcaptcha solve problem</p></figcaption></figure>

Web3Forms provides zero-config integration with hCaptcha. You don't need to setup your own keys or register with them. Just use the following code and add a script. You're done.

{% hint style="info" %}
Remember **hCaptcha's** captcha mostly feels a bit difficult for users to solve. In that case, you can either use hCaptcha Paid Plan or use alternatives like hidden [honeypot](/getting-started/customizations/spam-protection/spam-protection) (less secure) or [reCaptcha](/getting-started/pro-features/recaptcha-integration) / [Cloudflare Turnstile Captcha](/getting-started/pro-features/cloudflare-turnstile-captcha) method (Pro).
{% endhint %}

**Step 1: Add a \<div> inside your form**

```html
<form>
  ...
   <! -- Step 1: Add this line -->
   <div class="h-captcha" data-captcha="true"></div>
  ...
</form>
```

**Step 2: Add the script before the closing of \</body>**

```html
<! -- Step 2: Add the Web3Forms script -->
<script src="https://web3forms.com/client/script.js" async defer></script>
```

### Configuration Options

You can provide all options provided by hCaptcha by default. You need to append the option with `data-*` attribute. See example below

```markup
 <div class="h-captcha" 
      data-captcha="true" 
      data-lang="de" 
      data-theme="dark"
      data-onload="myFunction"
      data-render="explicit"
      data-size="compact"
      ></div>
```

For more configuration options, visit: <https://docs.hcaptcha.com/configuration>

### Activate hCaptcha to your form

Once everything's setup you need to activate hCaptcha on your form to make it mandatory on each form submissions. For that, visit the dashboard: [https://app.webforms.com](https://app.webforms.com/) and click on your form and then enable hCaptcha as your preferred captcha

{% hint style="info" %}
Add Client Side Validation as shown below to prevent form submission without checking the hCaptcha field.
{% endhint %}

### Client Side Validation

Use this snippet if you are using the HTML form-embedded method without Javascript to check whether the hCaptcha is filled or not.

Add this code block just above the closing of \</body> and make sure `YOUR_FORM_ID` is updated with your form id.

```html
<script>
const form = document.getElementById('YOUR_FORM_ID');

form.addEventListener('submit', function(e) {

    const hCaptcha = form.querySelector('textarea[name=h-captcha-response]').value;

    if (!hCaptcha) {
        e.preventDefault();
        alert("Please fill out captcha field")
        return
    }
});
</script>
```

### Manual Setup

If you want to load hCaptcha directly instead of using web3forms proxy, make sure you use the following **sitekey** for free plans. You can set your own site key and secret key on all paid plans,

```javascript
// hCaptcha Site Key for Web3Forms
data-sitekey="50b2fe65-b00b-4b9e-ad62-3ba471098be2"
```

### Full Code

```html
<form action="https://api.web3forms.com/submit" method="POST">
    <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE">
    <input type="text" name="name" required>
    <input type="email" name="email" required>
    <textarea name="message" required></textarea>
    
    <! -- Step 1: Add this line -->
    <div class="h-captcha" data-captcha="true"></div>
    
    <button type="submit">Submit Form</button>
</form>

<! -- Step 2: Add the script -->
<script src="https://web3forms.com/client/script.js" async defer></script>
```

If you add just two lines to your contact form, you will get a working hCaptcha to protect your form.

## Usage with React / Next.js

To use hCaptcha with React or Next.js, please follow the instructions below.

First, install the [@hcaptcha/react-hcaptcha ](https://www.npmjs.com/package/@hcaptcha/react-hcaptcha)package from NPM.

```bash
npm install @hcaptcha/react-hcaptcha --save
# or
pnpm add @hcaptcha/react-hcaptcha
```

Then, add the \<HCaptcha/> component inside the form.

Make sure you are using `50b2fe65-b00b-4b9e-ad62-3ba471098be2`as the `sitekey` for free plans. Also make sure `reCaptchaCompat` is false.

You can use a custom site key if you are on a Paid plan.

<pre class="language-jsx"><code class="lang-jsx">import { useForm } from "react-hook-form";
<strong>import HCaptcha from '@hcaptcha/react-hcaptcha';
</strong>
export default function ContactForm() {
  const { register, handleSubmit, setValue } = useForm();
  
<strong>  const onHCaptchaChange = (token) => {
</strong><strong>    setValue("h-captcha-response", token);
</strong><strong>  };
</strong>  
  const onSubmit = async (data) => {
    console.log(data);
    
    await fetch("https://api.web3forms.com/submit", {
      method: "POST",
      body: data
    }).then((res) => res.json());
  }

return (
  &#x3C;form onSubmit={handleSubmit(onSubmit)}>
     {/* // other form fields */}
<strong>      &#x3C;HCaptcha
</strong><strong>         sitekey="50b2fe65-b00b-4b9e-ad62-3ba471098be2"
</strong><strong>         reCaptchaCompat={false}
</strong><strong>         onVerify={onHCaptchaChange} 
</strong>      /> 
  &#x3C;/form>
)}
</code></pre>

That's it.

Make sure you have enabled `hcaptcha` as the Block Spam option in the settings. Login to your dashboard to change it if not enabled already.

#### Other implementations

You can see the following guide for more examples. Just make sure you are using the correct `sitekey` as mentioned above.\
\
<https://www.npmjs.com/package/@hcaptcha/react-hcaptcha>


# reCaptcha & Turnstile

This is a Pro feature.

reCaptcha & Turnstile captcha is available for Pro users.

Check out the relavant pages:

{% content-ref url="/pages/-MTfIteihs\_72JgixZjX" %}
[reCaptcha Integration](/getting-started/pro-features/recaptcha-integration)
{% endcontent-ref %}

{% content-ref url="/pages/KCw9ndZ84hnstJ0K2sWh" %}
[Cloudflare Turnstile Captcha](/getting-started/pro-features/cloudflare-turnstile-captcha)
{% endcontent-ref %}


# Honeypot

NOT RECOMMENDED: Prevent bots and spammers using your forms to send emails.

{% hint style="danger" %}
**Warning:** This feature is depreciated. Please use any other captcha.

*Honeypot seems to be less effective in forms to prevent spam submissions. So, we suggest you add a proper captcha to protect your form.*
{% endhint %}

Bots and Spam Submissions are prevented using the Honeypot Spam Prevention method. By now, these bots are getting advanced, so we have made sure to add some extra layer of protection for this Honeypot. This will stop most bots from submitting your form.

### `botcheck`

{% hint style="info" %}
Honeypot is optional to include, however we recommend adding this if you are not using the [hCaptcha](/getting-started/customizations/spam-protection/hcaptcha) or [reCaptcha Integration](/getting-started/pro-features/recaptcha-integration)
{% endhint %}

See the code below.

```markup
<input type="checkbox" name="botcheck" class="hidden" style="display: none;">
```

{% hint style="info" %}
The Input type should be `checkbox` and the name should be `botcheck`
{% endhint %}


# Report Spam

We do filter all spam on the server side, so you can be safe. We block almost **8000+** spam every month for our users.

However, there are some times when you will still get spam, In that case, please report that spam by forwarding the email to `support@web3forms.com`

![](/files/-MaECFJ0dtEiWtD-7nt2)

In the email body, please also mention that you have received spam and want to block it. We will block the user IP and the corresponding message.


# Custom Reply-To

Set a custom reply-to email for your submission.

By default, we take `email` as the `replyto` address. So if your form has an `email` input, you don't need to configure anything. In the submission you receive, you can see the reply to email.

However, If you want to add a custom `replyto` email address, you can use the following code.

```markup
<input type="hidden" name="replyto" value="custom@gmail.com" />
```

**Here's an example with full code:**

```markup
<!-- // Default Form. Here, `email` is used as `replyto` -->

<form action="https://api.web3forms.com/submit" method="POST">
    <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE">
    <input type="text" name="name" required>
    <!-- replyto set by this input. usually, it's the user who submits the form.  -->
    <input type="email" name="email" required>
    <button type="submit">Submit Form</button>
</form>


<!-- // Custom `replyto` Form -->

<form action="https://api.web3forms.com/submit" method="POST">
    <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE">
    <!-- `replyto` email will be the given value.  -->
    <input type="hidden" name="replyto" value="custom@gmail.com" />
    <input type="text" name="name" required>
    <input type="email" name="email" required>
    <button type="submit">Submit Form</button>
</form>

```


# From Name

You can customize the **From Name** of the email you receive using the `from_name` hidden tag. The default From Name is "**Notifications**"

```markup
<input type="hidden" name="from_name" value="Mission Control">
```

![](/files/-ManYqACe6aKIppjpcrn)


# Pro Features

Unlock advanced features with Web3Forms Paid features (Pro, Agency/Team, Starter).

{% hint style="info" %}
All features below require an active **paid** subscription.
{% endhint %}

***

### Spam Protection

* [reCaptcha Integration ](/getting-started/pro-features/recaptcha-integration)- Google reCaptcha v3 for invisible spam protection
* [Cloudflare Turnstile Captcha](/getting-started/pro-features/cloudflare-turnstile-captcha) - Privacy-friendly captcha alternative

***

### Email Features

* [Add CC Email](/getting-started/pro-features/add-cc-email) - Send copies to multiple recipients
* [Autoresponder (Auto-Reply)](/getting-started/pro-features/autoresponder) - Send automatic confirmation emails to users
* [Intro Text](/getting-started/pro-features/intro-text) - Add custom text to your notification emails

***

### File Uploads

* [File Attachments](/getting-started/pro-features/file-attachments) - Single file uploads up to 5MB
* [Advanced File Uploader](/getting-started/pro-features/advanced-file-uploader) - Multiple files, larger sizes, drag & drop

***

### Integrations & Security

* [Webhooks](/getting-started/pro-features/webhooks) - Send form data to third-party services (Zapier, Make, etc.)
* [Restrict to Domain](/getting-started/pro-features/restrict-to-domain) - Limit form submissions to specific domains

***

### Need Pro?

[Upgrade to Pro →](https://web3forms.com/pricing)

All Pro features are instantly available after upgrading. Configure them in your [dashboard](https://app.web3forms.com).


# reCaptcha Integration

Web3forms supports Google's reCaptcha v3 for forms.

**Codepen Demo**: <https://codepen.io/surjithctly/pen/BaZQLyR>

{% hint style="info" %}
Heads Up! This is a PRO feature. You must have an active subscription to use this feature.
{% endhint %}

### Generate reCaptcha Keys <a href="#add-the-turnstile-widget-to-your-site" id="add-the-turnstile-widget-to-your-site"></a>

To setup, first you should register your domain on Google reCaptcha and generate API keys from their website. Go to [reCaptcha Website](https://www.google.com/recaptcha/admin/create) to create new keys. Choose reCaptcha v3 from the option. Add your domain name and submit to create your keys. **You will need both Site Key and Secret Key**. Copy those code and save it in your notepad. We will need this later.

![Registering reCaptcha](/files/-MTueW187KwTnahyst0Q)

### Client-side Integration <a href="#add-the-turnstile-widget-to-your-site" id="add-the-turnstile-widget-to-your-site"></a>

Now open your HTML file where your form exists and paste the following code just before the closing of `</body>` tag.

<pre class="language-markup"><code class="lang-markup">&#x3C;!-- Recaptcha v3 -->

&#x3C;script src="https://www.google.com/recaptcha/api.js?render=<a data-footnote-ref href="#user-content-fn-1">YOUR_SITE_KEY_HERE</a>">&#x3C;/script>
&#x3C;script>
    grecaptcha.ready(function () {
        grecaptcha.execute('<a data-footnote-ref href="#user-content-fn-1">YOUR_SITE_KEY_HERE</a>', {
                action: 'contact'
            })
            .then(function (token) {
                recaptchaResponse.value = token;
            });
    });
    
&#x3C;/script>
</code></pre>

Now replace `YOUR_SITE_KEY_HERE` with your actual Site key you've obtained from the reCaptcha Website. You need to replace it in two places above. `LINE 3` & `LINE 6`

{% hint style="warning" %}
Heads Up! You'll need to change the SITE KEY in two places in the above code.
{% endhint %}

Now add the following code inside your `<form>` tag.

```markup
<input type="hidden" name="recaptcha_response" id="recaptchaResponse">
```

### Add Secret Keys to your Web3Forms Dashboard <a href="#add-the-turnstile-widget-to-your-site" id="add-the-turnstile-widget-to-your-site"></a>

1. Visit the Web3Forms Dashboard and select your form at: [https://app.webforms.com](https://app.webforms.com/)
2. Open Settings and choose `recaptcha` as your captcha provider
3. Enter the **Secret Key** in the Textbox below
4. Save Changes

That's it. Your form will automatically be protected with reCaptcha v3.

That's it. Now test your form and it should work without any extra configuration.

#### How to know the reCaptcha is working as expected?

To test, right click the page and choose **Inspect Element**. Now inspect the `<form>` part where the above `recaptcha_response` will be populated with a large key value. If you don't see that, check `console.log()` for more info.

[^1]: update site key here


# Cloudflare Turnstile Captcha

Web3Forms supports cloudflare turnstile captcha in our forms.

**Codepen Demo**: <https://codepen.io/surjithctly/pen/ExdGwpE>

{% hint style="info" %}
Heads Up! This is a PRO feature.\
You must have an active subscription to use this feature.
{% endhint %}

## Steps

### 1. Create Turnstile Captcha Accounut <a href="#add-the-turnstile-widget-to-your-site" id="add-the-turnstile-widget-to-your-site"></a>

1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com/?to=/:account/turnstile) and select your account.
2. Go to **Turnstile**.
3. In the widget overview, select **Settings**.
4. Copy your **sitekey** and **secret key**.

### 2. Add the Turnstile Script to your website <a href="#add-the-turnstile-widget-to-your-site" id="add-the-turnstile-widget-to-your-site"></a>

To add the Turnstile script:

1. Insert the Turnstile script snippet in your HTML’s `<head>` element:

```
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
```

### 3. Render the widget inside your form <a href="#add-the-turnstile-widget-to-your-site" id="add-the-turnstile-widget-to-your-site"></a>

To render the Turnstile widget in your form:

1. Insert the below code inside your `<form>` tag. Make sure to change `YOUR_SITE_KEY_HERE` with the actual site key.

```
<div class="cf-turnstile" data-sitekey="YOUR_SITE_KEY_HERE" data-theme="light"></div>
```

### 4. Add Secret Keys to your Web3Forms Dashboard <a href="#add-the-turnstile-widget-to-your-site" id="add-the-turnstile-widget-to-your-site"></a>

1. Visit the Web3Forms Dashboard and select your form: <https://app.webforms.com>
2. Open Settings and choose `turnstile` as your captcha provider
3. Enter the **Secret Key** in the Textbox below
4. Save Changes

That's it. Your form will automatically be protected with Cloudflare Captcha.

<figure><img src="/files/1Kgz2g6OAyhh5YvS77cE" alt=""><figcaption></figcaption></figure>

To read more detailed guide, visit the official docs here:\
<https://developers.cloudflare.com/turnstile/get-started/>


# Add CC Email

{% hint style="info" %}
Heads Up! This is a PRO feature. You must have an active membership to use this feature.
{% endhint %}

```markup
<input type="hidden" name="ccemail" value="partner@example.com" />
```

If you have multiple cc emails, you can add them using semi-column `;` as a separator.

Example:

```markup
<input type="hidden" name="ccemail" value="partner@example.com; accounts@example.com" />
```


# Autoresponder (Auto-Reply)

{% hint style="info" %}
Heads Up! This is a PRO feature. You must have an active subscription to use this feature.
{% endhint %}

Autoresponder is available for all Pro/Agency users. Following details can be customised.

### Enable Autoreponder

You can enable autoresponder from the Form Settings Page from our dashboard: [https://app.webforms.com](https://app.webforms.com/)

{% hint style="info" %}
Autoresponder will only work on **production** websites. It will not work on localhost and some preview environments.
{% endhint %}

#### Available Options

1. From Name (Company Name)
2. Autoresponder Subject
3. Autoresponder Intro Text (eg: Thanks for submitting the form..)
4. Show copy of their submission in the email - Yes/No
5. Full `https://` path of your Logo Image (PNG preferred)\
   eg: `https://yoursite.com/img/logo.png`

<figure><img src="/files/et7y0oDxSISuj1ZhoYhK" alt=""><figcaption></figcaption></figure>

Also, to make the autoresponder work, you must make sure your `<form>` has an **email field** with name attribute `email` or `Email` is included in the form. The autoresponder will send emails to that particular email once user filled the form.

```html
// example code     ⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄
<input type="email" name="email" placeholder="you@company.com" />
```


# File Attachments

{% hint style="info" %}
Heads Up! This is a PRO feature. You must have an active subscription to use this feature.
{% endhint %}

```markup
<input type="file" name="attachment" />
```

You will need to add `enctype="multipart/form-data"` to the Form Element to make the attachment work.

```markup
<form action="https://api.web3forms.com/submit" enctype="multipart/form-data" method="POST">
  ...
  <input type="file" name="attachment" />
  ...  
</form>
```

{% hint style="info" %}
If you are using Javascript / Ajax to submit the form, make sure you set the Headers accordingly. Setting wrong headers will throw an error.
{% endhint %}

### Multiple File Attachments

We support multiple file attachments on the contact form. We process them together and send them to you.

```html
<form action="https://api.web3forms.com/submit" enctype="multipart/form-data" method="POST">
  ...
  <label> Your Resume </label>
  <input type="file" name="resume" />
  
  <label> Your Photo </label>
  <input type="file" name="photo" />
  ...  
</form>
```

### Advanced File Uploader

Our Default HTML5 File uploader works only for single files up to 5 MB only. To upload multiple files or larger attachments, we recommend using our Advanced File Uploader. [Please see the guide here](#undefined)

## File upload with Javascript

#### Here's an example code with Javascript

```html
<form id="myForm" method="POST">
  ...
  <input type="file" id="attachment" name="attachment" />
  ...  
  <button type="submit">Submit Form</button>
</form>
```

```javascript
const form = document.getElementById("myForm");

form.addEventListener("submit", function (e) {
  e.preventDefault();
  
  const formData = new FormData(form);
  
  formData.append("access_key", "YOUR_ACCESS_KEY_HERE");
  formData.append("subject", "New Submission from Web3Forms");

  const file = document.getElementById("attachment");
  const filesize = file.files[0].size / 1024;

  if (filesize > 1000) {
    alert("Please upload file less than 1 MB");
    return;
  }
  
  // Don't add `headers` or `content-type` in this fetch call
  // Since it contains attachments, the browser auto-adds them. 
  fetch("https://api.web3forms.com/submit", {
    method: "POST",
    body: formData
  })
    .then(async (response) => {
      let json = await response.json();
      if (response.status == 200) {
        console.log(json.message);
      } else {
        console.log(response);
      }
    })
    .catch((error) => {
      console.log(error);
    })
    .then(function () {
      form.reset();
    });
});

```


# Advanced File Uploader

For large attachments or multiple file uploads, use our advanced file uploader.

{% hint style="info" %}
Heads Up! This is a PRO feature. You must have an active subscription to use this feature.
{% endhint %}

<figure><img src="/files/CQFeN3nqxzDMiXhDrFxq" alt="" width="375"><figcaption></figcaption></figure>

Our Default HTML5 File Uploader only supports file attachments up to 5 MB. Also currently it does not support multiple files. If you need to upload large files or multiple files, use our advanced file uploader.

**Step 1: Add a File input inside your form with \`**&#x64;ata-advance&#x64;**\` attribute**

<pre class="language-html"><code class="lang-html">&#x3C;form action="https://api.web3forms.com/submit" method="POST">
  ...
   &#x3C;! -- Step 1: Add this line -->
<strong>   &#x3C;input type="file" data-advanced="true" name="attachment" style="display:none;" />
</strong>  ...
&#x3C;/form>
</code></pre>

{% hint style="danger" %}
For advanced uploader, `enctype=""` is not required and must be removed from the `<form>`<br>
{% endhint %}

**Step 2: Add the following script before the closing of \</body>**

```html
<! -- Step 2: Add our script to load the file uploader -->
<script src="https://web3forms.com/client/script.js" async defer></script>
```

### Advanced Options

You can configure some options in the advanced uploader like multiple, accept types, max file size etc. See below:

```html
 <input type="file" 
 name="attachment"
 data-form-id="YOUR_ACCESS_KEY_OR_FORM_ID_HERE" (required if not added in `form` )
 data-advanced="true"                       (enable advanced file upload)
 accept="image/*, application/pdf"          (accept only some file types)
 data-max-files="3"                         (Total number of files allowed)
 data-max-file-size="5MB"                   (Maximum file size for single item)
 data-content="Drag & Drop or <i>Browse<i>" (Custom Label in your language)
  />
```

⚠️ **Note on `data-form-id` :** We will try to get the form-id from your form action URL or access key from the hidden `access_key` input inside `<form>`. if you are using them dynamically or in other places, you need to fill that here as well.

### Live Demo on Codepen

<https://codepen.io/surjithctly/pen/RwXBQZR>

### Example Code

```html
<form action="https://api.web3forms.com/submit" method="POST">
    <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE">
    <input type="text" name="name" required>
    <input type="email" name="email" required>
    <textarea name="message" required></textarea>
    
    <! -- Step 1: Add this line (showing advanced options) -->
  <input
        type="file"
        name="attachment"
        data-advanced="true"
        multiple
        data-max-file-size="3MB"
        data-max-files="3" />
    
    <button type="submit">Submit Form</button>
</form>

<! -- Step 2: Add the script -->
<script src="https://web3forms.com/client/script.js" async defer></script>
```

If you add just two lines to your contact form, you will get an advanced file upload form.

{% hint style="warning" %}
Note: You do not need to use `multipart/form-data` if you are using our advanced file uploader. You can use the normal method.
{% endhint %}

### Styling & Theme

You can set your own theme & style as you wish by overwriting the class names provided by filepond. Here's how a dark theme would look like:

```html
<!-- Dark Theme -->

<style>
  .filepond--panel-root {
    background-color: #2c2c2c;
  }
  .filepond--drop-label {
    color: #d4d4d4;
  }
</style>

```

### Client Side Validation

Use this snippet to make the file upload field required and to validate if the file is uploaded or not.

Add the following code block just above the closing of \</body> and make sure `YOUR_FORM_ID` is updated with your form id.

```html
<script>
const form = document.getElementById('YOUR_FORM_ID');

form.addEventListener('submit', function(e) {

    const fileInput = form.querySelector('[name="attachment"]').value;

    if (!fileInput) {
        e.preventDefault();
        alert("Please upload files first!")
        return
    }
});
</script>
```

## Javascript Example

{% hint style="warning" %}
For Javascript usage, you must serialize the data and include `Content-Type` headers as `application/json`
{% endhint %}

<pre class="language-javascript"><code class="lang-javascript">const form = document.getElementById('form');
const submitBtn = form.querySelector('button[type="submit"]');

form.addEventListener('submit', async (e) => {
    e.preventDefault();
    
<strong>    const formData = new FormData(form);
</strong><strong>    const object = Object.fromEntries(formData);
</strong><strong>    const json = JSON.stringify(object);
</strong>    
    const originalText = submitBtn.textContent;
    
    submitBtn.textContent = "Sending...";
    submitBtn.disabled = true;
    
    try {
        const response = await fetch("https://api.web3forms.com/submit", {
            method: "POST",
            body: json,
<strong>           headers: {
</strong><strong>             "Content-Type": "application/json"
</strong><strong>           }
</strong>        });
        
        const data = await response.json();
        
        if (response.ok) {
            alert("Success! Your message has been sent.");
            form.reset();
        } else {
            alert("Error: " + data.message);
        }
        
    } catch (error) {
        alert("Something went wrong. Please try again.");
    } finally {
        submitBtn.textContent = originalText;
        submitBtn.disabled = false;
    }
});
</code></pre>

## Usage with React

Iif you are using react, we suggest you to use the Filepond Library directly.

Also check: [Filepond React](https://github.com/pqina/react-filepond)

**File Uploader Widget**

```jsx
import React, { useState } from 'react';
import { FilePond, registerPlugin } from 'react-filepond';
import 'filepond/dist/filepond.min.css';

// Register plugins if needed
// registerPlugin(FilePondPluginImageExifOrientation, FilePondPluginImagePreview);

function FileUploader() {
  const [files, setFiles] = useState([]);

  const getPresignedUrl = async (file) => {
    try {
      const response = await fetch(`https://api.web3forms.com/upload?file=${file.name}`);
      const data = await response.json();
      return data;
    } catch (error) {
      console.error('Error generating pre-signed URL:', error);
      throw error;
    }
  };

  return (
    <FilePond
      files={files}
      onupdatefiles={setFiles}
      allowMultiple={true}
      maxFiles={3}
      name="attachment"
      labelIdle='Drag & Drop your files or <span class="filepond--label-action">Browse</span>'
      server={{
        process: async (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
          try {
            const { url, key } = await getPresignedUrl(file);
            
            const response = await fetch(url, {
              method: 'PUT',
              body: file,
              headers: {
                'Content-Type': file.type,
              },
            });

            if (response.ok) {
              load(key);
            } else {
              error('Upload failed');
            }
          } catch (err) {
            error('Error uploading file');
          }
        },
      }}
    />
  );
}

export default FileUploader;
```

**Using it with Vanilla React**

```jsx
import React from 'react';
import FileUploader from './FileUploader';

function App() {
  return (
    <div className="App">
      <h1>File Upload Example</h1>
      <form method="POST" action="https://api.web3forms.com/submit">
        <input
          type="hidden"
          name="access_key"
          value="c00d70af-1ca3-466d-98a7-c82408e76e91"
        />
        <input type="text" name="First Name" />
        <FileUploader />
        <input type="submit" value="Submit" />
      </form>
    </div>
  );
}

export default App;
```

**Usage with React Hook Form**

```jsx
import { useForm, Controller } from "react-hook-form";
import FileUploader from './FileUploader';

export default function Support() {
  const { register, handleSubmit } = useForm({
    mode: "onTouched",
  });

  const onSubmit = async (data, e) => {
    // Replace with actual call to Web3Forms
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input type="text" {...register("name")} />
      <Controller
        control={control}
        name="attachment"
        render={({ field }) => (
          <FileUploader
            onChange={(e) => field.onChange(e.cdnUrl)}
          />
        )}
      />
      <button type="submit">Submit</button>
    </form>
  );
}

```


# Webhooks

Send form data to any URL endpoint via HTTP POST. Webhooks enable you to connect Web3Forms with thousands of applications and services, creating powerful automation workflows without writing code.

{% hint style="info" %}
This is a **PRO feature**. You must have an active PRO plan subscription to use this feature.
{% endhint %}

## What are Webhooks?

Webhooks allow you to automatically send form submission data to any HTTP endpoint in real-time. This opens up endless possibilities for integrating with:

* **Automation Platforms**: Zapier, Make (Integromat), n8n, Pipedream
* **CRM Systems**: Salesforce, HubSpot, Pipedrive
* **Email Marketing**: Mailchimp, ConvertKit, SendGrid
* **Project Management**: Asana, Trello, ClickUp
* **Databases**: Airtable, MongoDB, PostgreSQL
* **Communication**: Slack, Discord, Microsoft Teams
* **Custom Applications**: Your own backend services

## Key Features

* ✅ **Universal Compatibility**: Works with any service that accepts HTTP POST requests
* ✅ **Real-time Delivery**: Data is sent immediately after form submission
* ✅ **Secure Transmission**: Data is sent over HTTPS
* ✅ **Automatic Retry**: Failed webhooks are retried automatically
* ✅ **Clean Payload**: Sensitive data is removed before sending

## Setup Instructions

### Step 1: Create a Webhook URL

Webhook URLs can be created using various platforms:

**Recommended Platforms:**

* [**Zapier**](https://zapier.com/) - Connect with 5,000+ apps (Commercial)
* [**Make**](https://www.make.com/) (formerly Integromat) - Advanced automation (Free tier available)
* [**Pipedream**](https://pipedream.com/) - Developer-friendly automation (Generous free plan)
* [**n8n**](https://n8n.io/) - Open-source automation (Self-hosted or cloud)

{% hint style="success" %}
We recommend **Pipedream** if you're technical, as it offers a generous free plan and provides excellent debugging tools.
{% endhint %}

### Step 2: Access the Integrations Tab

1. Log in to your [Web3Forms Dashboard](https://app.web3forms.com)
2. Select the form you want to connect
3. Navigate to the **Integrations** tab in your form settings

### Step 3: Enable Webhook Integration

1. Find the **Webhook** integration card
2. Toggle the switch to enable the integration
3. Paste your webhook URL in the **Webhook URL** field
4. Click the **Save Settings** button

**\[SCREENSHOT PLACEHOLDER: Webhook integration card in Web3Forms dashboard]**

<figure><img src="/files/HzEaAYpb6CVyRVXiwVYI" alt=""><figcaption><p>Webhook Integration Settings</p></figcaption></figure>

## Webhook Payload Structure

Web3Forms sends form data as a JSON payload via HTTP POST request. The payload includes all form fields submitted by the user.

### Request Headers

```
Content-Type: application/json
User-Agent: Web3Forms/1.0
```

### Example Payload

```json
{
  "name": "John Doe",
  "email": "john@example.com",
  "phone": "+1234567890",
  "message": "Hello, I'm interested in your services...",
  "subject": "New Contact Form Submission",
  "from_name": "My Website",
  "submittedAt": "2025-12-22T10:30:00.000Z"
}
```

### What's Included

* **All form fields**: Any field you include in your form (name, email, message, etc.)
* **Custom fields**: Any additional fields you've added
* **Metadata fields**: Subject, from\_name, and other configuration fields

### What's Excluded

For security and privacy, the following data is **removed** before sending:

* `access_key` - Your Web3Forms access key
* `apikey` - Legacy API key field
* `attachment` - File attachments (separate handling)
* `botcheck` - Anti-spam honeypot field
* `recaptcha_response` - CAPTCHA tokens

## Use Cases

### CRM Integration

Automatically add leads to your CRM:

1. Create a webhook in Zapier or Make
2. Connect to your CRM (Salesforce, HubSpot, etc.)
3. Map form fields to CRM fields
4. Leads are added automatically

### Database Storage

Store submissions in a database:

* Send to Airtable for a visual database
* Use Pipedream to insert into PostgreSQL or MongoDB
* Create custom data warehousing solutions

### Team Notifications

Send notifications to multiple platforms:

* Slack channels for team awareness
* Discord servers for community projects
* Microsoft Teams for enterprise environments
* Email notifications to multiple recipients

### Email Marketing

Add subscribers to your email list:

* Connect to Mailchimp, ConvertKit, or SendGrid
* Automatically create contact lists
* Trigger welcome email sequences

### Custom Processing

Build custom workflows:

* Validate and enrich data
* Perform background processing
* Trigger custom business logic
* Integrate with proprietary systems

## Popular Integrations

### Zapier

Connect Web3Forms with 5,000+ apps using Zapier:

1. Create a new Zap in Zapier
2. Choose **Webhooks by Zapier** as the trigger
3. Select **Catch Hook**
4. Copy the webhook URL
5. Paste it in Web3Forms webhook settings
6. Test and configure your automation

[Learn more about Zapier integration →](/getting-started/integrations/soon/zapier)

### Make (Integromat)

Build complex automation scenarios:

1. Create a new Scenario in Make
2. Add a **Webhook** module as the trigger
3. Choose **Custom webhook**
4. Copy the webhook URL
5. Add it to Web3Forms
6. Build your automation workflow

[Learn more about Make integration →](/getting-started/integrations/soon/integromat)

### Pipedream

Developer-friendly automation with code:

1. Create a new Workflow in Pipedream
2. Select **HTTP / Webhook** as the trigger
3. Copy the endpoint URL
4. Add it to Web3Forms
5. Use pre-built actions or write custom Node.js code

### n8n

Open-source workflow automation:

1. Create a new Workflow in n8n
2. Add a **Webhook** node
3. Configure the webhook path
4. Copy the webhook URL
5. Connect it to Web3Forms
6. Build your self-hosted automation

## Testing Your Webhook

### Test in Web3Forms

1. Submit a test entry through your form
2. Check if the webhook was triggered
3. Verify data arrived at your endpoint

### Debug with Webhook Testing Tools

Use these tools to inspect webhook payloads:

* [**Webhook.site**](https://webhook.site/) - Free webhook testing
* [**RequestBin**](https://requestbin.com/) - Inspect HTTP requests
* [**Pipedream RequestBin**](https://pipedream.com/requestbin) - Developer-focused debugging

### Check Delivery Status

Monitor webhook delivery in your automation platform:

* Check execution logs in Zapier/Make/Pipedream
* Review error messages if delivery fails
* Verify payload structure matches expectations

## Troubleshooting

### Webhook Not Triggering

* **Verify URL**: Ensure the webhook URL is correct and accessible
* **Check Status**: Make sure the integration is enabled (toggle on)
* **Test Endpoint**: Use webhook testing tools to verify your endpoint works
* **Check Logs**: Review logs in your automation platform
* **Firewall**: Ensure your endpoint isn't blocked by a firewall

### Invalid URL Error

* Webhook URL must start with `https://`
* URL must be publicly accessible
* Don't include spaces or invalid characters
* Test the URL in a browser or curl command

### Data Not Received

* Check the payload structure in your automation platform
* Verify field names match what you expect
* Ensure your endpoint is processing JSON correctly
* Check for rate limits on your receiving service

### Timeout Errors

* Webhook endpoints must respond within 30 seconds
* If processing takes longer, return 200 OK immediately
* Process data asynchronously in the background

## Advanced Configuration

### Multiple Webhooks

To send data to multiple endpoints:

1. Use one webhook URL in Web3Forms
2. Configure your automation platform to forward to multiple services
3. Example: Zapier → Send to both Slack and Airtable

### Data Transformation

Transform data before sending to your destination:

* Use automation platforms to map and modify fields
* Filter submissions based on conditions
* Enrich data with external API calls
* Format data for specific integrations

### Conditional Logic

Send to different endpoints based on form data:

* Use automation platforms to add conditional routing
* Example: Send enterprise leads to sales team, others to support
* Filter spam or test submissions

### Error Handling

Handle webhook failures gracefully:

* Set up retry logic in your automation platform
* Create error notifications for failed webhooks
* Log failures for debugging
* Implement fallback endpoints

## Security Best Practices

### Protect Your Webhook URLs

* Never share webhook URLs publicly
* Regenerate URLs if compromised
* Use URL parameters for authentication if supported
* Monitor webhook activity for unusual patterns

### Validate Incoming Data

In your webhook handler:

* Validate data types and formats
* Sanitize input to prevent injection attacks
* Check for required fields
* Implement rate limiting

### Use HTTPS

* Always use HTTPS endpoints
* Never use HTTP for webhooks
* Ensure SSL certificates are valid

## Related Integrations

* [Google Sheets Integration](/getting-started/integrations/google-sheets) - Direct spreadsheet sync
* [Slack Integration](/getting-started/integrations/slack) - Team notifications
* [Discord Integration](/getting-started/integrations/discord) - Community notifications
* [Telegram Integration](/getting-started/integrations/telegram-notifications) - Mobile notifications

## Additional Resources

* [Zapier Webhooks Documentation](https://zapier.com/page/webhooks/)
* [Make Webhooks Guide](https://www.make.com/en/help/tools/webhooks)
* [Pipedream Workflows](https://pipedream.com/docs/workflows/)
* [n8n Documentation](https://docs.n8n.io/)

## Need Help?

If you encounter any issues with webhooks:

* Email <support@web3forms.com>
* [Contribute to our documentation on Github](https://github.com/surjithctly/web3forms-docs)
* Check the documentation of your automation platform


# Restrict to Domain

Whitelist a domain to send the form from.

{% hint style="info" %}
Heads Up! This is a PRO feature. You must have an active subscription to use this feature.
{% endhint %}

You can restrict the form from sending only through a whitelisted domain. This will potentially reduce spam attacks. So even if someone else got the access key, they cannot send emails to you. Only emails from your website are counted.

To enable this feature, you must add the domains you wanted to use in form settings. You can add multiple domains separated with comma. Do not add protocols like https\:// in the domain name.

{% hint style="info" %}
Only root or subdomain allowed. Once added forms will only work on the added domain and it will not work locally. So you must add this feature only after testing.
{% endhint %}

<figure><img src="/files/CoRNvU64gclS8mDNn1SP" alt=""><figcaption></figcaption></figure>


# Intro Text

Email Intro Text customizations are available for all Paid users. You can change them in Form Settings in [https://app.webforms.com](https://app.webforms.com/).

<figure><img src="/files/ttdAzXQ8oxCuZv5SjeCb" alt="" width="563"><figcaption></figcaption></figure>


# Examples


# Basic HTML Contact Form

### Basic Example

```html
<form action="https://api.web3forms.com/submit" method="POST">

    <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE">

    <input type="text" name="name" required>
    <input type="email" name="email" required>
    <textarea name="message" required></textarea>
    <input type="hidden" name="redirect" value="https://web3forms.com/success">

    <button type="submit">Submit Form</button>

</form>
```

## Contact form with TailwindCSS

[Check it out on Codepen](https://codepen.io/surjithctly/pen/ZELQggB)

```markup
<div class="flex items-center min-h-screen bg-gray-50 dark:bg-gray-900">
  <div class="container mx-auto">
    <div class="max-w-md mx-auto my-10 bg-white p-5 rounded-md shadow-sm">
      <div class="text-center">
        <h1
          class="my-3 text-3xl font-semibold text-gray-700 dark:text-gray-200"
        >
          Contact Us
        </h1>
        <p class="text-gray-400 dark:text-gray-400">
          Fill up the form below to send us a message.
        </p>
      </div>
      <div class="m-7">
        <form action="https://api.web3forms.com/submit" method="POST" id="form">
          <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE" />
          <input
            type="hidden"
            name="subject"
            value="New Submission from Web3Forms"
          />
          <input
            type="hidden"
            name="redirect"
            value="https://web3forms.com/success"
          />
          <input type="checkbox" name="botcheck" id="" style="display: none;" />
          <div class="mb-6">
            <label
              for="name"
              class="block mb-2 text-sm text-gray-600 dark:text-gray-400"
              >Full Name</label
            >
            <input
              type="text"
              name="name"
              id="name"
              placeholder="John Doe"
              required
              class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500"
            />
          </div>
          <div class="mb-6">
            <label
              for="email"
              class="block mb-2 text-sm text-gray-600 dark:text-gray-400"
              >Email Address</label
            >
            <input
              type="email"
              name="email"
              id="email"
              placeholder="you@company.com"
              required
              class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500"
            />
          </div>
          <div class="mb-6">
            <label for="phone" class="text-sm text-gray-600 dark:text-gray-400"
              >Phone Number</label
            >
            <input
              type="text"
              name="phone"
              id="phone"
              placeholder="+1 (555) 1234-567"
              required
              class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500"
            />
          </div>
          <div class="mb-6">
            <label
              for="message"
              class="block mb-2 text-sm text-gray-600 dark:text-gray-400"
              >Your Message</label
            >

            <textarea
              rows="5"
              name="message"
              id="message"
              placeholder="Your Message"
              class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500"
              required
            ></textarea>
          </div>
          <div class="mb-6">
            <button
              type="submit"
              class="w-full px-3 py-4 text-white bg-indigo-500 rounded-md focus:bg-indigo-600 focus:outline-none"
            >
              Send Message
            </button>
          </div>
          <p class="text-base text-center text-gray-400" id="result"></p>
        </form>
      </div>
    </div>
  </div>
</div>
```


# Advanced - All Options

Here's an example with all possible customization options. Checkout other pages for more examples.

```html
<form action="https://api.web3forms.com/submit" method="POST">

  <!-- REQUIRED: Your Access key here. Don't worry this can be public -->
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE">

  <!-- Optional: Subject an be prefilled using type="hidden"
       or type="text" for normal user submitted input -->
  <input type="hidden" name="subject" value="New Submission from Web3Forms">

  <!-- Optional: From Name you want to see in the email
       Default is "Notifications". you can overwrite here -->
  <input type="hidden" name="from_name" value="Your Website Name">

  <!-- Optional: To send the form submission as CC email
       This feature available to PRO Plan users only -->
  <input type="hidden" name="ccemail" value="partner@example.com">

  <!-- Optional: Default replyto will be "email" field (if available)
       you may overwrite replyto with different email here -->
  <input type="hidden" name="replyto" value="customer@example.com">

  <!-- Optional: Custom Redirection or Thank you Page
       Make sure you add full URL including https:// -->
  <input type="hidden" name="redirect" value="https://web3forms.com/success">

  <!-- Optional: But Recommended: To Prevent SPAM Submission.
       Make sure its hidden by default -->
  <input type="checkbox" name="botcheck" class="hidden" style="display: none;">
  
   <!-- hCaptcha: Recommended for Advanced Spam Protection. -->
  <div class="h-captcha" data-captcha="true"></div>

  <!-- Google reCaptcha & Cloudflare Turnstile:
       This feature is available for paid users only -->
  <input type="hidden" name="recaptcha_response" id="recaptchaResponse">
  <div class="cf-turnstile" data-sitekey="<YOUR_SITE_KEY>"></div>
  
  <!-- Webhooks: Send your form data to Notion, Google Sheets or Zapier.
       This feature is available for paid users only -->
  <input type="hidden" name="webhook" value="WEBHOOK_URL_HERE" />

  <!-- Attachments: Make sure the <form> has enctype="multipart/form-data"
       This feature is available for paid users only -->
  <input type="file" name="attachment" />
  
  <!-- Advanced File Upload: This feature is available for paid users only -->
  <input type="hidden" data-fileupload="true" />

  <!-- Custom Form Data: Form data you wish to receive in email. -->
  <input type="email" name="email" required>
  <input type="text" name="First Name" required>
  <input type="text" name="Phone Number" required>
  <textarea name="message" required></textarea>

  <button type="submit">Submit Form</button>

</form>

<!-- Required only if you are using hCaptcha or Advanced File Upload. -->
<script src="https://web3forms.com/client/script.js" async defer></script>

```


# Ajax Contact Form using Javascript

[Check it out on Codepen](https://codepen.io/surjithctly/pen/OJWMKYG)

## HTML

```markup
<!-- 
    =======================================================================

    This is a working contact form. To receive email, 
    Replace YOUR_ACCESS_KEY_HERE with your actual Access Key.

    Create Access Key here 👉 https://web3forms.com/

    =======================================================================
 -->

<div class="flex items-center min-h-screen bg-gray-50 dark:bg-gray-900">
  <div class="container mx-auto">
    <div class="max-w-md mx-auto my-10 bg-white p-5 rounded-md shadow-sm">
      <div class="text-center">
        <h1
          class="my-3 text-3xl font-semibold text-gray-700 dark:text-gray-200"
        >
          Contact Us
        </h1>
        <p class="text-gray-400 dark:text-gray-400">
          Fill up the form below to send us a message.
        </p>
      </div>
      <div class="m-7">
        <form action="https://api.web3forms.com/submit" method="POST" id="form">
          <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE" />
          <input
            type="hidden"
            name="subject"
            value="New Submission from Web3Forms"
          />
          <input type="checkbox" name="botcheck" id="" style="display: none;" />

          <div class="mb-6">
            <label
              for="name"
              class="block mb-2 text-sm text-gray-600 dark:text-gray-400"
              >Full Name</label
            >
            <input
              type="text"
              name="name"
              id="name"
              placeholder="John Doe"
              required
              class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500"
            />
          </div>
          <div class="mb-6">
            <label
              for="email"
              class="block mb-2 text-sm text-gray-600 dark:text-gray-400"
              >Email Address</label
            >
            <input
              type="email"
              name="email"
              id="email"
              placeholder="you@company.com"
              required
              class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500"
            />
          </div>
          <div class="mb-6">
            <label for="phone" class="text-sm text-gray-600 dark:text-gray-400"
              >Phone Number</label
            >
            <input
              type="text"
              name="phone"
              id="phone"
              placeholder="+1 (555) 1234-567"
              required
              class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500"
            />
          </div>
          <div class="mb-6">
            <label
              for="message"
              class="block mb-2 text-sm text-gray-600 dark:text-gray-400"
              >Your Message</label
            >

            <textarea
              rows="5"
              name="message"
              id="message"
              placeholder="Your Message"
              class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500"
              required
            ></textarea>
          </div>
          <div class="mb-6">
            <button
              type="submit"
              class="w-full px-3 py-4 text-white bg-indigo-500 rounded-md focus:bg-indigo-600 focus:outline-none"
            >
              Send Message
            </button>
          </div>
          <p class="text-base text-center text-gray-400" id="result"></p>
        </form>
      </div>
    </div>
  </div>
</div>
```

## Javascript

```javascript
const form = document.getElementById("form");
const result = document.getElementById("result");

form.addEventListener("submit", function (e) {
  e.preventDefault();
  
  const formData = new FormData(form);
  const object = Object.fromEntries(formData);
  const json = JSON.stringify(object);
  
  result.innerHTML = "Please wait...";

  fetch("https://api.web3forms.com/submit", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json",
    },
    body: json,
  })
    .then(async (response) => {
      let json = await response.json();
      if (response.status == 200) {
        result.innerHTML = json.message;
        result.classList.remove("text-gray-500");
        result.classList.add("text-green-500");
      } else {
        console.log(response);
        result.innerHTML = json.message;
        result.classList.remove("text-gray-500");
        result.classList.add("text-red-500");
      }
    })
    .catch((error) => {
      console.log(error);
      result.innerHTML = "Something went wrong!";
    })
    .then(function () {
      form.reset();
      setTimeout(() => {
        result.style.display = "none";
      }, 5000);
    });
});
```


# Multi Column Contact Form

[Check it out on Codepen](https://codepen.io/surjithctly/pen/poRgMdz)

## HTML

```markup
<!-- 
    =======================================================================

    This is a working contact form. To receive email, 
    Replace YOUR_ACCESS_KEY_HERE with your actual Access Key.

    Create Access Key here 👉 https://web3forms.com/

    =======================================================================
 -->

<div class="flex items-center min-h-screen bg-gray-100 dark:bg-gray-900">
  <div class="container mx-auto">
    <div class="max-w-xl mx-auto my-10 bg-white p-5 rounded-md shadow-sm">
      <div class="text-center">
        <h1
          class="my-3 text-3xl font-semibold text-gray-700 dark:text-gray-200"
        >
          Contact Us
        </h1>
        <p class="text-gray-400 dark:text-gray-400">
          Fill up the form below to send us a message.
        </p>
      </div>
      <div class="m-7">
        <form action="https://api.web3forms.com/submit" method="POST" id="form">
          <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE" />
          <input
            type="hidden"
            name="subject"
            value="New Submission from Web3Forms"
          />
          <input type="checkbox" name="botcheck" id="" style="display: none;" />

          <div class="flex mb-6 space-x-4">
            <div class="w-full md:w-1/2">
              <label
                for="fname"
                class="block mb-2 text-sm text-gray-600 dark:text-gray-400"
                >First Name</label
              >
              <input
                type="text"
                name="name"
                id="first_name"
                placeholder="John"
                required
                class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500"
              />
            </div>
            <div class="w-full md:w-1/2">
              <label
                for="lname"
                class="block mb-2 text-sm text-gray-600 dark:text-gray-400"
                >Last Name</label
              >
              <input
                type="text"
                name="last_name"
                id="lname"
                placeholder="Doe"
                required
                class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500"
              />
            </div>
          </div>

          <div class="flex mb-6 space-x-4">
            <div class="w-full md:w-1/2">
              <label
                for="email"
                class="block mb-2 text-sm text-gray-600 dark:text-gray-400"
                >Email Address</label
              >
              <input
                type="email"
                name="email"
                id="email"
                placeholder="you@company.com"
                required
                class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500"
              />
            </div>

            <div class="w-full md:w-1/2">
              <label
                for="phone"
                class="block text-sm mb-2 text-gray-600 dark:text-gray-400"
                >Phone Number</label
              >
              <input
                type="text"
                name="phone"
                id="phone"
                placeholder="+1 (555) 1234-567"
                required
                class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500"
              />
            </div>
          </div>
          <div class="mb-6">
            <label
              for="message"
              class="block mb-2 text-sm text-gray-600 dark:text-gray-400"
              >Your Message</label
            >

            <textarea
              rows="5"
              name="message"
              id="message"
              placeholder="Your Message"
              class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500"
              required
            ></textarea>
          </div>
          <div class="mb-6">
            <button
              type="submit"
              class="w-full px-3 py-4 text-white bg-indigo-500 rounded-md focus:bg-indigo-600 focus:outline-none"
            >
              Send Message
            </button>
          </div>
          <p class="text-base text-center text-gray-400" id="result"></p>
        </form>
      </div>
    </div>
  </div>
</div>
```

## Javascript

```javascript
const form = document.getElementById("form");
const result = document.getElementById("result");

form.addEventListener("submit", function (e) {
  e.preventDefault();
  
  const formData = new FormData(form);
  const object = Object.fromEntries(formData);
  const json = JSON.stringify(object);
  
  result.innerHTML = "Please wait...";

  fetch("https://api.web3forms.com/submit", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json",
    },
    body: json,
  })
    .then(async (response) => {
      let json = await response.json();
      if (response.status == 200) {
        result.innerHTML = json.message;
        result.classList.remove("text-gray-500");
        result.classList.add("text-green-500");
      } else {
        console.log(response);
        result.innerHTML = json.message;
        result.classList.remove("text-gray-500");
        result.classList.add("text-red-500");
      }
    })
    .catch((error) => {
      console.log(error);
      result.innerHTML = "Something went wrong!";
    })
    .then(function () {
      form.reset();
      setTimeout(() => {
        result.style.display = "none";
      }, 5000);
    });
});
```


# Javascript Form Validation

[Check it out on Codepen](https://codepen.io/surjithctly/pen/LYxNPEm)

## HTML

```markup
<!-- 
    =======================================================================

    This is a working contact form. To receive email, 
    Replace YOUR_ACCESS_KEY_HERE with your actual Access Key.

    Create Access Key here 👉 https://web3forms.com/

    =======================================================================
 -->

<div class="flex items-center min-h-screen bg-gray-100 dark:bg-gray-900">
  <div class="container mx-auto">
    <div class="max-w-xl mx-auto my-10 bg-white p-5 rounded-md shadow-sm">
      <div class="text-center">
        <h1
          class="my-3 text-3xl font-semibold text-gray-700 dark:text-gray-200"
        >
          Contact Us
        </h1>
        <p class="text-gray-400 dark:text-gray-400">
          Fill up the form below to send us a message.
        </p>
      </div>
      <div class="m-7">
        <form
          action="https://api.web3forms.com/submit"
          method="POST"
          id="form"
          class="needs-validation"
          novalidate
        >
          <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE" />
          <input
            type="hidden"
            name="subject"
            value="New Submission from Web3Forms"
          />
          <input type="checkbox" name="botcheck" id="" style="display: none;" />

          <div class="flex mb-6 space-x-4">
            <div class="w-full md:w-1/2">
              <label
                for="fname"
                class="block mb-2 text-sm text-gray-600 dark:text-gray-400"
                >First Name</label
              >
              <input
                type="text"
                name="name"
                id="first_name"
                placeholder="John"
                required
                class="w-full px-3 py-2 placeholder-gray-300 border-2 border-gray-200 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300"
              />
              <div
                class="empty-feedback invalid-feedback text-red-400 text-sm mt-1"
              >
                Please provide your first name.
              </div>
            </div>
            <div class="w-full md:w-1/2">
              <label
                for="lname"
                class="block mb-2 text-sm text-gray-600 dark:text-gray-400"
                >Last Name</label
              >
              <input
                type="text"
                name="last_name"
                id="lname"
                placeholder="Doe"
                required
                class="w-full px-3 py-2 placeholder-gray-300 border-2 border-gray-200 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300"
              />
              <div
                class="empty-feedback invalid-feedback text-red-400 text-sm mt-1"
              >
                Please provide your last name.
              </div>
            </div>
          </div>

          <div class="flex mb-6 space-x-4">
            <div class="w-full md:w-1/2">
              <label
                for="email"
                class="block mb-2 text-sm text-gray-600 dark:text-gray-400"
                >Email Address</label
              >
              <input
                type="email"
                name="email"
                id="email"
                placeholder="you@company.com"
                required
                class="w-full px-3 py-2 placeholder-gray-300 border-2 border-gray-200 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300"
              />
              <div class="empty-feedback text-red-400 text-sm mt-1">
                Please provide your email address.
              </div>
              <div class="invalid-feedback text-red-400 text-sm mt-1">
                Please provide a valid email address.
              </div>
            </div>

            <div class="w-full md:w-1/2">
              <label
                for="phone"
                class="block text-sm mb-2 text-gray-600 dark:text-gray-400"
                >Phone Number</label
              >
              <input
                type="text"
                name="phone"
                id="phone"
                placeholder="+1 (555) 1234-567"
                required
                class="w-full px-3 py-2 placeholder-gray-300 border-2 border-gray-200 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300"
              />

              <div
                class="empty-feedback invalid-feedback text-red-400 text-sm mt-1"
              >
                Please provide your phone number.
              </div>
            </div>
          </div>
          <div class="mb-6">
            <label
              for="message"
              class="block mb-2 text-sm text-gray-600 dark:text-gray-400"
              >Your Message</label
            >

            <textarea
              rows="5"
              name="message"
              id="message"
              placeholder="Your Message"
              class="w-full px-3 py-2 placeholder-gray-300 border-2 border-gray-200 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300"
              required
            ></textarea>
            <div
              class="empty-feedback invalid-feedback text-red-400 text-sm mt-1"
            >
              Please enter your message.
            </div>
          </div>
          <div class="mb-6">
            <button
              type="submit"
              class="w-full px-3 py-4 text-white bg-indigo-500 rounded-md focus:bg-indigo-600 focus:outline-none"
            >
              Send Message
            </button>
          </div>
          <p class="text-base text-center text-gray-400" id="result"></p>
        </form>
      </div>
    </div>
  </div>
</div>
```

## CSS

```css
.invalid-feedback,
.empty-feedback {
  display: none;
}

.was-validated :placeholder-shown:invalid ~ .empty-feedback {
  display: block;
}

.was-validated :not(:placeholder-shown):invalid ~ .invalid-feedback {
  display: block;
}

.is-invalid,
.was-validated :invalid {
  border-color: #dc3545;
}
```

## Javascript

```javascript
(function () {
  "use strict";
  /*
   * Form Validation
   */

  // Fetch all the forms we want to apply custom validation styles to
  const forms = document.querySelectorAll(".needs-validation");
  const result = document.getElementById("result");
  // Loop over them and prevent submission
  Array.prototype.slice.call(forms).forEach(function (form) {
    form.addEventListener(
      "submit",
      function (event) {
        if (!form.checkValidity()) {
          event.preventDefault();
          event.stopPropagation();

          form.querySelectorAll(":invalid")[0].focus();
        } else {
          /*
           * Form Submission using fetch()
           */
          event.preventDefault();
          event.stopPropagation();
          
          const formData = new FormData(form);
          const object = Object.fromEntries(formData);
          const json = JSON.stringify(object);
          result.innerHTML = "Please wait...";

          fetch("https://api.web3forms.com/submit", {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
              Accept: "application/json",
            },
            body: json,
          })
            .then(async (response) => {
              let json = await response.json();
              if (response.status == 200) {
                result.innerHTML = json.message;
                result.classList.remove("text-gray-500");
                result.classList.add("text-green-500");
              } else {
                console.log(response);
                result.innerHTML = json.message;
                result.classList.remove("text-gray-500");
                result.classList.add("text-red-500");
              }
            })
            .catch((error) => {
              console.log(error);
              result.innerHTML = "Something went wrong!";
            })
            .then(function () {
              form.reset();
              form.classList.remove("was-validated");
              setTimeout(() => {
                result.style.display = "none";
              }, 5000);
            });
        }
        form.classList.add("was-validated");
      },
      false
    );
  });
})();
```


# Contact Form with Dark Mode

[Check it out on Codepen](https://codepen.io/surjithctly/pen/MWJygKb)

## HTML

```markup
<!-- 
    =======================================================================

    This is a working contact form. To receive email, 
    Replace YOUR_ACCESS_KEY_HERE with your actual Access Key.

    Create Access Key here 👉 https://web3forms.com/

    =======================================================================
 -->

<div class="flex items-center min-h-screen bg-gray-900">
  <div class="container mx-auto">
    <div class="max-w-md mx-auto my-10 bg-gray-800 p-5 rounded-md shadow-sm">
      <div class="text-center">
        <h1 class="my-3 text-3xl font-semibold text-gray-100">Contact Us</h1>
        <p class="text-gray-400 dark:text-gray-400">
          Fill up the form below to send us a message.
        </p>
      </div>
      <div class="m-7">
        <form action="https://api.web3forms.com/submit" method="POST" id="form">
          <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE" />
          <input
            type="hidden"
            name="subject"
            value="New Submission from Web3Forms"
          />
          <input type="checkbox" name="botcheck" id="" style="display: none;" />

          <div class="mb-6">
            <label for="name" class="block mb-2 text-sm text-gray-400"
              >Full Name</label
            >
            <input
              type="text"
              name="name"
              id="name"
              placeholder="John Doe"
              required
              class="w-full px-3 py-2 h-12 rounded-sm placeholder-gray-500 text-gray-900 bg-gray-100 text-sm focus:outline-none"
            />
          </div>
          <div class="mb-6">
            <label for="email" class="block mb-2 text-sm text-gray-400"
              >Email Address</label
            >
            <input
              type="email"
              name="email"
              id="email"
              placeholder="you@company.com"
              required
              class="w-full px-3 py-2 h-12 rounded-sm placeholder-gray-500 text-gray-900 bg-gray-100 text-sm focus:outline-none"
            />
          </div>
          <div class="mb-6">
            <label for="phone" class="block mb-2 text-sm text-gray-400"
              >Phone Number</label
            >
            <input
              type="text"
              name="phone"
              id="phone"
              placeholder="+1 (555) 1234-567"
              required
              class="w-full px-3 py-2 h-12 rounded-sm placeholder-gray-500 text-gray-900 bg-gray-100 text-sm focus:outline-none"
            />
          </div>
          <div class="mb-6">
            <label for="message" class="block mb-2 text-sm text-gray-400"
              >Your Message</label
            >

            <textarea
              rows="5"
              name="message"
              id="message"
              placeholder="Your Message"
              class="w-full px-3 py-2 rounded-sm placeholder-gray-500 text-gray-900 bg-gray-100 text-sm focus:outline-none"
              required
            ></textarea>
          </div>
          <div class="mb-6">
            <button
              type="submit"
              class="w-full bg-indigo-600 inline-block text-white no-underline hover:text-indigo-100 py-4 px-4 rounded-sm focus:outline-none"
            >
              Send Message
            </button>
          </div>
          <p class="text-base text-center text-gray-400" id="result"></p>
        </form>
      </div>
    </div>
  </div>
</div>
```

## Javascript

```javascript
const form = document.getElementById("form");
const result = document.getElementById("result");

form.addEventListener("submit", function (e) {
  e.preventDefault();
  
  const formData = new FormData(form);
  const object = Object.fromEntries(formData);
  const json = JSON.stringify(object);
  result.innerHTML = "Please wait...";

  fetch("https://api.web3forms.com/submit", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json",
    },
    body: json,
  })
    .then(async (response) => {
      let json = await response.json();
      if (response.status == 200) {
        result.innerHTML = json.message;
        result.classList.remove("text-gray-500");
        result.classList.add("text-green-500");
      } else {
        console.log(response);
        result.innerHTML = json.message;
        result.classList.remove("text-gray-500");
        result.classList.add("text-red-500");
      }
    })
    .catch((error) => {
      console.log(error);
      result.innerHTML = "Something went wrong!";
    })
    .then(function () {
      form.reset();
      setTimeout(() => {
        result.style.display = "none";
      }, 5000);
    });
});
```


# Raw Contact Form

[Check it out on Codepen](https://codepen.io/surjithctly/pen/WNRwwdx)

## HTML

```markup
<!-- 
    =======================================================================

    This is a working contact form. To receive email, 
    Replace YOUR_ACCESS_KEY_HERE with your actual Access Key.

    Create Access Key here 👉 https://web3forms.com/

    =======================================================================
 -->

<form action="https://api.web3forms.com/submit" method="POST" id="form">
  <fieldset>
    <legend>Contact Form</legend>
    <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE" />
    <input type="hidden" name="subject" value="New Submission from Web3Forms" />
    <input
      type="hidden"
      name="redirect"
      value="https://web3forms.com/success"
    />
    <input type="checkbox" name="botcheck" id="" style="display: none;" />
    <div>
      <label for="name">Full Name</label><br />
      <input
        type="text"
        name="name"
        id="name"
        placeholder="John Doe"
        required
      />
      <br /><br />
    </div>
    <div>
      <label for="email">Email Address</label><br />
      <input
        type="email"
        name="email"
        id="email"
        placeholder="you@company.com"
        required
      /><br /><br />
    </div>
    <div>
      <label for="phone">Phone Number</label>
      <br />
      <input
        type="text"
        name="phone"
        id="phone"
        placeholder="+1 (555) 1234-567"
        required
      /><br /><br />
    </div>
    <div>
      <label for="message">Your Message</label>
      <br />
      <textarea
        rows="5"
        name="message"
        id="message"
        placeholder="Your Message"
        required
      ></textarea
      ><br /><br />
    </div>

    <button type="submit">Send Message</button>
  </fieldset>
</form>
```

## CSS

```css
form {
  max-width: 500px;
  margin: 150px auto;
}

fieldset {
  padding: 30px;
}

input,
textarea,
button {
  width: 100%;
}
```


# Google reCaptcha v3

HTML (Styled using TailwindCSS)

```html
<div class="flex items-center min-h-screen bg-gray-100 dark:bg-gray-900">
  <div class="container mx-auto">
    <div class="max-w-md mx-auto my-10 bg-white p-5 rounded-md shadow-sm">
      <div class="text-center">
        <h1 class="my-3 text-3xl font-semibold text-gray-700 dark:text-gray-200">
          Contact Us
        </h1>
        <p class="text-gray-400 dark:text-gray-400">
          Fill up the form below to send us a message.
        </p>
      </div>
      <div class="m-7">
        <form action="https://api.web3forms.com/submit" method="POST" id="form">
          <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE" />
          <input type="hidden" name="subject" value="New Submission from Web3Forms" />
          <input type="checkbox" name="botcheck" id="" style="display: none;" />
          <!-- Google reCaptcha v3: To Prevent SPAM Submission.PRO Plan only -->
          <input type="hidden" name="recaptcha_response" id="recaptchaResponse">

          <div class="mb-6">
            <label for="name" class="block mb-2 text-sm text-gray-600 dark:text-gray-400">Full Name</label>
            <input type="text" name="name" id="name" placeholder="John Doe" required class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500" />
          </div>
          <div class="mb-6">
            <label for="email" class="block mb-2 text-sm text-gray-600 dark:text-gray-400">Email Address</label>
            <input type="email" name="email" id="email" placeholder="you@company.com" required class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500" />
          </div>
          <div class="mb-6">
            <label for="phone" class="text-sm text-gray-600 dark:text-gray-400">Phone Number</label>
            <input type="text" name="phone" id="phone" placeholder="+1 (555) 1234-567" required class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500" />
          </div>
          <div class="mb-6">
            <label for="message" class="block mb-2 text-sm text-gray-600 dark:text-gray-400">Your Message</label>

            <textarea rows="5" name="message" id="message" placeholder="Your Message" class="w-full px-3 py-2 placeholder-gray-300 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-500 dark:border-gray-600 dark:focus:ring-gray-900 dark:focus:border-gray-500" required></textarea>
          </div>
          <div class="mb-6">
            <button type="submit" class="w-full px-3 py-4 text-white bg-indigo-500 rounded-md focus:bg-indigo-600 focus:outline-none">
              Send Message
            </button>
          </div>
          <p class="text-base text-center text-gray-400" id="result"></p>
        </form>
      </div>
    </div>
  </div>
</div>

<!-- Needed for Recaptcha -->

<script src="https://www.google.com/recaptcha/api.js?render=YOUR_PUBLIC_KEY_HERE"></script>
<script>
  grecaptcha.ready(function() {
    grecaptcha.execute('YOUR_PUBLIC_KEY_HERE', {
      action: 'contact'
    }).then(function(token) {
      recaptchaResponse.value = token;
    });
  });
</script>
```

Javascript

```javascript
const form = document.getElementById("form");
const result = document.getElementById("result");

form.addEventListener("submit", function (e) {
  e.preventDefault();
  
  const formData = new FormData(form);
  const object = Object.fromEntries(formData);
  const json = JSON.stringify(object);
  result.innerHTML = "Please wait...";

  fetch("https://api.web3forms.com/submit", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json"
    },
    body: json
  })
    .then(async (response) => {
      let json = await response.json();
      if (response.status == 200) {
        result.innerHTML = json.message;
        result.classList.remove("text-gray-500");
        result.classList.add("text-green-500");
      } else {
        console.log(response);
        result.innerHTML = json.message;
        result.classList.remove("text-gray-500");
        result.classList.add("text-red-500");
      }
    })
    .catch((error) => {
      console.log(error);
      result.innerHTML = "Something went wrong!";
    })
    .then(function () {
      form.reset();
      setTimeout(() => {
        result.style.display = "none";
      }, 5000);
    });
});

```


# File Upload Form

### File Upload using Multipart/form-data

```html
<form action="https://api.web3forms.com/submit" enctype="multipart/form-data" method="POST">
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE">
  <input type="text" name="name" required>
  <input type="email" name="email" required>
  <input type="file" name="attachment" />
  <button type="submit">Submit Form</button>
</form>
```

## File upload with Javascript

#### Here's an example code with Javascript

```html
<form id="myForm" method="POST">
  ...
  <input type="file" id="attachment" name="attachment" />
  ...  
  <button type="submit">Submit Form</button>
</form>
```

```javascript
const form = document.getElementById("myForm");

form.addEventListener("submit", function (e) {
  e.preventDefault();
  
  const formData = new FormData(form);
  
  formData.append("access_key", "YOUR_ACCESS_KEY_HERE");
  formData.append("subject", "New Submission from Web3Forms");

  const file = document.getElementById("attachment");
  const filesize = file.files[0].size / 1024;

  if (filesize > 1000) {
    alert("Please upload file less than 1 MB");
    return;
  }
  
  // Don't add `headers` or `content-type` in this fetch call
  // Since it contains attachments, the browser auto-adds them. 
  fetch("https://api.web3forms.com/submit", {
    method: "POST",
    body: formData
  })
    .then(async (response) => {
      let json = await response.json();
      if (response.status == 200) {
        console.log(json.message);
      } else {
        console.log(response);
      }
    })
    .catch((error) => {
      console.log(error);
    })
    .then(function () {
      form.reset();
    });
});

```


# With Multiple Checkbox

How to integrate Checkbox with Web3Forms Properly

There are some confusions on how multiple checkboxes works and how to to integrate it with Web3Forms.

If you simply added a checkbox like this and sent the data to a regular form action, `check` would return `on` or `off` based on whether the user checked or not.

```html
<input type="checkbox" name="check">
```

However, if you need to add a value to your checkbox, you need to define it like this:

```
<input type="checkbox" name="check" value="checked">
```

Now, this would return `check: checked`

### Multiple Checkboxes

You need to add the same **name** with different values for multiple checkboxes. See:

```html

<label>Interests</label>
<input type="checkbox" id="coding" name="interest" value="coding" />
<input type="checkbox" id="music" name="interest" value="music" />

```

Web3Forms will then automatically parse them to be comma-separated like this:

```
Interests
coding,music
```

### Multiple Checkbox with Javascript

If you are using javascript, you have to manually stringify multiple data like this before sending the request to Web3Forms API. See example code:

```javascript
const formData = new FormData(form);
const interests = [];
 
form.querySelectorAll('input[name="interest"]:checked').forEach((checkbox) => {
    interests.push(checkbox.value);
});
  
formData.set('interest', interests);
```

This will set the checkbox as you intended.

#### Live Demo

{% embed url="<https://codepen.io/surjithctly/pen/eYobEbO>" %}
[View Codepen](https://codepen.io/surjithctly/pen/eYobEbO?editors=1010)
{% endembed %}


# Integrations

Web3Forms allows you to connect third-party services to receive form submissions, enabling powerful automation and data management workflows. All integrations listed below are available for **PRO plan** users.

## Available Integrations

### Google Sheets (Beta)

Automatically sync form submissions to a Google Sheets spreadsheet in real-time. Perfect for organizing and analyzing form data.

[Learn more about Google Sheets integration →](/getting-started/integrations/google-sheets)

### Telegram

Get instant notifications in your Telegram chat or group whenever someone submits a form. Stay updated on the go.

[Learn more about Telegram integration →](/getting-started/integrations/telegram-notifications)

### Slack

Get instant notifications in your Slack channel for every form submission. Keep your team informed in real-time.

[Learn more about Slack integration →](/getting-started/integrations/slack)

### Discord

Get instant notifications in your Discord server whenever you receive a new form submission.

[Learn more about Discord integration →](/getting-started/integrations/discord)

### Webhook

Send form data to any URL endpoint via HTTP POST. Compatible with Zapier, Make (formerly Integromat), n8n, and custom endpoints.

[Learn more about Webhooks →](/getting-started/pro-features/webhooks)

## Popular Use Cases

### Automation Platforms

* **Zapier**: Connect Web3Forms with 5,000+ apps using webhooks
* **Make (Integromat)**: Build complex automation workflows
* **n8n**: Open-source workflow automation
* **Pipedream**: Developer-focused automation platform

[View automation platform guides →](/getting-started/integrations/soon/zapier)

### Data Management

* **Google Sheets**: Organize submissions in spreadsheets
* **Airtable**: Store form data in a flexible database
* **Notion**: Manage submissions in your all-in-one workspace

[View data management examples →](/getting-started/examples)

### Team Notifications

* **Slack**: Notify team channels
* **Discord**: Alert Discord communities
* **Telegram**: Personal or group notifications

## Getting Started

{% hint style="info" %}
All integrations require an active **PRO plan** subscription. [Upgrade to PRO](https://web3forms.com/pricing) to access these features.
{% endhint %}

To set up an integration:

1. Log in to your [Web3Forms Dashboard](https://app.web3forms.com)
2. Select your form
3. Navigate to the **Integrations** tab
4. Choose your desired integration
5. Follow the setup instructions for that specific service
6. Save your settings

## Need Help?

If you need assistance setting up an integration, feel free to [contact our support team](mailto:support@web3forms.com) or [contribute to our documentation on Github](https://github.com/surjithctly/web3forms-docs).


# Google Sheets

Automatically sync your Web3Forms submissions to a Google Sheets spreadsheet in real-time. This integration is perfect for organizing, analyzing, and sharing form data with your team.

{% hint style="info" %}
This is a **PRO feature** currently in **Beta**. You must have an active PRO plan subscription to use this integration.
{% endhint %}

## Features

* ✅ **Real-time Sync**: Form submissions are automatically added to your spreadsheet
* ✅ **Easy Setup**: Connect with just a few clicks using Google OAuth
* ✅ **Flexible Configuration**: Choose which spreadsheet and sheet to use
* ✅ **Automatic Headers**: Column headers are created based on your form fields
* ✅ **No Code Required**: No scripts or API keys needed

## Setup Instructions

### Step 1: Access the Integrations Tab

1. Log in to your [Web3Forms Dashboard](https://app.web3forms.com)
2. Select the form you want to connect
3. Navigate to the **Integrations** tab in your form settings

### Step 2: Enable Google Sheets Integration

1. Find the **Google Sheets** integration card
2. Click "Connect" enable the integration
3. You'll be prompted to sign in with your Google account
4. Grant Web3Forms permission to access your Google Sheets

### Step 3: Configure Sheet Settings

**Spreadsheet Selection**

* Click the **Select** button to choose your destination spreadsheet
* You can select any existing spreadsheet in your Google Drive

**Sheet Name (Optional)**

* Enter the name of the sheet where data should be added
* Leave empty to use the default sheet (Sheet1)

<figure><img src="/files/vTYuMNolIIGl35pFmk2R" alt=""><figcaption></figcaption></figure>

### Step 5: Save Settings

Click the **Save Settings** button to activate the integration.

## How It Works

1. When a user submits your Web3Forms contact form, the data is processed
2. Web3Forms automatically sends the submission to your connected Google Sheets
3. A new row is added with all the form field data
4. Column headers are created based on your form field names (if not already present)

### Data Format

Each submission creates a new row with the following information:

* **Timestamp**: Date and time of submission
* **Form Fields**: All custom fields from your form (name, email, message, etc.)

## Example Spreadsheet Structure

Here's how your data might look in Google Sheets:

| Timestamp           | Name       | Email              | Message               | Phone       |
| ------------------- | ---------- | ------------------ | --------------------- | ----------- |
| 2025-12-22 10:30 AM | John Doe   | <john@example.com> | Hello, I need help... | +1234567890 |
| 2025-12-22 11:45 AM | Jane Smith | <jane@example.com> | I have a question...  | +0987654321 |

## Managing Your Integration

### Disconnect Google Sheets

To stop syncing submissions to Google Sheets:

1. Go to your form's Integrations tab
2. Find the Google Sheets integration
3. Click the **Disconnect** button

### Change Spreadsheet

To use a different spreadsheet:

1. Click the **Select** button again
2. Choose a new spreadsheet from your Google Drive
3. Update the sheet name if needed
4. Click **Save Settings**

## Troubleshooting

### No Data Appearing in Spreadsheet

* **Check Integration Status**: Ensure the toggle is enabled and shows "Connected"
* **Verify Sheet Name**: Make sure the sheet name matches exactly (case-sensitive)
* **Check Permissions**: Ensure Web3Forms has access to your Google account
* **Test Your Form**: Submit a test entry and check if it appears

### Permission Errors

If you see permission errors:

1. Disconnect the integration
2. Reconnect and re-authorize your Google account
3. Make sure the spreadsheet isn't restricted or protected

### Data Not Formatting Correctly

* Column headers are created from form field names
* Make sure your form fields have descriptive `name` attributes
* Avoid special characters in field names for best results

## Privacy & Security

* Web3Forms uses secure OAuth 2.0 for Google account authentication
* Only necessary permissions are requested (selected spreadsheet access only)
* Your access tokens are encrypted and stored securely.
* You can revoke access anytime from your [Google Account Settings](https://myaccount.google.com/permissions)

## Related Integrations

* [Webhook Integration](/getting-started/pro-features/webhooks) - Send data to custom endpoints
* [Zapier Integration](/getting-started/integrations/soon/zapier) - Connect with 5,000+ apps
* [Airtable Integration](/getting-started/integrations/soon/airtable) - Alternative database solution


# Slack

Get instant notifications in your Slack channel for every form submission. Keep your team informed in real-time and collaborate on responses directly within Slack.

{% hint style="info" %}
This is a **PRO feature**. You must have an active PRO plan subscription to use this integration.
{% endhint %}

## Features

* ✅ **Real-time Notifications**: Receive form submissions instantly in Slack
* ✅ **Team Collaboration**: Share submissions with your entire team
* ✅ **Formatted Messages**: Clean, professional message formatting
* ✅ **Channel Flexibility**: Send to any public or private channel
* ✅ **Easy Setup**: Connect with just a webhook URL

## Setup Instructions

### Step 1: Create an Incoming Webhook in Slack

To receive notifications, you need to create an Incoming Webhook in your Slack workspace:

1. Go to your Slack workspace
2. Navigate to **Apps** or visit <https://api.slack.com/apps>
3. Click **Create New App** (or use an existing app)
4. Select **From scratch**
5. Give your app a name (e.g., "Web3Forms Notifications")
6. Choose your workspace
7. Click **Create App**

### Step 2: Enable Incoming Webhooks

1. In your app settings, click **Incoming Webhooks** from the left sidebar
2. Toggle **Activate Incoming Webhooks** to **On**
3. Scroll down and click **Add New Webhook to Workspace**
4. Select the channel where you want to receive notifications
5. Click **Allow**

### Step 3: Copy Your Webhook URL

1. After authorization, you'll see your webhook URL
2. It will look like: `https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXX`
3. Click **Copy** to copy the webhook URL

### Step 4: Configure Web3Forms Integration

1. Log in to your [Web3Forms Dashboard](https://app.web3forms.com)
2. Select the form you want to connect
3. Navigate to the **Integrations** tab in your form settings
4. Find the **Slack** integration card
5. Toggle the switch to enable the integration
6. Paste your Webhook URL in the **Webhook URL** field
7. Click the **Save Settings** button

<figure><img src="/files/xLBggZMsydyiChhkDbMQ" alt=""><figcaption></figcaption></figure>

## How It Works

1. When a user submits your Web3Forms contact form, the data is processed
2. Web3Forms sends a formatted notification to your Slack webhook
3. The message appears instantly in your designated Slack channel
4. Your team can see and respond to the submission

### Notification Format

Each form submission sends a formatted message to Slack with:

* **Header**: "New Form Submission" with a notification icon
* **Form Fields**: All submitted data (name, email, message, etc.)

## Managing Your Integration

### Update Webhook URL

To change the destination channel:

1. Create a new Incoming Webhook for a different channel in Slack
2. Go to your form's Integrations tab in Web3Forms
3. Update the Webhook URL field with the new URL
4. Click **Save Settings**

### Disable Notifications

To stop receiving Slack notifications:

1. Go to your form's Integrations tab
2. Toggle the Slack switch off
3. Your settings will be saved automatically

## Troubleshooting

### Not Receiving Notifications

If you're not receiving Slack notifications:

* **Verify Webhook URL**: Ensure the URL is correct and complete
* **Check Integration Status**: Make sure the toggle is enabled in Web3Forms
* **Test the Webhook**: Use Slack's webhook testing tool to verify it's working
* **Check Channel**: Ensure you're looking at the correct Slack channel
* **App Permissions**: Verify the Slack app hasn't been removed or disabled
* **Test Your Form**: Submit a test entry and wait a few seconds

### Invalid Webhook URL Error

* Make sure you copied the entire webhook URL
* URLs should start with `https://hooks.slack.com/services/`
* Don't include any extra spaces or characters
* Generate a new webhook URL if the old one isn't working

### Messages Not Formatting Correctly

* Web3Forms sends standard Slack message formatting
* Custom field names will appear as-is in messages
* Use descriptive field names for better readability

## Advanced Tips

### Customizing the Slack App

You can customize your Slack app:

1. Go to your app settings at [api.slack.com/apps](https://api.slack.com/apps)
2. Add a custom icon for your notifications
3. Change the app name and description
4. Customize the display name shown in messages

## Related Integrations

* [Telegram Integration](/getting-started/integrations/telegram-notifications) - Mobile notifications via Telegram
* [Discord Integration](/getting-started/integrations/discord) - Notifications in Discord
* [Webhook Integration](/getting-started/pro-features/webhooks) - Send to custom endpoints


# Discord

Get instant notifications in your Discord server whenever you receive a new form submission. Perfect for community-driven projects, development teams, and keeping everyone in the loop.

{% hint style="info" %}
This is a **PRO feature**. You must have an active PRO plan subscription to use this integration.
{% endhint %}

## Features

* ✅ **Real-time Notifications**: Receive form submissions instantly in Discord
* ✅ **Server Integration**: Send to any channel in your Discord server
* ✅ **Rich Embeds**: Beautiful, formatted message embeds
* ✅ **Community Engagement**: Keep your community informed
* ✅ **Easy Setup**: Connect with just a webhook URL

## Setup Instructions

### Step 1: Create a Webhook in Discord

To receive notifications, you need to create a webhook in your Discord server:

1. Open Discord and go to your server
2. Right-click on the channel where you want to receive notifications
3. Select **Edit Channel** (or click the ⚙️ gear icon)
4. Navigate to the **Integrations** tab
5. Click **Webhooks** or **Create Webhook**
6. Click **New Webhook** button

### Step 2: Configure the Webhook

1. Give your webhook a name (e.g., "Web3Forms Bot")
2. Optionally, upload a custom avatar for the webhook
3. Select the channel where notifications should be posted
4. Click **Copy Webhook URL**
5. The URL will look like: `https://discord.com/api/webhooks/123456789/XXXXXXXXXXXX`

<figure><img src="/files/hFuECDouKOZpgqxeivqi" alt=""><figcaption></figcaption></figure>

### Step 3: Configure Web3Forms Integration

1. Log in to your [Web3Forms Dashboard](https://app.web3forms.com)
2. Select the form you want to connect
3. Navigate to the **Integrations** tab in your form settings
4. Find the **Discord** integration card
5. Toggle the switch to enable the integration
6. Paste your Webhook URL in the **Webhook URL** field
7. Click the **Save Settings** button

<figure><img src="/files/pgUjtRgw3iVgw6PKPkrW" alt=""><figcaption></figcaption></figure>

## How It Works

1. When a user submits your Web3Forms contact form, the data is processed
2. Web3Forms sends a formatted notification to your Discord webhook
3. The message appears instantly in your designated Discord channel
4. Your server members can see and respond to the submission

### Notification Format

Each form submission sends a rich embed message to Discord with:

* "New Form Submission" Title
* **Fields**: All submitted form data (name, email, message, etc.)

## Managing Your Integration

### Update Webhook URL

To change the destination channel:

1. Create a new webhook for a different channel in Discord
2. Go to your form's Integrations tab in Web3Forms
3. Update the Webhook URL field with the new URL
4. Click **Save Settings**

### Disable Notifications

To stop receiving Discord notifications:

1. Go to your form's Integrations tab
2. Toggle the Discord switch off
3. Your settings will be saved automatically

### Delete Webhook

To completely remove the webhook from Discord:

1. Go to your Discord channel settings
2. Navigate to **Integrations** → **Webhooks**
3. Find the webhook and click **Delete Webhook**
4. Remember to disable the integration in Web3Forms as well

## Troubleshooting

### Not Receiving Notifications

If you're not receiving Discord notifications:

* **Verify Webhook URL**: Ensure the URL is correct and complete
* **Check Integration Status**: Make sure the toggle is enabled in Web3Forms
* **Test the Webhook**: Send a test message using Discord's webhook testing
* **Check Channel**: Ensure you're looking at the correct Discord channel
* **Webhook Deleted**: Verify the webhook still exists in Discord settings
* **Test Your Form**: Submit a test entry and wait a few seconds

### Invalid Webhook URL Error

* Make sure you copied the entire webhook URL
* URLs should start with `https://discord.com/api/webhooks/`
* Don't include any extra spaces or characters
* Generate a new webhook URL if the old one isn't working

### Webhook Not Found Error

This means the webhook was deleted from Discord:

1. Create a new webhook in Discord
2. Update the webhook URL in Web3Forms
3. Save your settings

### Messages Not Appearing

* Check Discord channel permissions
* Ensure the webhook has permission to post in the channel
* Verify you haven't muted the channel
* Check if Discord is filtering webhook messages

## Privacy & Security

* Your webhook URL is stored securely and encrypted
* Only form submission data is sent to Discord
* No access keys or sensitive credentials are exposed
* You can delete webhook URLs anytime in Discord settings
* Webhook URLs are specific to your Discord server

## Advanced Tips

### Customizing the Webhook

Customize your Discord webhook:

1. Go to your Discord channel settings
2. Navigate to **Integrations** → **Webhooks**
3. Click on your webhook
4. Change the name and avatar
5. Move it to a different channel if needed

### Channel Organization

Best practices for organizing notifications:

* Create a dedicated `#form-submissions` channel
* Use channel categories to organize different form types
* Set up channel permissions to control who sees submissions
* Use thread creation for discussion on specific submissions

## Related Integrations

* [Slack Integration](/getting-started/integrations/slack) - Team notifications in Slack
* [Telegram Integration](/getting-started/integrations/telegram-notifications) - Mobile notifications via Telegram
* [Webhook Integration](/getting-started/pro-features/webhooks) - Send to custom endpoints

## Additional Resources

* [Discord Webhooks Documentation](https://discord.com/developers/docs/resources/webhook)
* [Discord Server Setup Guide](https://support.discord.com/hc/en-us/articles/206346498)


# Telegram

Get instant notifications in your Telegram chat or group whenever someone submits a form on your website. Perfect for staying updated on the go and responding to inquiries quickly.

{% hint style="info" %}
This is a **PRO feature**. You must have an active PRO plan subscription to use this integration.
{% endhint %}

## Features

* ✅ **Instant Notifications**: Receive form submissions in real-time
* ✅ **Personal or Group Chats**: Send to your private chat or team groups
* ✅ **Formatted Messages**: Clean, readable message formatting
* ✅ **Mobile & Desktop**: Works on all Telegram platforms
* ✅ **No Coding Required**: Simple setup with just a Chat ID

## Setup Instructions

### Step 1: Get Your Chat ID

To receive notifications, you need to get your Telegram Chat ID:

1. Open Telegram on your phone or desktop
2. Search for **@web3forms\_bot** in Telegram
3. Start a chat with the bot
4. Send the `/start` command
5. The bot will reply with your **Chat ID** (a number like `123456789`)
6. Copy this Chat ID for the next step

{% hint style="info" %}
**For Group Chats**: Add @web3forms\_bot to your group and send `/start` to get the group's Chat ID.
{% endhint %}

### Step 2: Access the Integrations Tab

1. Log in to your [Web3Forms Dashboard](https://app.web3forms.com)
2. Select the form you want to connect
3. Navigate to the **Integrations** tab in your form settings

### Step 3: Enable Telegram Integration

1. Find the **Telegram** integration card
2. Toggle the switch to enable the integration
3. Paste your Chat ID in the **Chat ID** field
4. Click the **Save Settings** button

<figure><img src="/files/qENmtkYUB2g7fSVK0jFa" alt=""><figcaption></figcaption></figure>

## How It Works

1. When a user submits your Web3Forms contact form, the data is processed
2. Web3Forms sends a formatted notification to your Telegram chat
3. You receive the message instantly on all your Telegram devices

## Managing Your Integration

### Update Chat ID

To change the destination chat:

1. Get a new Chat ID from @web3forms\_bot
2. Go to your form's Integrations tab
3. Update the Chat ID field
4. Click **Save Settings**

### Disable Notifications

To stop receiving Telegram notifications:

1. Go to your form's Integrations tab
2. Toggle the Telegram switch off
3. Your settings will be saved automatically

## Troubleshooting

### Not Receiving Notifications

If you're not receiving Telegram notifications:

* **Verify Chat ID**: Make sure the Chat ID is correct (it should be a number)
* **Check Integration Status**: Ensure the toggle is enabled
* **Test the Bot**: Send `/start` to @web3forms\_bot again to verify it's working
* **Check Spam/Blocked**: Make sure you haven't blocked the bot
* **Test Your Form**: Submit a test entry and wait a few seconds

### Group Notifications Not Working

For group chats:

1. Ensure @web3forms\_bot is added to the group
2. The bot must not be removed from the group
3. Use the group's Chat ID, not your personal Chat ID
4. Make sure the group allows bots to send messages

### Wrong Chat ID

If you entered the wrong Chat ID:

* You won't receive any notifications
* Simply update the Chat ID with the correct one
* No data is lost; future submissions will be sent to the new chat

## Advanced Tips

### Using with Groups

Set up a dedicated Telegram group for form submissions:

1. Create a new Telegram group
2. Add @web3forms\_bot to the group
3. Add your team members
4. Send `/start` to get the group Chat ID
5. Use this Chat ID in your Web3Forms integration

## Related Integrations

* [Slack Integration](/getting-started/integrations/slack) - Team notifications in Slack
* [Discord Integration](/getting-started/integrations/discord) - Notifications in Discord
* [Webhook Integration](/getting-started/pro-features/webhooks) - Custom endpoints


# Webhooks

Send form data to any URL endpoint via HTTP POST. Webhooks enable you to connect Web3Forms with thousands of applications and services, creating powerful automation workflows without writing code.

{% hint style="info" %}
This is a **PRO feature**. You must have an active PRO plan subscription to use this feature.
{% endhint %}

## What are Webhooks?

Webhooks allow you to automatically send form submission data to any HTTP endpoint in real-time. This opens up endless possibilities for integrating with:

* **Automation Platforms**: Zapier, Make (Integromat), n8n, Pipedream
* **CRM Systems**: Salesforce, HubSpot, Pipedrive
* **Email Marketing**: Mailchimp, ConvertKit, SendGrid
* **Project Management**: Asana, Trello, ClickUp
* **Databases**: Airtable, MongoDB, PostgreSQL
* **Communication**: Slack, Discord, Microsoft Teams
* **Custom Applications**: Your own backend services

## Key Features

* ✅ **Universal Compatibility**: Works with any service that accepts HTTP POST requests
* ✅ **Real-time Delivery**: Data is sent immediately after form submission
* ✅ **Secure Transmission**: Data is sent over HTTPS
* ✅ **Automatic Retry**: Failed webhooks are retried automatically
* ✅ **Clean Payload**: Sensitive data is removed before sending

## Setup Instructions

### Step 1: Create a Webhook URL

Webhook URLs can be created using various platforms:

**Recommended Platforms:**

* [**Zapier**](https://zapier.com/) - Connect with 5,000+ apps (Commercial)
* [**Make**](https://www.make.com/) (formerly Integromat) - Advanced automation (Free tier available)
* [**Pipedream**](https://pipedream.com/) - Developer-friendly automation (Generous free plan)
* [**n8n**](https://n8n.io/) - Open-source automation (Self-hosted or cloud)

{% hint style="success" %}
We recommend **Pipedream** if you're technical, as it offers a generous free plan and provides excellent debugging tools.
{% endhint %}

### Step 2: Access the Integrations Tab

1. Log in to your [Web3Forms Dashboard](https://app.web3forms.com)
2. Select the form you want to connect
3. Navigate to the **Integrations** tab in your form settings

### Step 3: Enable Webhook Integration

1. Find the **Webhook** integration card
2. Toggle the switch to enable the integration
3. Paste your webhook URL in the **Webhook URL** field
4. Click the **Save Settings** button

**\[SCREENSHOT PLACEHOLDER: Webhook integration card in Web3Forms dashboard]**

<figure><img src="/files/HzEaAYpb6CVyRVXiwVYI" alt=""><figcaption><p>Webhook Integration Settings</p></figcaption></figure>

## Webhook Payload Structure

Web3Forms sends form data as a JSON payload via HTTP POST request. The payload includes all form fields submitted by the user.

### Request Headers

```
Content-Type: application/json
User-Agent: Web3Forms/1.0
```

### Example Payload

```json
{
  "name": "John Doe",
  "email": "john@example.com",
  "phone": "+1234567890",
  "message": "Hello, I'm interested in your services...",
  "subject": "New Contact Form Submission",
  "from_name": "My Website",
  "submittedAt": "2025-12-22T10:30:00.000Z"
}
```

### What's Included

* **All form fields**: Any field you include in your form (name, email, message, etc.)
* **Custom fields**: Any additional fields you've added
* **Metadata fields**: Subject, from\_name, and other configuration fields

### What's Excluded

For security and privacy, the following data is **removed** before sending:

* `access_key` - Your Web3Forms access key
* `apikey` - Legacy API key field
* `attachment` - File attachments (separate handling)
* `botcheck` - Anti-spam honeypot field
* `recaptcha_response` - CAPTCHA tokens

## Use Cases

### CRM Integration

Automatically add leads to your CRM:

1. Create a webhook in Zapier or Make
2. Connect to your CRM (Salesforce, HubSpot, etc.)
3. Map form fields to CRM fields
4. Leads are added automatically

### Database Storage

Store submissions in a database:

* Send to Airtable for a visual database
* Use Pipedream to insert into PostgreSQL or MongoDB
* Create custom data warehousing solutions

### Team Notifications

Send notifications to multiple platforms:

* Slack channels for team awareness
* Discord servers for community projects
* Microsoft Teams for enterprise environments
* Email notifications to multiple recipients

### Email Marketing

Add subscribers to your email list:

* Connect to Mailchimp, ConvertKit, or SendGrid
* Automatically create contact lists
* Trigger welcome email sequences

### Custom Processing

Build custom workflows:

* Validate and enrich data
* Perform background processing
* Trigger custom business logic
* Integrate with proprietary systems

## Popular Integrations

### Zapier

Connect Web3Forms with 5,000+ apps using Zapier:

1. Create a new Zap in Zapier
2. Choose **Webhooks by Zapier** as the trigger
3. Select **Catch Hook**
4. Copy the webhook URL
5. Paste it in Web3Forms webhook settings
6. Test and configure your automation

[Learn more about Zapier integration →](/getting-started/integrations/soon/zapier)

### Make (Integromat)

Build complex automation scenarios:

1. Create a new Scenario in Make
2. Add a **Webhook** module as the trigger
3. Choose **Custom webhook**
4. Copy the webhook URL
5. Add it to Web3Forms
6. Build your automation workflow

[Learn more about Make integration →](/getting-started/integrations/soon/integromat)

### Pipedream

Developer-friendly automation with code:

1. Create a new Workflow in Pipedream
2. Select **HTTP / Webhook** as the trigger
3. Copy the endpoint URL
4. Add it to Web3Forms
5. Use pre-built actions or write custom Node.js code

### n8n

Open-source workflow automation:

1. Create a new Workflow in n8n
2. Add a **Webhook** node
3. Configure the webhook path
4. Copy the webhook URL
5. Connect it to Web3Forms
6. Build your self-hosted automation

## Testing Your Webhook

### Test in Web3Forms

1. Submit a test entry through your form
2. Check if the webhook was triggered
3. Verify data arrived at your endpoint

### Debug with Webhook Testing Tools

Use these tools to inspect webhook payloads:

* [**Webhook.site**](https://webhook.site/) - Free webhook testing
* [**RequestBin**](https://requestbin.com/) - Inspect HTTP requests
* [**Pipedream RequestBin**](https://pipedream.com/requestbin) - Developer-focused debugging

### Check Delivery Status

Monitor webhook delivery in your automation platform:

* Check execution logs in Zapier/Make/Pipedream
* Review error messages if delivery fails
* Verify payload structure matches expectations

## Troubleshooting

### Webhook Not Triggering

* **Verify URL**: Ensure the webhook URL is correct and accessible
* **Check Status**: Make sure the integration is enabled (toggle on)
* **Test Endpoint**: Use webhook testing tools to verify your endpoint works
* **Check Logs**: Review logs in your automation platform
* **Firewall**: Ensure your endpoint isn't blocked by a firewall

### Invalid URL Error

* Webhook URL must start with `https://`
* URL must be publicly accessible
* Don't include spaces or invalid characters
* Test the URL in a browser or curl command

### Data Not Received

* Check the payload structure in your automation platform
* Verify field names match what you expect
* Ensure your endpoint is processing JSON correctly
* Check for rate limits on your receiving service

### Timeout Errors

* Webhook endpoints must respond within 30 seconds
* If processing takes longer, return 200 OK immediately
* Process data asynchronously in the background

## Advanced Configuration

### Multiple Webhooks

To send data to multiple endpoints:

1. Use one webhook URL in Web3Forms
2. Configure your automation platform to forward to multiple services
3. Example: Zapier → Send to both Slack and Airtable

### Data Transformation

Transform data before sending to your destination:

* Use automation platforms to map and modify fields
* Filter submissions based on conditions
* Enrich data with external API calls
* Format data for specific integrations

### Conditional Logic

Send to different endpoints based on form data:

* Use automation platforms to add conditional routing
* Example: Send enterprise leads to sales team, others to support
* Filter spam or test submissions

### Error Handling

Handle webhook failures gracefully:

* Set up retry logic in your automation platform
* Create error notifications for failed webhooks
* Log failures for debugging
* Implement fallback endpoints

## Security Best Practices

### Protect Your Webhook URLs

* Never share webhook URLs publicly
* Regenerate URLs if compromised
* Use URL parameters for authentication if supported
* Monitor webhook activity for unusual patterns

### Validate Incoming Data

In your webhook handler:

* Validate data types and formats
* Sanitize input to prevent injection attacks
* Check for required fields
* Implement rate limiting

### Use HTTPS

* Always use HTTPS endpoints
* Never use HTTP for webhooks
* Ensure SSL certificates are valid

## Related Integrations

* [Google Sheets Integration](/getting-started/integrations/google-sheets) - Direct spreadsheet sync
* [Slack Integration](/getting-started/integrations/slack) - Team notifications
* [Discord Integration](/getting-started/integrations/discord) - Community notifications
* [Telegram Integration](/getting-started/integrations/telegram-notifications) - Mobile notifications

## Additional Resources

* [Zapier Webhooks Documentation](https://zapier.com/page/webhooks/)
* [Make Webhooks Guide](https://www.make.com/en/help/tools/webhooks)
* [Pipedream Workflows](https://pipedream.com/docs/workflows/)
* [n8n Documentation](https://docs.n8n.io/)

## Need Help?

If you encounter any issues with webhooks:

* Email <support@web3forms.com>
* [Contribute to our documentation on Github](https://github.com/surjithctly/web3forms-docs)
* Check the documentation of your automation platform


# Coming Soon


# Zapier

Connect Web3Forms with 5,000+ apps using Zapier webhooks. Automate your workflow without writing any code by creating powerful integrations between your forms and your favorite tools.

{% hint style="info" %}
This integration uses **Webhooks**, which is a PRO feature. You must have an active PRO plan subscription to use Zapier with Web3Forms.
{% endhint %}

## What is Zapier?

[Zapier](https://zapier.com/) is a popular automation platform that connects different apps and services together. With Zapier, you can automatically send your Web3Forms submissions to thousands of other apps including:

* **CRM**: Salesforce, HubSpot, Pipedrive, Zoho CRM
* **Email Marketing**: Mailchimp, ConvertKit, ActiveCampaign
* **Spreadsheets**: Google Sheets, Airtable, Excel Online
* **Communication**: Slack, Discord, Microsoft Teams
* **Project Management**: Trello, Asana, ClickUp, Monday.com
* **And 5,000+ more apps**

## Setup Instructions

### Step 1: Create a Zapier Account

1. Go to [zapier.com](https://zapier.com/)
2. Sign up for a free account or log in
3. Free plan includes 100 tasks per month

### Step 2: Create a New Zap

1. Click **Create Zap** in your Zapier dashboard
2. Give your Zap a descriptive name (e.g., "Web3Forms to Google Sheets")

**\[SCREENSHOT PLACEHOLDER: Zapier dashboard with Create Zap button]**

### Step 3: Set Up the Trigger

1. In the **Trigger** section, search for "Webhooks by Zapier"
2. Select **Webhooks by Zapier**
3. Choose **Catch Hook** as the trigger event
4. Click **Continue**

**\[SCREENSHOT PLACEHOLDER: Zapier webhook trigger selection]**

### Step 4: Copy the Webhook URL

1. Zapier will generate a custom webhook URL
2. It will look like: `https://hooks.zapier.com/hooks/catch/123456/abcdef/`
3. Click **Copy** to copy the webhook URL
4. Keep this tab open, you'll need it in a moment

**\[SCREENSHOT PLACEHOLDER: Zapier webhook URL displayed]**

### Step 5: Add Webhook to Web3Forms

1. Open a new tab and go to your [Web3Forms Dashboard](https://app.web3forms.com)
2. Select your form
3. Navigate to the **Integrations** tab
4. Find the **Webhook** integration card
5. Toggle it on
6. Paste the Zapier webhook URL in the **Webhook URL** field
7. Click **Save Settings**

**\[SCREENSHOT PLACEHOLDER: Web3Forms webhook integration settings]**

### Step 6: Test the Connection

1. Go back to Zapier
2. Click **Test trigger**
3. Submit a test entry through your Web3Forms form
4. Zapier will catch the webhook and display the test data
5. Click **Continue** once you see the test data

**\[SCREENSHOT PLACEHOLDER: Zapier showing caught webhook data]**

### Step 7: Set Up the Action

1. Choose the app you want to send data to (e.g., Google Sheets)
2. Select the action (e.g., "Create Spreadsheet Row")
3. Connect your account for that app
4. Map the form fields to the destination fields
5. Test the action
6. Click **Publish** to activate your Zap

**\[SCREENSHOT PLACEHOLDER: Zapier action configuration with field mapping]**

## Popular Zap Templates

### Send to Google Sheets

**Use Case**: Automatically add form submissions to a Google Sheets spreadsheet

**Setup**:

1. Trigger: Webhooks by Zapier → Catch Hook
2. Action: Google Sheets → Create Spreadsheet Row
3. Map fields: Name → Name, Email → Email, Message → Message

### Add to Mailchimp

**Use Case**: Automatically add email subscribers to your Mailchimp audience

**Setup**:

1. Trigger: Webhooks by Zapier → Catch Hook
2. Action: Mailchimp → Add/Update Subscriber
3. Map email field and any custom fields

### Create Trello Card

**Use Case**: Create a Trello card for each form submission

**Setup**:

1. Trigger: Webhooks by Zapier → Catch Hook
2. Action: Trello → Create Card
3. Use form data to populate card title and description

### Send Slack Notification

**Use Case**: Notify your team in Slack about new submissions

**Setup**:

1. Trigger: Webhooks by Zapier → Catch Hook
2. Action: Slack → Send Channel Message
3. Format message with form data

### Add to CRM

**Use Case**: Automatically create leads in your CRM

**Setup**:

1. Trigger: Webhooks by Zapier → Catch Hook
2. Action: Your CRM → Create Lead/Contact
3. Map all relevant form fields

## Multi-Step Zaps

Create complex workflows with multiple actions:

**Example: Lead Routing Workflow**

1. **Trigger**: Catch webhook from Web3Forms
2. **Action 1**: Add lead to Google Sheets
3. **Action 2**: Create contact in CRM
4. **Action 3**: Send notification to Slack
5. **Action 4**: Send thank you email via Gmail

**Example: Conditional Routing**

1. **Trigger**: Catch webhook from Web3Forms
2. **Filter**: Check if message contains "urgent"
3. **Action 1**: If urgent → Send SMS via Twilio
4. **Action 2**: If not urgent → Send to standard support queue

## Tips for Using Zapier

### Field Mapping

When mapping fields:

* Use the exact field names from your form
* Check the data preview to ensure correct mapping
* Test thoroughly before publishing

### Error Handling

Set up error notifications:

* Add your email to Zap error notifications
* Monitor your Zap history regularly
* Fix failing Zaps promptly

### Data Formatting

Format data correctly:

* Use Zapier's Formatter tool for date/time conversions
* Clean up text fields (trim whitespace, change case)
* Split full names into first/last names if needed

### Filters

Use filters to control when Zaps run:

* Only process submissions with specific values
* Skip test submissions
* Route different types of submissions differently

## Pricing

Zapier offers several pricing tiers:

* **Free**: 100 tasks/month, single-step Zaps
* **Starter**: $19.99/month, 750 tasks/month, multi-step Zaps
* **Professional**: $49/month, 2,000 tasks/month, advanced features
* **Team**: $299/month, 50,000 tasks/month, team collaboration

{% hint style="info" %}
Each form submission counts as 1 task in Zapier. Multi-step Zaps count each action as an additional task.
{% endhint %}

## Troubleshooting

### Webhook Not Triggering

* Verify the webhook URL is correct in Web3Forms
* Ensure the webhook integration is enabled (toggle on)
* Check that your Zap is turned on
* Submit a test form to trigger the webhook

### No Data Showing in Zapier

* Make sure you submitted the form after setting up the webhook
* Check that the form includes all expected fields
* Review the webhook payload in Zapier's history

### Zap Errors

Common errors and solutions:

**"Could not find record"**

* Check that the destination record exists
* Verify account connections are active

**"Required field missing"**

* Ensure all required fields are mapped
* Provide default values for optional fields

**"Invalid format"**

* Use Zapier's Formatter to convert data types
* Check date/time formats match expectations

### Rate Limits

If hitting Zapier task limits:

* Upgrade to a higher plan
* Use filters to reduce unnecessary tasks
* Consolidate multiple Zaps

## Alternatives to Zapier

If Zapier doesn't fit your needs, consider:

* [**Make (Integromat)**](/getting-started/integrations/soon/integromat) - More complex automation, better free tier
* [**Pipedream**](https://pipedream.com/) - Developer-friendly with code support
* [**n8n**](https://n8n.io/) - Open-source, self-hostable
* **Custom Webhooks** - Build your own integration

## Related Resources

* [Webhooks Documentation](/getting-started/pro-features/webhooks) - Complete webhook guide
* [Make (Integromat) Integration](/getting-started/integrations/soon/integromat) - Alternative automation platform
* [Google Sheets Integration](/getting-started/integrations/google-sheets) - Direct spreadsheet sync


# Make (Integromat)

Build powerful automation workflows with Web3Forms and Make (formerly Integromat). Create complex, multi-step scenarios that connect your forms with hundreds of apps and services.

{% hint style="info" %}
This integration uses **Webhooks**, which is a PRO feature. You must have an active PRO plan subscription to use Make with Web3Forms.
{% endhint %}

## What is Make?

[Make](https://www.make.com/) (formerly known as Integromat) is an advanced automation platform that allows you to design sophisticated workflows visually. Make is known for:

* **Visual Workflow Builder**: Drag-and-drop interface for creating scenarios
* **Advanced Logic**: Routers, filters, aggregators, and iterators
* **Better Free Tier**: More operations than competitors
* **Detailed Execution History**: See exactly how your data flows
* **Developer-Friendly**: JSON/XML processing, HTTP requests, custom code

## Setup Instructions

### Step 1: Create a Make Account

1. Go to [make.com](https://www.make.com/)
2. Sign up for a free account or log in
3. Free tier includes 1,000 operations per month

### Step 2: Create a New Scenario

1. Click **Create a new scenario** in your Make dashboard
2. Give your scenario a descriptive name (e.g., "Web3Forms to Google Sheets")

**\[SCREENSHOT PLACEHOLDER: Make dashboard with Create Scenario button]**

### Step 3: Add a Webhook Module

1. Click the **+** button to add a new module
2. Search for "Webhooks"
3. Select **Webhooks** from the results
4. Choose **Custom webhook**

**\[SCREENSHOT PLACEHOLDER: Make module selection showing Webhooks]**

### Step 4: Create a Webhook

1. Click **Add** to create a new webhook
2. Give it a name (e.g., "Web3Forms Contact Form")
3. Click **Save**
4. Make will generate a webhook URL
5. Click **Copy address to clipboard**

**\[SCREENSHOT PLACEHOLDER: Make webhook creation dialog]**

### Step 5: Add Webhook to Web3Forms

1. Open a new tab and go to your [Web3Forms Dashboard](https://app.web3forms.com)
2. Select your form
3. Navigate to the **Integrations** tab
4. Find the **Webhook** integration card
5. Toggle it on
6. Paste the Make webhook URL in the **Webhook URL** field
7. Click **Save Settings**

**\[SCREENSHOT PLACEHOLDER: Web3Forms webhook integration settings]**

### Step 6: Determine the Data Structure

1. Go back to Make
2. The webhook module will be waiting for data
3. Submit a test entry through your Web3Forms form
4. Make will capture the data structure automatically
5. Click **OK** once you see the test data

**\[SCREENSHOT PLACEHOLDER: Make showing webhook data structure]**

### Step 7: Add Actions

1. Click the **+** button after the webhook module
2. Choose your desired app (e.g., Google Sheets, Airtable, Slack)
3. Select the action you want to perform
4. Map the webhook data to the action fields
5. Test your scenario
6. Click the toggle to activate your scenario

**\[SCREENSHOT PLACEHOLDER: Make scenario with webhook and action modules]**

## Popular Make Scenarios

### Send to Google Sheets

**Use Case**: Automatically add form submissions to a Google Sheets spreadsheet

**Modules**:

1. Webhooks → Custom webhook
2. Google Sheets → Add a row
3. Map webhook data to spreadsheet columns

### Add to Airtable

**Use Case**: Store submissions in an Airtable base

**Modules**:

1. Webhooks → Custom webhook
2. Airtable → Create a record
3. Map all form fields to Airtable fields

### Multi-Platform Notifications

**Use Case**: Send notifications to multiple platforms

**Modules**:

1. Webhooks → Custom webhook
2. Slack → Create a message
3. Discord → Create a message
4. Email → Send an email

### Conditional Routing

**Use Case**: Route submissions based on content

**Modules**:

1. Webhooks → Custom webhook
2. Router (splits into multiple paths)
3. Path 1 (VIP leads) → Send to Sales CRM
4. Path 2 (Support) → Create ticket in Help Desk
5. Path 3 (General) → Add to Google Sheets

## Advanced Make Features

### Routers

Route data to different paths based on conditions:

```
Webhook → Router
  ├─ Path 1 (if email contains @company.com) → Send to Sales
  ├─ Path 2 (if message contains "urgent") → SMS Alert
  └─ Path 3 (default) → Standard Processing
```

### Filters

Add filters between modules to control data flow:

* **Filter by Field Value**: Only process if email domain is specific
* **Filter by Time**: Only during business hours
* **Filter by Content**: Only if message contains keywords
* **Filter by Length**: Only if message is longer than X characters

### Aggregators

Combine multiple submissions:

* Collect submissions over 1 hour
* Aggregate into single email or report
* Send batch updates instead of individual notifications

### Iterators

Process arrays and multiple items:

* Split multi-value fields
* Process each item individually
* Handle file attachments separately

### Data Transformation

Make offers powerful data tools:

* **Text Parser**: Extract specific information
* **JSON Parser**: Parse complex JSON data
* **Date/Time**: Format dates and times
* **Math**: Calculate values
* **Encryption**: Hash or encrypt sensitive data

## Troubleshooting

### Webhook Not Receiving Data

* Verify the webhook URL is correct in Web3Forms
* Ensure webhook integration is enabled (toggle on)
* Check that your scenario is active (toggle on)
* Submit a test form after setting up the webhook

### Scenario Errors

Common errors and solutions:

**"Invalid data structure"**

* Re-determine the data structure
* Check field mappings
* Ensure data types match

**"Connection failed"**

* Reconnect your app accounts
* Check API credentials
* Verify account permissions

**"Rate limit exceeded"**

* Reduce scenario frequency
* Implement throttling
* Upgrade to higher tier

### Data Mapping Issues

* Use the mapping panel to select correct fields
* Check data preview before mapping
* Test with real data, not empty values

## Best Practices

### Scenario Organization

* Use descriptive names for scenarios
* Add notes to complex modules
* Group related scenarios in folders
* Document your workflow logic

### Error Handling

* Enable error notifications
* Add error handlers to critical scenarios
* Set up fallback actions
* Monitor execution history regularly

### Performance Optimization

* Use filters early to reduce operations
* Combine multiple actions when possible
* Avoid unnecessary loops
* Cache frequently accessed data

### Testing

* Always test with real data
* Test all router paths
* Check edge cases
* Verify error handling

## Templates and Examples

### Basic Form to Sheet

```
[Webhook] → [Google Sheets: Add Row]
```

### Form to CRM with Notification

```
[Webhook] → [HubSpot: Create Contact] → [Slack: Send Message]
```

### Conditional Lead Routing

```
[Webhook] → [Router]
  ├─ [Filter: VIP] → [Salesforce: Create Lead] → [SMS Alert]
  ├─ [Filter: Regular] → [HubSpot: Create Contact] → [Email]
  └─ [Filter: Default] → [Google Sheets: Add Row]
```

### Daily Digest

```
[Webhook] → [Data Store: Add] → [Scheduler: Daily 9AM]
  → [Data Store: Search] → [Aggregator] → [Email: Send Digest]
```


# n8n

Build powerful, self-hosted automation workflows with Web3Forms and n8n. Create custom integrations, process data with code, and maintain complete control over your automation infrastructure.

{% hint style="info" %}
This integration uses **Webhooks**, which is a PRO feature. You must have an active PRO plan subscription to use n8n with Web3Forms.
{% endhint %}

### What is n8n?

[n8n](https://n8n.io/) is a fair-code licensed workflow automation tool that allows you to connect different apps and services together. Unlike other automation platforms, n8n can be self-hosted, giving you complete control over your data and workflows.

#### Why Choose n8n?

* **Self-Hosted**: Run on your own infrastructure for complete data control
* **Open Source**: Fair-code license with access to source code
* **Cloud Option**: Managed cloud hosting also available
* **No Vendor Lock-in**: Export and migrate your workflows anytime
* **Code Support**: Write custom JavaScript/Python for complex logic
* **Visual Editor**: Intuitive drag-and-drop workflow builder
* **400+ Integrations**: Pre-built nodes for popular services
* **Generous Free Tier**: Self-hosted version is completely free

#### Step 1: Create a New Workflow

1. Access your n8n instance (default: <http://localhost:5678>)
2. Click **Create new workflow**
3. Give your workflow a descriptive name (e.g., "Web3Forms to Database")

**\[SCREENSHOT PLACEHOLDER: n8n new workflow creation]**

#### Step 2: Add a Webhook Node

1. Click the **+** button to add a new node
2. Search for "Webhook"
3. Select **Webhook** from the list
4. Configure the webhook:
   * **HTTP Method**: POST
   * **Path**: Choose a custom path (e.g., web3forms)
   * **Authentication**: None (or configure if needed)
5. Click **Execute Node** to activate the webhook
6. Copy the **Test URL** or **Production URL**

**\[SCREENSHOT PLACEHOLDER: n8n webhook node configuration]**

#### Step 3: Add Webhook to Web3Forms

1. Log in to your [Web3Forms Dashboard](https://app.web3forms.com/)
2. Select your form
3. Navigate to the **Integrations** tab
4. Find the **Webhook** integration card
5. Toggle it on
6. Paste your n8n webhook URL
7. Click **Save Settings**

**\[SCREENSHOT PLACEHOLDER: Web3Forms webhook settings with n8n URL]**

#### Step 4: Test the Connection

1. Go back to n8n
2. The webhook node should be waiting for data
3. Submit a test entry through your Web3Forms form
4. n8n will capture the data and display it
5. Click **Execute Node** to process the test data

**\[SCREENSHOT PLACEHOLDER: n8n showing captured webhook data]**

#### Step 5: Add Processing Nodes

1. Click **+** after the webhook node
2. Add your desired processing nodes:
   * Database operations (PostgreSQL, MongoDB, MySQL)
   * HTTP requests to APIs
   * Data transformation
   * Conditional logic
   * Error handling
3. Connect nodes together
4. Map data from webhook to each node
5. Test your workflow

**\[SCREENSHOT PLACEHOLDER: n8n workflow with multiple connected nodes]**

#### Step 6: Activate Your Workflow

1. Toggle the **Active** switch in the top right
2. Your workflow is now live and will process all submissions
3. Monitor executions in the **Executions** tab

**\[SCREENSHOT PLACEHOLDER: n8n workflow activation toggle]**

### Integration Examples

#### Web3Forms → Notion Database

1. **Webhook** → Receive form data
2. **Set** → Format data for Notion
3. **Notion** → Create database item
4. **Slack** → Send notification

#### Web3Forms → Custom API

1. **Webhook** → Receive form data
2. **Function** → Validate and transform data
3. **HTTP Request** → POST to your API
4. **IF** → Check response status
5. **Email** → Send success/error notification

#### Web3Forms → CRM + Marketing

1. **Webhook** → Receive lead
2. **Switch** → Route by criteria
   * Hot lead → Salesforce + SMS
   * Warm lead → HubSpot + Email sequence
   * Cold lead → Mailchimp list
3. **Set** → Log outcome
4. **Webhook Response** → Send confirmation

### Troubleshooting

#### Webhook Not Receiving Data

* **Check Activation**: Ensure workflow is active (toggle on)
* **Verify URL**: Confirm webhook URL is correct in Web3Forms
* **Test Mode**: Use test URL first, then switch to production
* **Firewall**: Ensure n8n is accessible from internet
* **Logs**: Check n8n execution logs for errors

#### Workflow Not Executing

* **Check Trigger**: Ensure webhook node is properly configured
* **Execution Mode**: Verify workflow is in production mode
* **Resource Limits**: Check if server has enough memory/CPU
* **Permissions**: Ensure n8n has write permissions for data directory

#### Data Mapping Issues

* **Field Names**: Check exact field names from webhook data
* **Data Types**: Ensure types match (string, number, boolean)
* **Empty Values**: Handle optional fields with default values
* **Nested Data**: Use expressions to access nested properties

#### Performance Issues

* **Optimize Queries**: Use efficient database queries
* **Reduce API Calls**: Batch operations when possible
* **Use Caching**: Cache frequently accessed data
* **Queue Mode**: Enable for high-volume workflows


# Notion

Store your Web3Forms submissions directly in Notion databases, the all-in-one workspace for notes, tasks, wikis, and databases. Perfect for teams that want to manage form submissions alongside their other work.

{% hint style="info" %}
This integration uses **Webhooks**, which is a PRO feature. You must have an active PRO plan subscription to use Notion with Web3Forms.
{% endhint %}

## What is Notion?

[Notion](https://www.notion.so/) is an all-in-one workspace that combines notes, docs, wikis, and project management. Notion databases are perfect for storing form submissions because they offer:

* **Flexible Databases**: Create custom properties for any type of data
* **Multiple Views**: Table, board, timeline, calendar, gallery, and list views
* **Rich Content**: Add notes, files, and links to each submission
* **Collaboration**: Share with team members and set permissions
* **Templates**: Create templates for processing submissions
* **Powerful Filtering**: Filter and sort by any property

## Integration Methods

There are several ways to integrate Web3Forms with Notion:

### Method 1: Using Zapier (Easiest)

The simplest way to connect Web3Forms to Notion with a user-friendly interface.

### Method 2: Using Make (Most Flexible)

More advanced automation with better free tier and visual workflow builder.

### Method 3: Using Pipedream (For Developers)

Developer-friendly platform with code support and generous free tier.

### Method 4: Direct API Integration

Use Notion's API directly for custom implementations.

## Setup via Zapier

### Step 1: Create Notion Database

1. Open [Notion](https://www.notion.so/)
2. Create a new page or open an existing workspace
3. Add a **Database** (full page or inline)
4. Name it "Form Submissions" or similar
5. Add properties to match your form fields:
   * Name (Title or Text)
   * Email (Email)
   * Phone (Phone)
   * Message (Text)
   * Status (Select or Multi-select)
   * Submitted (Date or Created time)

**\[SCREENSHOT PLACEHOLDER: Notion database with form submission properties]**

### Step 2: Set Up Zapier Integration

1. Go to [Zapier](https://zapier.com/) and create a new Zap
2. **Trigger**: Choose "Webhooks by Zapier" → "Catch Hook"
3. Copy the webhook URL
4. Add the webhook URL to Web3Forms integration settings
5. Submit a test form to send data to Zapier

**\[SCREENSHOT PLACEHOLDER: Zapier webhook setup for Notion]**

### Step 3: Configure Notion Action

1. **Action**: Search for "Notion" and select it
2. Choose **Create Database Item** as the action event
3. Click **Sign in to Notion** and connect your account
4. Grant Zapier access to your workspace
5. Select the database you created
6. Map form fields to Notion properties:
   * Form Name → Name (Title)
   * Form Email → Email
   * Form Message → Message
   * etc.

**\[SCREENSHOT PLACEHOLDER: Zapier Notion action with property mapping]**

### Step 4: Test and Activate

1. Test the Zap to ensure the item is created correctly
2. Check your Notion database for the test entry
3. Turn on your Zap
4. Submit a form to verify everything works

## Setup via Make (Integromat)

### Step 1: Create Notion Database

Follow the same steps as in the Zapier method to create your Notion database.

### Step 2: Get Notion Integration Token

1. Go to [Notion Integrations](https://www.notion.so/my-integrations)
2. Click **New integration**
3. Give it a name (e.g., "Web3Forms")
4. Select your workspace
5. Click **Submit**
6. Copy the **Internal Integration Token** (keep it secure!)

**\[SCREENSHOT PLACEHOLDER: Notion integration token creation]**

### Step 3: Share Database with Integration

1. Open your Notion database
2. Click **Share** in the top right
3. Click **Invite**
4. Select your integration from the list
5. Click **Invite**

**\[SCREENSHOT PLACEHOLDER: Sharing Notion database with integration]**

### Step 4: Set Up Make Scenario

1. Go to [Make](https://www.make.com/) and create a new scenario
2. Add a **Webhooks** module → **Custom webhook**
3. Create webhook and copy the URL
4. Add the URL to Web3Forms

**\[SCREENSHOT PLACEHOLDER: Make webhook configuration]**

### Step 5: Add Notion Module

1. Click **+** after the webhook module
2. Search for "Notion" and select it
3. Choose **Create a Database Item**
4. Create a new connection using your integration token
5. Select your database
6. Map webhook data to Notion properties

**\[SCREENSHOT PLACEHOLDER: Make Notion module with field mapping]**

### Step 6: Test and Activate

1. Run the scenario once
2. Submit a test form
3. Verify the entry appears in Notion
4. Activate your scenario

## Setup via Pipedream

### Step 1: Create Notion Database

Follow the same steps to create your Notion database and integration token.

### Step 2: Create Pipedream Workflow

1. Go to [Pipedream](https://pipedream.com/)
2. Create a new workflow
3. Select **HTTP / Webhook** as the trigger
4. Copy the endpoint URL
5. Add it to Web3Forms webhook settings

**\[SCREENSHOT PLACEHOLDER: Pipedream HTTP trigger]**

### Step 3: Add Notion Step

1. Click **+** to add a new step
2. Search for "Notion" and select **Create Page**
3. Connect your Notion account
4. Select your database
5. Map form data to Notion properties using the data from step 1

**\[SCREENSHOT PLACEHOLDER: Pipedream Notion action]**

### Step 4: Deploy and Test

1. Click **Deploy** to activate your workflow
2. Submit a test form
3. Check Notion for the new entry
4. Review execution logs in Pipedream

## Notion Property Types

When setting up your database, use these property types for optimal results:

| Form Data        | Recommended Notion Property |
| ---------------- | --------------------------- |
| Name             | Title or Text               |
| Email            | Email                       |
| Phone            | Phone number                |
| Message/Comments | Text (long form)            |
| URL/Website      | URL                         |
| Date/Time        | Date or Created time        |
| Status           | Select or Status            |
| Categories       | Multi-select                |
| Priority         | Select                      |
| Checkbox/Boolean | Checkbox                    |
| Files            | Files & media               |

## Getting Your Database ID

To use the Notion API, you need your Database ID:

1. Open your database in Notion
2. Click the **•••** menu → **Copy link**
3. The URL looks like: `https://notion.so/workspace-name/DATABASE_ID?v=...`
4. Extract the 32-character ID (before the `?`)
5. Format: `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`

**Example:**

```
URL: https://notion.so/myworkspace/a1b2c3d4e5f6...?v=...
Database ID: a1b2c3d4e5f6...
```

## Troubleshooting

### Items Not Creating

* **Integration Access**: Ensure database is shared with your integration
* **Property Names**: Check that property names match exactly (case-sensitive)
* **Required Properties**: Title property must be mapped
* **Token Valid**: Verify integration token is correct

### Authentication Errors

* **Regenerate Token**: Create a new integration token in Notion
* **Workspace Access**: Ensure integration has access to workspace
* **Database Permissions**: Re-share database with integration

### Missing Data

* **Property Mapping**: Review all property mappings
* **Property Types**: Ensure data types match (email → email property)
* **Empty Values**: Check if form fields are empty
* **Character Limits**: Notion has limits on text length

### Integration Not Appearing

When sharing database:

* Refresh the integrations list
* Make sure integration is created in the correct workspace
* Check that integration status is "Active"

## Related Integrations

* [Airtable Integration](/getting-started/integrations/soon/airtable) - Alternative database solution
* [Google Sheets Integration](/getting-started/integrations/google-sheets) - Spreadsheet storage
* [Zapier Integration](/getting-started/integrations/soon/zapier) - Automation platform guide
* [Make Integration](/getting-started/integrations/soon/integromat) - Advanced automation
* [Webhooks Documentation](/getting-started/pro-features/webhooks) - Direct API integration


# Airtable

Store your Web3Forms submissions in Airtable, the flexible database that combines the power of a database with the simplicity of a spreadsheet. Perfect for organizing, filtering, and collaborating on form data.

{% hint style="info" %}
This integration uses **Webhooks**, which is a PRO feature. You must have an active PRO plan subscription to use Airtable with Web3Forms.
{% endhint %}

## What is Airtable?

[Airtable](https://airtable.com/) is a cloud-based collaboration platform that combines the features of a database, spreadsheet, and project management tool. It's ideal for storing and organizing form submissions because it offers:

* **Rich Field Types**: Text, numbers, attachments, checkboxes, dates, and more
* **Views**: Grid, calendar, kanban, gallery, and form views
* **Filtering & Sorting**: Powerful data organization tools
* **Collaboration**: Share with team members and set permissions
* **Automations**: Trigger actions based on new submissions
* **Integrations**: Connect with thousands of other apps

## Integration Methods

There are two ways to integrate Web3Forms with Airtable:

### Method 1: Using Zapier or Make (Recommended)

The easiest way to connect Web3Forms to Airtable is through automation platforms:

* **Zapier**: Simple setup with no-code interface
* **Make**: More advanced features and better free tier

### Method 2: Direct Webhook Integration

For developers, you can use Airtable's API with a custom webhook endpoint or services like Pipedream.

## Setup via Zapier

### Step 1: Create Airtable Base

1. Log in to [Airtable](https://airtable.com/)
2. Create a new base or open an existing one
3. Create a table for form submissions (e.g., "Contact Forms")
4. Add fields matching your form data:
   * Name (Single line text)
   * Email (Email)
   * Phone (Phone number)
   * Message (Long text)
   * Submitted At (Date)

**\[SCREENSHOT PLACEHOLDER: Airtable base with form submission fields]**

### Step 2: Set Up Zapier Integration

1. Go to [Zapier](https://zapier.com/) and create a new Zap
2. **Trigger**: Choose "Webhooks by Zapier" → "Catch Hook"
3. Copy the webhook URL
4. Add the webhook URL to your Web3Forms integration settings
5. Test by submitting your form

**\[SCREENSHOT PLACEHOLDER: Zapier webhook trigger setup]**

### Step 3: Configure Airtable Action

1. **Action**: Search for "Airtable" and select it
2. Choose **Create Record** as the action event
3. Connect your Airtable account
4. Select your base and table
5. Map form fields to Airtable fields:
   * Name → Name field
   * Email → Email field
   * Message → Message field
   * etc.

**\[SCREENSHOT PLACEHOLDER: Zapier Airtable action with field mapping]**

### Step 4: Test and Activate

1. Test the Zap to ensure data is being created correctly
2. Check your Airtable base for the test record
3. Turn on your Zap
4. Submit a form to verify end-to-end functionality

## Setup via Make (Integromat)

### Step 1: Create Airtable Base

Follow the same steps as in the Zapier method to create your Airtable base and table.

### Step 2: Set Up Make Scenario

1. Go to [Make](https://www.make.com/) and create a new scenario
2. Add a **Webhooks** module → **Custom webhook**
3. Create a new webhook and copy the URL
4. Add the webhook URL to Web3Forms

**\[SCREENSHOT PLACEHOLDER: Make webhook module configuration]**

### Step 3: Add Airtable Module

1. Click **+** after the webhook module
2. Search for "Airtable" and select it
3. Choose **Create a Record** as the action
4. Connect your Airtable account (you'll need an API key)
5. Select your base and table
6. Map the webhook data to Airtable fields

**\[SCREENSHOT PLACEHOLDER: Make Airtable module with field mapping]**

### Step 4: Test and Activate

1. Run the scenario once to test
2. Submit a test form
3. Verify the record appears in Airtable
4. Activate your scenario

## Airtable API Key Setup

If using Make or direct API integration, you'll need an Airtable API key:

1. Go to [Airtable Account Settings](https://airtable.com/account)
2. Click **Generate API key** in the API section
3. Copy your API key (keep it secure!)
4. Use this key when connecting to Make or other services

{% hint style="warning" %}
Never share your Airtable API key publicly or commit it to version control.
{% endhint %}

## Getting Your Base ID

To use the Airtable API, you need your Base ID:

1. Go to [Airtable API Documentation](https://airtable.com/api)
2. Select your base from the list
3. The Base ID appears in the introduction section
4. It starts with "app" (e.g., `appXXXXXXXXXXXXXX`)

## Troubleshooting

### Records Not Creating

* **Check Field Names**: Ensure field names in Airtable match your mapping
* **Field Types**: Verify field types are compatible (e.g., email field for email data)
* **API Permissions**: Make sure your API key has write permissions
* **Base Limits**: Check if you've reached Airtable plan limits

### Authentication Errors

* **Regenerate API Key**: Create a new API key in Airtable settings
* **Reconnect Account**: In Zapier/Make, reconnect your Airtable account
* **Check Permissions**: Ensure the API key has access to the specific base

### Missing Data

* **Field Mapping**: Review field mappings in your automation
* **Required Fields**: Ensure all required Airtable fields are mapped
* **Data Format**: Check that data formats match (dates, numbers, etc.)

### Rate Limits

Airtable has API rate limits:

* **Free Plan**: 5 requests per second per base
* **Paid Plans**: Higher limits available
* If you hit limits, consider batching or reducing frequency

## Related Integrations

* [Google Sheets Integration](/getting-started/integrations/google-sheets) - Alternative spreadsheet solution
* [Zapier Integration](/getting-started/integrations/soon/zapier) - Automation platform guide
* [Make Integration](/getting-started/integrations/soon/integromat) - Advanced automation
* [Webhooks Documentation](/getting-started/pro-features/webhooks) - Direct API integration


# Options Reference

{% hint style="warning" %}
This documentation is work in progress. Feel free to [contribute on Github](https://github.com/surjithctly/web3forms-docs).
{% endhint %}


# API Reference

## Form Submission using Access Key

<mark style="color:green;">`POST`</mark> `https://api.web3forms.com/submit`

This endpoint allows you to submit form submissions. The following are the reserved names that will trigger form functions. You may use any other names in your forms as you need and it will be forwarded to your email as-is.

{% hint style="info" %}
It is recommend that you use the API client/browser side, not server side.

Server side usage requires paid plan + server IP whitelisting.
{% endhint %}

#### Request Body

| Name                                          | Type    | Description                                                                                                                                                         |
| --------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| access\_key<mark style="color:red;">\*</mark> | string  | This is where you should pass your Access Key. It is required to send the form to your email address.                                                               |
| email                                         | string  | User Email. This will be used to set reply to address. So its easy to follow-up.                                                                                    |
| subject                                       | string  | Email Subject. It can be submitted by user or prefilled using `hidden` attribute.                                                                                   |
| ccemail                                       | string  | **PRO feature:** Add your co-workers to your email notification.                                                                                                    |
| replyto                                       | string  | Reply to Email. If you don't want to use `email` as replyto, you can assign a custom email here.                                                                    |
| redirect                                      | string  | <p>URL. You can use a custom URL to redirect to a page when the form submits successfully.<br><code>NOTE: Only recommended when using without JavaScript</code></p> |
| botcheck                                      | boolean | Hidden. To prevent Spam Submissions. Make sure its hidden by adding `display:none;`                                                                                 |
| attachment                                    | file    | **PRO feature:** Send a file.                                                                                                                                       |
| webhook                                       | string  | **PRO feature:** Hidden. Trigger a webhook when form is submitted.                                                                                                  |

## Form submission using Form ID

<mark style="color:green;">`POST`</mark> `https://api.web3forms.com/submit/YOUR_FORM_ID`

{% hint style="info" %}
Form ID and Access key is same UUID. Not a different one.
{% endhint %}

Use Access key as form ID in the POST URL directly if your usage did not allow you to add a hidden `access_key` field inside `<form>`

No hidden access\_key field is need to add if using this method.

#### Request Body

`[any]: [any]`

Any fields are accepted.

## Response Codes

#### `200` Success

```javascript
{
   "success":true,
   "body":{
      "data":{
        [USER SUBMITTED DATA]
      },
      "message":"Email sent successfully!"
   }
}
```

#### `303` Success Redirect

Redirects to `https://api.web3forms.com/submit/success` endpoint by default.

or custom redirect page set by user.

#### `400` Client Error

```javascript
{
   "success":false,
   "body":{
      "data":{
        [USER SUBMITTED DATA]
      },
      "message":"Error Description"
   }
}
```

#### `429` Ratelimit

```javascript
 {
   "success": false,
   "message": "Too may requests. Please try later!"
   }
}
```

#### `500` Server Error

```javascript
{
  "statusCode": 500,
  "error": "Something went wrong on server."
}
```


# Submissions API

Read your form submissions programmatically — including metadata like user IP address. This is a **read-only** REST API, separate from the form submission endpoint.

{% hint style="info" %}
The Submissions API is a **PRO feature**. Create and manage API keys from your [dashboard](https://app.web3forms.com/account/api-keys).
{% endhint %}

## Base URL

```
https://api.web3forms.com/v1
```

## Authentication

Every request must include a Bearer token in the `Authorization` header. Your API key looks like `w3f_live_…`.

```bash
curl https://api.web3forms.com/v1/forms \
  -H "Authorization: Bearer w3f_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```

{% hint style="warning" %}
Your API key is shown **only once** when you create it. Store it somewhere safe. If you lose it, revoke it and create a new one.
{% endhint %}

### Managing keys

Go to **Dashboard → Account → API Keys**:

* **Create** a key — give it a label (e.g. "Production backend"). The full key is shown once.
* **Revoke** a key — takes effect immediately; any request using it returns `401`.
* You can hold up to **10 active keys** at a time.

A key is scoped to your account and can read submissions for any form you own.

## Rate limits

Requests are throttled at **20 requests/second** (burst 50) per account. Exceeding this returns `429` with a `Retry-After` header (in seconds).

***

## List forms

<mark style="color:green;">`GET`</mark> `https://api.web3forms.com/v1/forms`

Returns all forms you own.

#### Response

```json
{
  "data": [
    {
      "form_id": "0a1b2c3d-....",
      "form_name": "Contact Form",
      "created_at": "2026-01-15T10:30:00.000Z",
      "total_count": 142
    }
  ]
}
```

***

## List submissions

<mark style="color:green;">`GET`</mark> `https://api.web3forms.com/v1/submissions`

Returns submissions for a form, newest first.

#### Query Parameters

| Name                                       | Type    | Description                                  |
| ------------------------------------------ | ------- | -------------------------------------------- |
| form\_id<mark style="color:red;">\*</mark> | string  | The form to fetch submissions for.           |
| limit                                      | integer | Page size. Default `50`, min `1`, max `100`. |
| cursor                                     | string  | Pagination cursor from a previous response.  |

#### Example

```bash
curl "https://api.web3forms.com/v1/submissions?form_id=FORM_ID&limit=50" \
  -H "Authorization: Bearer w3f_live_…"
```

#### Response

```json
{
  "data": [
    {
      "id": "sub_a1b2c3d4e5f6",
      "form_id": "0a1b2c3d-....",
      "submitted_at": "2026-05-26T18:21:09.123Z",
      "ip_address": "203.0.113.42",
      "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...",
      "site_url": "https://example.com/contact",
      "fields": {
        "name": "Jane Doe",
        "email": "jane@example.com",
        "message": "Hello!"
      },
      "attachments": []
    }
  ],
  "has_more": true,
  "next_cursor": "eyJQSyI6Ii4uLiJ9"
}
```

### Pagination

When `has_more` is `true`, pass `next_cursor` back as the `cursor` parameter to fetch the next page. Repeat until `has_more` is `false`.

```bash
curl "https://api.web3forms.com/v1/submissions?form_id=FORM_ID&cursor=NEXT_CURSOR" \
  -H "Authorization: Bearer w3f_live_…"
```

***

## Get a submission

<mark style="color:green;">`GET`</mark> `https://api.web3forms.com/v1/submissions/{id}`

Returns a single submission by its `id`.

#### Example

```bash
curl "https://api.web3forms.com/v1/submissions/sub_a1b2c3d4e5f6" \
  -H "Authorization: Bearer w3f_live_…"
```

#### Response

```json
{
  "data": {
    "id": "sub_a1b2c3d4e5f6",
    "form_id": "0a1b2c3d-....",
    "submitted_at": "2026-05-26T18:21:09.123Z",
    "ip_address": "203.0.113.42",
    "user_agent": "Mozilla/5.0 ...",
    "site_url": "https://example.com/contact",
    "fields": { "name": "Jane Doe", "email": "jane@example.com" },
    "attachments": []
  }
}
```

***

## Errors

Errors return a non-2xx status and a JSON body:

```json
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid API key"
  }
}
```

| Status | Code                  | Meaning                                           |
| ------ | --------------------- | ------------------------------------------------- |
| `400`  | `bad_request`         | Missing or invalid parameter (e.g. no `form_id`)  |
| `401`  | `unauthorized`        | Missing, malformed, or revoked key                |
| `403`  | `forbidden`           | Key not authorized for that form                  |
| `404`  | `not_found`           | Form or submission doesn't exist (or isn't yours) |
| `429`  | `rate_limit_exceeded` | Too many requests — retry after the header value  |
| `500`  | `server_error`        | Something went wrong on our end                   |


# Troubleshooting

Here are common issues with Web3Forms and how to fix them.

## Form submitted successfully but email not received

Form Submission Emails are sent instantly and will reach your inbox in seconds. In rare cases, it can take up to 1-2 minutes. Even if you don't receive any email after waiting, please make sure you check the "Promotions" or "Updates" tab if you are using Gmail. Otherwise, you can check the "Spam/Junk" folder once to confirm the email is landed there.

Once you have received the email, it is recommended to drag the email to your Primary Inbox and press "YES" when asked if you want to mark future emails as important. So all future emails from our `notify+{hash}@web3forms.com` will reach your primary inbox.

### **Bounced Emails**

Another chance is that sometimes the email might be bounced. Thus it will prevent all subsequent request to that particular email. This usally happens when you create an Access key before the email is configured.\
\
If that's the case, [contact support](https://web3forms.com/help?contact=true) and we will remove it from the **suppression list**.

### Missing MX Records

Make sure your domain has proper MX records set as suggested by your email provider. If no MX records found, we cannot deliver your message.

Verify your MX records here:

{% embed url="<https://dnschecker.org/mx-lookup.php>" %}

{% embed url="<https://mxtoolbox.com/MXLookup.aspx>" %}

#### Google Workspace issues

If you are using Google workspace, [check this link](https://support.google.com/a/answer/16004259?sjid=8694392699073914797-NC\&visit_id=639034785281386808-3518368676\&rd=1) to setup MX records for your email domain. Also make sure web3forms.com domain is allowed:

Contact Your Email Admin: If you are part of a larger organization, please check with your Google Workspace administrator to see if there are any current network issues or aggressive filtering rules for incoming mail.

Check: Google Workspace > Gmail > Spam, Phishing, and Malware screen

## Email received without any data

Ensure you have added a `name` attribute to each of your form elements. Form data is processed only if `name` attribute is present in the formData.

```html
<!-- ❌ Wrong -->

<label>Full Name</label>
<input type="text" placeholder="Full Name" />

<!-- ✅ Correct -->

<label>Full Name</label>
<input type="text" name="full_name" placeholder="Full Name" />

```

## Emails going to Spam/Junk Folder

if your Web3Forms Submission emails lands in your email provider's spam/junk folder especially if you are using hotmail or outlook, follow the steps.

1. Add *`notify@web3forms.com`* email to your contact list
2. Add our domain `web3forms.com` to your safe sender's list

<figure><img src="/files/dKuxKXj1HPkEB4gJKQS5" alt=""><figcaption><p>enabling safe sender in outlook</p></figcaption></figure>

**In Gmail:**

1. Manually mark a few of the emails as Not Spam / Not Junk
2. Move a few emails to your Primary/Main Inbox Tab
3. Add a filter to enable "Never Send to Spam" for emails coming from Web3Forms.

## CORS Error

Sometimes, you might receive a following error message while submitting form to web3forms.

{% hint style="info" %}
*Access to fetch at `https://api.web3forms.com/submit` from origin `https://yourwebsite.com` has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.*
{% endhint %}

This is not an issue with Web3Forms, but it can be easily fixed by modifying your code. By default Web3Forms allow CORS from any website, but here are few things you need to keep in mind to fix them:

Web3Forms supports two types of Content-Type

1. `x-www-form-urlencoded`
2. `application/json`

The first one is used by the browser automatically when submitting the form using the default HTML Method, There is nothing you need to configure and it works as expected in modern browsers.

The `application/json` is however to be used while sending the formData from Javascript or from your framework. So the server will return `application/json` to the client as well. Now you can show success message based on the return json or redirect to another page.

### How to fix the CORS Error in Web3Forms?

#### **301 Redirect Cors Error**

If you are using the javascript method to send the form, you should not use `redirect` in the HTML form. You should remove that and add the redirect inside the javascript success callback using `window.location.href`

```html
// ❌ Wrong

<form id="javascript_form" method="POST">
     ...
    <input type="hidden" name="redirect" value="https://web3forms.com/success">
     ...
</form> 



// ✅ Correct

<form id="javascript_form" method="POST">
     ... 
</form> 

<script>
// ...
.then(async (response) => {
  let json = await response.json();
  if (response.status == 200) {
      window.location.href = "success.html" // <-- add this line
  }
// ...   
</script>
```

#### Mixed Content-Type Error

The CORS error usually happens when you mix javascript and form-urlencoded together.

You should never use `x-www-form-urlencoded` while sending data through Web3Forms as it returns a `301` redirect after form submission. This will result in a CORS error for the user while the message delivers as usual.

To fix the issue, you must always use `application/json` for custom POST method or use the [FormData()](https://developer.mozilla.org/en-US/docs/Web/API/FormData) function provided by Javascript. This will ensure correct response from Web3Forms server.

```javascript
// ❌ Wrong 

const response = await fetch('https://api.web3forms.com/submit', {
   method: 'POST',
   headers: {
     'Content-Type': 'x-www-form-urlencoded',
   },
   body: JSON.stringify(data),
});



// ✅ Correct

const response = await fetch('https://api.web3forms.com/submit', {
   method: 'POST',
   headers: {
     'Content-Type': 'application/json',
   },
   body: JSON.stringify(data),
});

```

## Form works locally, but not working on my hosted domain.

To prevent spam & abuse, we block certain domains, sub-domains & LTDs by default. If your form works as expected in localhost and not working in your custom domain website, please [contact us](https://web3forms.com/contact) with the domain name to review. Once approved, you can submit form as usual.

To approve certain free sub-domains provided by some platforms won't be approved. So please add a custom domain and contact us if its not working. Otherwise, you would need a paid plan to allow the free sub-domain.

## 403 : This method is not allowed

Web3Forms API is expected to run on client side for spam prevention. If you call the API on the server side, you might get this method is not allowed error.

To fix this, make sure you run our API on the client side. Our API fetch should be visible in the network tab in browser developer console. Do not proxy it in another API or server side code. The access key can be public and safe to add in client side code.

If your use-case require you to use server side code, then you must add your server IP address to our Safelist + you must have an active **Paid** subscription. Please contact support with your server IP to activate server side API calls.

## 429: Rate limited because of too many requests

When we detect too many requests from single IP address in a short period of time, we block the IP for a certain period temporarily to prevent spamming or abuse of our system.

If you get this error, which means you tried to submit forms too many times quickly. Please wait for one hour and try again. For testing, make sure you take some time for each submissions to avoid rate-limits.

Rate-limits for your IP address will be removed automatically after one hour.


# FAQ

Frequently Asked Questions

## 1. Access Keys

### Do I need to hide access key?

No. You do not need to hide the access key. Access key is public. No need to confuse it with secret API key. An access key is used to send emails to a particular email. It doesn't store any sensitive data. Think of it as an alias to your email, but one step harder.

### What happens if someone else got my access key?

Nothing much. What happens if you accidentally made your email address public? They can send you emails. Similarly, if someone else has access to your access\_key, they can only send you emails.

### Can someone spam me if they got my access key?

Same as email address, they can use it to send you unsolicited emails. But Web3Forms has multiple security measures to prevent such things from happening. We have a firewall & active spam check algorithms which blocks spam emails reaching from your inbox.

As a user, you have multiple additional options to protect your form.

### How to prevent spam and Protect my form?

To protect your form from unauthorized uses, you can use following measures:

1. A**dd Captcha:** This is a simple and effective way to stop such spam as each submission must have a valid captcha token. You can use multiple captchas such as [hCaptcha](/getting-started/customizations/spam-protection/hcaptcha), [reCaptcha](/getting-started/pro-features/recaptcha-integration) or [Turnstile](/getting-started/pro-features/cloudflare-turnstile-captcha)
2. **Domain Restriction:** You can also enable domain restrictions on your form so that only forms submitted from your website will go through. All other submissions will be blocked. Please note that this is a pro feature.

## 2. GDPR & Privacy

### Are you GDPR Compliant?

We do not store any form submissions of our users. We process them and forward to your email or the endpoint you specified such as webhooks. So, we are confident that we comply with GDPR regulations, but we cannot make any legal statements. You can consult with your legal advisor to ask opinion.

There might be server logs containing personally identifiable informations which we delete periodically (every 2 months)

### Where are your servers located?

Our servers are located in the United States US-East Region. We are not based on Europe.

### Are you a registered company?

Web3forms is a subsidiary product of our parent company named Web3Creative which is a registered business based in Kerala, India. Registration Details:

Registration Certificate (LCAS): SH091040080115

IEC Code: \[redacted for privacy]

Udyam Registration: UDYAM-KL-10-0039115


# HTML & JavaScript

Sometimes you want to use JavaScript to submit the form and its possible with Web3Forms. If you use JavaScript, you can keep users on the same page instead of redirecting to other page. Also you will be able to code custom form validation or integration with other tools / services.

The initial steps are same as [Pure HTML](/getting-started/installation#step-01-get-access-key). Be sure to check to know how to create Access Key. Then use the following sample code to get started. Modify it according to your needs.

## HTML

```markup
<form method="POST" id="form">

    <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE">
    <input type="hidden" name="subject" value="New Submission from Web3Forms">
    <input type="checkbox" name="botcheck" id="" style="display: none;">

    <!-- Custom Form Data -->
    <input type="email" name="email" required>
    <input type="text" name="name" required>
    <input type="text" name="phone" required>
    <textarea name="message" required></textarea>

    <button type="submit">Submit</button>

    <div id="result"></div>

</form>
```

## JavaScript

```javascript
const form = document.getElementById('form');
const result = document.getElementById('result');

form.addEventListener('submit', function(e) {
  e.preventDefault();
  const formData = new FormData(form);
  const object = Object.fromEntries(formData);
  const json = JSON.stringify(object);
  result.innerHTML = "Please wait..."

    fetch('https://api.web3forms.com/submit', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Accept': 'application/json'
            },
            body: json
        })
        .then(async (response) => {
            let json = await response.json();
            if (response.status == 200) {
                result.innerHTML = json.message;
            } else {
                console.log(response);
                result.innerHTML = json.message;
            }
        })
        .catch(error => {
            console.log(error);
            result.innerHTML = "Something went wrong!";
        })
        .then(function() {
            form.reset();
            setTimeout(() => {
                result.style.display = "none";
            }, 3000);
        });
});
```


# JS Frameworks


# React JS

React contact form example using react-hook-form plugin

Here are the examples and guides if you are using React Framework. Click on one of the guides based on your use and needs.

* [@web3forms/react Plugin](/how-to-guides/js-frameworks/react-js/react-plugin)
* [Simple React Contact Form](/how-to-guides/js-frameworks/react-js/simple-react-contact-form)
* [Using React Hook Form](/how-to-guides/js-frameworks/react-js/react-js)
* [React File Upload Form](/how-to-guides/js-frameworks/react-js/react-file-upload-form)
* [React Hook Form File Upload](/how-to-guides/js-frameworks/react-js/react-hook-form-file-upload)


# Web3Forms React Plugin

We have an official Web3Forms React Plugin to help you send form submissions easily using Web3Forms & React, Next.js etc.

[@web3forms/react](https://www.npmjs.com/package/@web3forms/react) is available to download from [npm](https://www.npmjs.com/package/@web3forms/react) and the source on [github](https://github.com/web3forms/web3forms-react).

The following example shows how you can create a working contact form using this react hook.

First, install the plugins from NPM:

```bash
npm install @web3forms/react
npm install react-hook-form
# or
pnpm add @web3forms/react
pnpm add react-hook-form
```

Then, Import the Plugin & add the following code.

### Basic Example

```jsx
import { useState, useEffect } from "react";
// npm install react-hook-form @web3forms/react
import { useForm } from "react-hook-form";
import useWeb3Forms from "@web3forms/react";

export default function Contact() {

  const {register, reset, handleSubmit} = useForm();

  const [isSuccess, setIsSuccess] = useState(false);
  const [result, setResult] = useState(null);

  const accessKey = "YOUR_ACCESS_KEY_HERE";

  const { submit: onSubmit } = useWeb3Forms({
    access_key: accessKey,
    settings: {
      from_name: "Acme Inc",
      subject: "New Contact Message from your Website",
      // ... other settings
    },
    onSuccess: (msg, data) => {
      setIsSuccess(true);
      setResult(msg);
      reset();
    },
    onError: (msg, data) => {
      setIsSuccess(false);
      setResult(msg);
    },
  });

  return (
    <div>
    <form onSubmit={handleSubmit(onSubmit)}>
        <input type="text" {...register("name", { required: true })}>
        <input type="email" {...register("email", { required: true })}>
        <textarea {...register("message", { required: true })}></textarea>

        <button type="submit">Submit Form</button>

      </form>

      <div>{result}</div>
  </div>
 );
}
```

### Advanced Example (with tailwindcss)

{% code title="contact.js" %}

```jsx
// This example uses `@web3forms/react` plugin and tailwindcss for css styling

import { useState, useEffect } from "react";
import { useForm } from "react-hook-form";
import useWeb3Forms from "@web3forms/react";

export default function Contact() {
  const {
    register,
    handleSubmit,
    reset,
    watch,
    control,
    setValue,
    formState: { errors, isSubmitSuccessful, isSubmitting },
  } = useForm({
    mode: "onTouched",
  });
  const [isSuccess, setIsSuccess] = useState(false);
  const [message, setMessage] = useState(false);

  // Please update the Access Key in the .env
  const apiKey = process.env.PUBLIC_ACCESS_KEY || "YOUR_ACCESS_KEY_HERE";

  const { submit: onSubmit } = useWeb3Forms({
    access_key: apiKey,
    settings: {
      from_name: "Acme Inc",
      subject: "New Contact Message from your Website",
    },
    onSuccess: (msg, data) => {
      setIsSuccess(true);
      setMessage(msg);
      reset();
    },
    onError: (msg, data) => {
      setIsSuccess(false);
      setMessage(msg);
    },
  });

  return (
    <>
      <form onSubmit={handleSubmit(onSubmit)} className="my-10">
        <input
          type="checkbox"
          id=""
          className="hidden"
          style={{ display: "none" }}
          {...register("botcheck")}></input>

        <div className="mb-5">
          <input
            type="text"
            placeholder="Full Name"
            autoComplete="false"
            className={`w-full px-4 py-3 border-2 placeholder:text-gray-800 dark:text-white rounded-md outline-none dark:placeholder:text-gray-200 dark:bg-gray-900   focus:ring-4  ${
              errors.name
                ? "border-red-600 focus:border-red-600 ring-red-100 dark:ring-0"
                : "border-gray-300 focus:border-gray-600 ring-gray-100 dark:border-gray-600 dark:focus:border-white dark:ring-0"
            }`}
            {...register("name", {
              required: "Full name is required",
              maxLength: 80,
            })}
          />
          {errors.name && (
            <div className="mt-1 text-red-600">
              <small>{errors.name.message}</small>
            </div>
          )}
        </div>

        <div className="mb-5">
          <label htmlFor="email_address" className="sr-only">
            Email Address
          </label>
          <input
            id="email_address"
            type="email"
            placeholder="Email Address"
            name="email"
            autoComplete="false"
            className={`w-full px-4 py-3 border-2 placeholder:text-gray-800 dark:text-white rounded-md outline-none dark:placeholder:text-gray-200 dark:bg-gray-900   focus:ring-4  ${
              errors.email
                ? "border-red-600 focus:border-red-600 ring-red-100 dark:ring-0"
                : "border-gray-300 focus:border-gray-600 ring-gray-100 dark:border-gray-600 dark:focus:border-white dark:ring-0"
            }`}
            {...register("email", {
              required: "Enter your email",
              pattern: {
                value: /^\S+@\S+$/i,
                message: "Please enter a valid email",
              },
            })}
          />
          {errors.email && (
            <div className="mt-1 text-red-600">
              <small>{errors.email.message}</small>
            </div>
          )}
        </div>

        <div className="mb-3">
          <textarea
            name="message"
            placeholder="Your Message"
            className={`w-full px-4 py-3 border-2 placeholder:text-gray-800 dark:text-white dark:placeholder:text-gray-200 dark:bg-gray-900   rounded-md outline-none  h-36 focus:ring-4  ${
              errors.message
                ? "border-red-600 focus:border-red-600 ring-red-100 dark:ring-0"
                : "border-gray-300 focus:border-gray-600 ring-gray-100 dark:border-gray-600 dark:focus:border-white dark:ring-0"
            }`}
            {...register("message", {
              required: "Enter your Message",
            })}
          />
          {errors.message && (
            <div className="mt-1 text-red-600">
              {" "}
              <small>{errors.message.message}</small>
            </div>
          )}
        </div>

        <button
          type="submit"
          className="w-full py-4 font-semibold text-white transition-colors bg-gray-900 rounded-md hover:bg-gray-800 focus:outline-none focus:ring-offset-2 focus:ring focus:ring-gray-200 px-7 dark:bg-white dark:text-black ">
          {isSubmitting ? (
            <svg
              className="w-5 h-5 mx-auto text-white dark:text-black animate-spin"
              xmlns="http://www.w3.org/2000/svg"
              fill="none"
              viewBox="0 0 24 24">
              <circle
                className="opacity-25"
                cx="12"
                cy="12"
                r="10"
                stroke="currentColor"
                strokeWidth="4"></circle>
              <path
                className="opacity-75"
                fill="currentColor"
                d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
            </svg>
          ) : (
            "Send Message"
          )}
        </button>
      </form>

      {isSubmitSuccessful && isSuccess && (
        <div className="mt-3 text-sm text-center text-green-500">
          {message || "Success. Message sent successfully"}
        </div>
      )}
      {isSubmitSuccessful && !isSuccess && (
        <div className="mt-3 text-sm text-center text-red-500">
          {message || "Something went wrong. Please try later."}
        </div>
      )}
    </>
  );
}

```

{% endcode %}


# React Hook Form

React contact form example using react-hook-form plugin

Here's a sample React Contact Form built with `react-hook-form` plugin. See [Plugin docs here](https://react-hook-form.com/).

This example uses TailwindCSS for styling. You may use your own if needed.

```jsx
import React from "react";
import { useForm, useWatch } from "react-hook-form";

export default function ContactForm() {
  const {
    register,
    handleSubmit,
    setValue,
    reset,
    control,
    formState: { errors, isSubmitSuccessful, isSubmitting },
  } = useForm({
    mode: "onTouched",
  });
  const [isSuccess, setIsSuccess] = React.useState(false);
  const [Message, setMessage] = React.useState("");

  const userName = useWatch({ 
    control, 
    name: "name", 
    defaultValue: "Someone" 
  });
  
  useEffect(() => {
    setValue('subject', `${userName} sent a message from Website`)
  }, [userName, setValue]);

  const onSubmit = async (data, e) => {
    console.log(data);
    await fetch("https://api.web3forms.com/submit", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json",
      },
      body: JSON.stringify(data, null, 2),
    })
      .then(async (response) => {
        let json = await response.json();
        if (json.success) {
          setIsSuccess(true);
          setMessage(json.message);
          e.target.reset();
          reset();
        } else {
          setIsSuccess(false);
          setMessage(json.message);
        }
      })
      .catch((error) => {
        setIsSuccess(false);
        setMessage("Client Error. Please check the console.log for more info");
        console.log(error);
      });
  };

  return (
    <>
      <div className="w-full max-w-sm mx-auto my-5 border border-gray-100 rounded-md p-7">
        {!isSubmitSuccessful && (
          <form onSubmit={handleSubmit(onSubmit)}>
            <input
              type="hidden"
              value="YOUR_ACCESS_KEY_HERE"
              {...register("access_key")}
            />
            <input
              type="hidden"
              {...register("subject")}
            />
            <input
              type="hidden"
              value="Mission Control"
              {...register("from_name")}
            />
            <input
              type="checkbox"
              id=""
              className="hidden"
              style={{ display: "none" }}
              {...register("botcheck")}></input>

            <div className="mb-5">
              <input
                type="text"
                placeholder="Full Name"
                autoComplete="false"
                className={`w-full px-4 py-3 border-2  rounded-md outline-none  focus:ring-4  ${
                  errors.name
                    ? "border-red-600 focus:border-red-600 ring-red-100"
                    : "border-gray-300 focus:border-indigo-600 ring-indigo-100"
                }`}
                {...register("name", {
                  required: "Full name is required",
                  maxLength: 80,
                })}
              />
              {errors.name && (
                <div className="mt-1 text-red-600">
                  <small>{errors.name.message}</small>
                </div>
              )}
            </div>

            <div className="mb-5">
              <label htmlFor="email_address" className="sr-only">
                Email Address
              </label>
              <input
                id="email_address"
                type="email"
                placeholder="Email Address"
                name="email"
                autoComplete="false"
                className={`w-full px-4 py-3 border-2  rounded-md outline-none  focus:ring-4  ${
                  errors.email
                    ? "border-red-600 focus:border-red-600 ring-red-100"
                    : "border-gray-300 focus:border-indigo-600 ring-indigo-100"
                }`}
                {...register("email", {
                  required: "Enter your email",
                  pattern: {
                    value: /^\S+@\S+$/i,
                    message: "Please enter a valid email",
                  },
                })}
              />
              {errors.email && (
                <div className="mt-1 text-red-600">
                  <small>{errors.email.message}</small>
                </div>
              )}
            </div>

            <div className="mb-3">
              <textarea
                name="message"
                placeholder="Your Message"
                className={`w-full px-4 py-3 border-2  rounded-md outline-none  h-36  focus:ring-4  ${
                  errors.message
                    ? "border-red-600 focus:border-red-600 ring-red-100"
                    : "border-gray-300 focus:border-indigo-600 ring-indigo-100"
                }`}
                {...register("message", { required: "Enter your Message" })}
              />
              {errors.message && (
                <div className="mt-1 text-red-600">
                  {" "}
                  <small>{errors.message.message}</small>
                </div>
              )}
            </div>

            <button
              type="submit"
              className="w-full py-4 text-white transition-colors bg-indigo-600 rounded-md hover:bg-indigo-500 focus:outline-none focus:ring-offset-2 focus:ring focus:ring-indigo-200 px-7 umami--click--contact-submit">
              {isSubmitting ? (
                <svg
                  className="w-5 h-5 mx-auto text-white animate-spin"
                  xmlns="http://www.w3.org/2000/svg"
                  fill="none"
                  viewBox="0 0 24 24">
                  <circle
                    className="opacity-25"
                    cx="12"
                    cy="12"
                    r="10"
                    stroke="currentColor"
                    strokeWidth="4"></circle>
                  <path
                    className="opacity-75"
                    fill="currentColor"
                    d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
                </svg>
              ) : (
                "Send Message"
              )}
            </button>
          </form>
        )}
        {isSubmitSuccessful && isSuccess && (
          <>
            <div className="flex flex-col items-center justify-center text-center text-white rounded-md">
              <svg
                width="100"
                height="100"
                className="text-green-300"
                viewBox="0 0 100 100"
                fill="none"
                xmlns="http://www.w3.org/2000/svg">
                <path
                  d="M26.6666 50L46.6666 66.6667L73.3333 33.3333M50 96.6667C43.8716 96.6667 37.8033 95.4596 32.1414 93.1144C26.4796 90.7692 21.3351 87.3317 17.0017 82.9983C12.6683 78.6649 9.23082 73.5204 6.8856 67.8586C4.54038 62.1967 3.33331 56.1283 3.33331 50C3.33331 43.8716 4.54038 37.8033 6.8856 32.1414C9.23082 26.4796 12.6683 21.3351 17.0017 17.0017C21.3351 12.6683 26.4796 9.23084 32.1414 6.88562C37.8033 4.5404 43.8716 3.33333 50 3.33333C62.3767 3.33333 74.2466 8.24998 82.9983 17.0017C91.75 25.7534 96.6666 37.6232 96.6666 50C96.6666 62.3768 91.75 74.2466 82.9983 82.9983C74.2466 91.75 62.3767 96.6667 50 96.6667Z"
                  stroke="currentColor"
                  strokeWidth="3"
                />
              </svg>
              <h3 className="py-5 text-2xl text-green-500">Success</h3>
              <p className="text-gray-700 md:px-3">{Message}</p>
              <button
                className="mt-6 text-indigo-600 focus:outline-none"
                onClick={() => reset()}>
                Go back
              </button>
            </div>
          </>
        )}

        {isSubmitSuccessful && !isSuccess && (
          <div className="flex flex-col items-center justify-center text-center text-white rounded-md">
            <svg
              width="97"
              height="97"
              viewBox="0 0 97 97"
              className="text-red-400"
              fill="none"
              xmlns="http://www.w3.org/2000/svg">
              <path
                d="M27.9995 69C43.6205 53.379 52.3786 44.621 67.9995 29M26.8077 29L67.9995 69M48.2189 95C42.0906 95 36.0222 93.7929 30.3604 91.4477C24.6985 89.1025 19.554 85.6651 15.2206 81.3316C10.8872 76.9982 7.44975 71.8538 5.10454 66.1919C2.75932 60.53 1.55225 54.4617 1.55225 48.3333C1.55225 42.205 2.75932 36.1366 5.10454 30.4748C7.44975 24.8129 10.8872 19.6684 15.2206 15.335C19.554 11.0016 24.6985 7.56418 30.3604 5.21896C36.0222 2.87374 42.0906 1.66667 48.2189 1.66667C60.5957 1.66667 72.4655 6.58333 81.2172 15.335C89.9689 24.0867 94.8856 35.9566 94.8856 48.3333C94.8856 60.7101 89.9689 72.58 81.2172 81.3316C72.4655 90.0833 60.5957 95 48.2189 95Z"
                stroke="CurrentColor"
                strokeWidth="3"
              />
            </svg>

            <h3 className="text-2xl text-red-400 py-7">
              Oops, Something went wrong!
            </h3>
            <p className="text-gray-300 md:px-3">{Message}</p>
            <button className="mt-5 focus:outline-none" onClick={() => reset()}>
              Try Again
            </button>
          </div>
        )}
      </div>
      <p
        className="text-center text-sm">
        <a
          href="https://web3forms.com/"
          target="_blank"
          rel="noopener"
          className="text-indigo-500">
          Forms by Web3Froms
        </a>
      </p>
    </>
  );
}
```


# Simple React Contact Form

In this guide, you will learn how to setup a simple working contact form using React Framework and Web3Forms. No need to setup an SMTP or Custom Backend or Server. It all happens in the front end. You can copy paste to your react app and it will work.

Here's the code:

```jsx
import React from "react";

function App() {
  const [result, setResult] = React.useState("");

  const onSubmit = async (event) => {
    event.preventDefault();
    setResult("Sending....");
    const formData = new FormData(event.target);

    formData.append("access_key", "YOUR_ACCESS_KEY_HERE");

    const response = await fetch("https://api.web3forms.com/submit", {
      method: "POST",
      body: formData
    });

    const data = await response.json();

    if (data.success) {
      setResult("Form Submitted Successfully");
      event.target.reset();
    } else {
      console.log("Error", data);
      setResult(data.message);
    }
  };

  return (
    <div>
      <form onSubmit={onSubmit}>
        <input type="text" name="name" required/>
        <input type="email" name="email" required/>
        <textarea name="message" required></textarea>

        <button type="submit">Submit Form</button>

      </form>
      <span>{result}</span>

    </div>
  );
}

export default App;
```


# React File Upload Form

File uploading is one of the major features of Web3Forms. Integrating it with React is tricky. Using the following example, you can copy-paste a fully-working React File upload form.

If you are using React Hook form, Please [see this guide](/how-to-guides/js-frameworks/react-js/react-hook-form-file-upload).

{% hint style="warning" %}
Note: File Upload is only available for PRO users.
{% endhint %}

### Live Demo

{% embed url="<https://codesandbox.io/s/react-file-upload-form-o4deqz?file=/src/App.js>" %}
React File Upload Form
{% endembed %}

Here's the code:

```jsx
import React from "react";

function App() {
  const [result, setResult] = React.useState("");

  const onSubmit = async (event) => {
    event.preventDefault();
    setResult("Sending....");
    const formData = new FormData(event.target);

    formData.append("access_key", "YOUR_ACCESS_KEY_HERE");

    const res = await fetch("https://api.web3forms.com/submit", {
      method: "POST",
      body: formData
    }).then((res) => res.json());

    if (res.success) {
      console.log("Success", res);
      setResult(res.message);
    } else {
      console.log("Error", res);
      setResult(res.message);
    }
  };

  return (
    <div className="App">
      <h1>React File Upload Form</h1>
      <form onSubmit={onSubmit}>
        <input type="text" name="name"/>
        <input type="email" name="email"/>
        <input type="file" name="attachment" />
        <input type="submit" />
      </form>
      <span>{result}</span>
    </div>
  );
}

export default App;
```


# React Google ReCaptcha v3

Next.js Example

In this example, you can see a working google reCaptcha v3 (Invisible captcha) with React Hook Form.

{% hint style="warning" %}
Note: File Upload is only available for PRO users.
{% endhint %}

### Live Demo

{% embed url="<https://codesandbox.io/s/react-next-js-simple-google-recaptcha-v3-q21ov7?file=/pages/index.tsx>" %}
Invisible Google reCaptcha.
{% endembed %}

Here's the code:

```jsx
import React from "react";
import { useForm } from "react-hook-form";
import Script from "next/script";

function App() {
  const { register, handleSubmit, setValue } = useForm();
  const [result, setResult] = React.useState("");
  const [captchatoken, setCaptchaToken] = React.useState("");

  React.useEffect(() => {
    setValue("recaptcha_response", captchatoken);
  });

  const onSubmit = async (data) => {
    console.log(data);

    setResult("Sending....");
    const formData = new FormData();

    formData.append("access_key", "YOUR_ACCESS_KEY_HERE");

    for (const key in data) {
      if (key === "file") {
        formData.append(key, data[key][0]);
      } else {
        formData.append(key, data[key]);
      }
    }

    const res = await fetch("https://api.web3forms.com/submit", {
      method: "POST",
      body: formData
    }).then((res) => res.json());

    if (res.success) {
      console.log("Success", res);
      setResult(res.message);
    } else {
      console.log("Error", res);
      setResult(res.message);
    }
  };

  return (
    <div className="App">
      <h1>React Hook Form File Upload</h1>
      <form onSubmit={handleSubmit(onSubmit)}>
        <input type="text" placeholder="Name" {...register("name")} />
        <br />
        <br />
        <input type="email" placeholder="Email" {...register("email")} />
        <br />
        <br />
        <input type="file" {...register("file")} />
        <br />
        <input
          type="hidden"
          {...register("recaptcha_response")}
          id="recaptchaResponse"
        />
        <br />
        <input type="submit" />
      </form>
      <br />
      <span>{result}</span>

      <Script
        id="recaptcha-load"
        strategy="lazyOnload"
        src={`https://www.google.com/recaptcha/api.js?render=RECAPTCHA_SITE_KEY`}
        onLoad={() => {
          grecaptcha.ready(function () {
            grecaptcha
              .execute("RECAPTCHA_SITE_KEY", {
                action: "contact"
              })
              .then(function (token) {
                //console.log(token);
                setCaptchaToken(token);
              });
          });
        }}
      />
    </div>
  );
}

export default App;

```


# React Hook Form File Upload

File uploading is one of the major features of Web3Forms. Integrating it with React is tricky. Using the following example, you can copy-paste a fully-working React File upload form.

If you are NOT using React Hook form, Please [see this guide](/how-to-guides/js-frameworks/react-js/react-file-upload-form).

{% hint style="warning" %}
Note: File Upload is only available for PRO users.
{% endhint %}

### Live Demo

{% embed url="<https://codesandbox.io/s/react-hook-form-file-upload-km3bsh?file=/src/App.js>" %}
React Hook Form File Upload
{% endembed %}

Here's the code:

```jsx
import React from "react";
import { useForm } from "react-hook-form";

function App() {
  const { register, handleSubmit } = useForm();
  const [result, setResult] = React.useState("");

  const onSubmit = async (data) => {
    console.log(data);

    setResult("Sending....");
    const formData = new FormData();

    formData.append("access_key", "YOUR_ACCESS_KEY_HERE");

    for (const key in data) {
      if (key === "file") {
        formData.append(key, data[key][0]);
      } else {
        formData.append(key, data[key]);
      }
    }

    const res = await fetch("https://api.web3forms.com/submit", {
      method: "POST",
      body: formData
    }).then((res) => res.json());

    if (res.success) {
      console.log("Success", res);
      setResult(res.message);
    } else {
      console.log("Error", res);
      setResult(res.message);
    }
  };

  return (
    <div className="App">
      <h1>React Hook Form File Upload</h1>
      <form onSubmit={handleSubmit(onSubmit)}>
        <input type="text" placeholder="Name" {...register("name")} />
        <br />
        <br />
        <input type="email" placeholder="Email" {...register("email")} />
        <br />
        <br />
        <input type="file" {...register("file")} />
        <br />
        <br />
        <input type="submit" />
      </form>
      <br />
      <span>{result}</span>
    </div>
  );
}

export default App;

```


# Vue JS

```html
<script setup lang="ts">
import { ref } from "vue";
const WEB3FORMS_ACCESS_KEY = "YOUR_ACCESS_KEY_HERE";
const name = ref("")
const email = ref("")
const message = ref("")

const submitForm = async () => {
  const response = await fetch("https://api.web3forms.com/submit", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json",
    },
    body: JSON.stringify({
      access_key: WEB3FORMS_ACCESS_KEY,
      name: name.value,
      email: email.value,
      message: message.value,
    }),
  });
  const result = await response.json();
  if (result.success) {
    console.log(result);
  }
}
</script>
<template>
  <form @submit.prevent="submitForm">
    <input type="text" name="name" v-model="name"/>
    <input type="email" name="email"  v-model="email"/> 
    <textarea name="message" v-model="message"></textarea>
    <button type="submit">Send Message</button>
  </form>
</template>
```


# Svelte

Here's a simple working contact form code example for Svelte with Web3Forms

```markup
<script>
let status = "";
const handleSubmit = async data => {
  status = 'Submitting...'
  const formData = new FormData(data.currentTarget)
  const object = Object.fromEntries(formData);
  const json = JSON.stringify(object);

  const response = await fetch("https://api.web3forms.com/submit", {
      method: "POST",
      headers: {
          "Content-Type": "application/json",
          Accept: "application/json",
      },
      body: json
  });
  const result = await response.json();
  if (result.success) {
      console.log(result);
      status = result.message || "Success"
  }
}
</script>

<form on:submit|preventDefault={handleSubmit}>
    <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE">
    <input type="text" name="name" required />
    <input type="email" name="email" required />
    <textarea name="message" required rows="3"></textarea>
    <input type="submit" />
</form>

<div>{status}</div>
```


# Angular JS

## Prerequisites

Angular basics:

* ***Services***
* ***TemplateForms***

***

## Let's move to the code part:

* Let's assume that you already initialized your app and you have your component that has the form.

1. Create a service (***mail***)

```js
ng generate service services/mail
```

* define a method called (***sendEmail()***) that will return a *Promise* and accept a parameter (***formData***) that has type of (***FormData***).
* in the method we are going to return the *Promise* of the built in function (***fetch()***), which is accepting 2 arguments:

1. API endpoint: `https://api.web3forms.com/submit`.
2. Object with 2 properties: `{ method: 'POST', body: formData }`

* our ***service mail*** method should look like:

```js
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class MailService {
  constructor() {}

  sendEmail(formData: FormData): Promise<Response> {
    return fetch('https://api.web3forms.com/submit', {
      method: 'POST',
      body: formData,
    });
  }
}
```

* that's it for the ***mail service***.

***

* Now let's take a look at the HTML ***form***:

*We are you using TailwindCSS for styling*

```js
<!-- Form -->
<div class="mt-8">
<form
  class="flex flex-col gap-3"
  #contactForm="ngForm"
  (ngSubmit)="submitEmail(contactForm)"
>
  <!-- Name field -->
  <div>
    <input
      name="name"
      [(ngModel)]="contactFormValues.name"
      #name="ngModel"
      type="text"
      placeholder="Full Name"
      class="w-full p-2 border border-gray-200 rounded-md"
      required
      minlength="2"
    />
    <!-- input error message -->
    <p
      class="ml-1 text-red-400 text-sm"
      *ngIf="name.errors && name.touched && name.dirty"
    >
      name is required
    </p>
  </div>
  <!-- email field -->
  <div>
    <input
      name="email"
      [(ngModel)]="contactFormValues.email"
      #email="ngModel"
      type="email"
      placeholder="Email"
      class="w-full p-2 border border-gray-200 rounded-md"
      required
      pattern="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"
    />
    <!-- input error message -->
    <p
      class="ml-1 text-red-400 text-sm"
      *ngIf="email.errors && email.touched && email.dirty"
    >
      invalid email
    </p>
  </div>
  <!-- body field -->
  <div>
    <textarea
      name="body"
      [(ngModel)]="contactFormValues.body"
      #body="ngModel"
      cols="30"
      rows="10"
      class="w-full p-2 border border-gray-200 rounded-md"
      placeholder="Message"
      required
      minlength="20"
    ></textarea>
    <!-- input error message -->
    <p
      class="ml-1 text-red-400 text-sm"
      *ngIf="body.errors && body.touched && body.dirty"
    >
      at least write some words (20 characters length)
    </p>
  </div>
  <!-- Alert -->
  <div
    [ngClass]="{
      hidden: !showAlert
    }"
  >
    <p [ngClass]="alertColor" class="font-semibold">
      {{ alertMessage }}
    </p>
  </div>
  <!-- submit button -->
  <button
    [disabled]="contactForm.invalid || onSubmit"
    class="p-2 rounded-md font-bold uppercase text-white bg-light-color hover:bg-primary-color transition disabled:opacity-50 disabled:bg-light-color"
  >
    <ng-container *ngIf="onSubmit === false; else submittingEmail">
      send
    </ng-container>
    <ng-template #submittingEmail>
      <div class="animate-spin">
        <fa-icon [icon]="iconLoad"></fa-icon>
      </div>
    </ng-template>
  </button>
</form>
```

* As you can see we are assigning the values of the inputs to an object in our component class (***contactFormValues***) with the help of ***template forms***, and we have a button being used to submit the form as well as we have (***ng-container***) and (***ng-template***) inside the button tag to display whether the text (***send***) or show a spinning animated (***icon***) that indicates the form is being submitted.
* Let's take a look at the component class properties and methods:

> - Class properties:

```js
  constructor(
    private mailService: MailService
  ) {}

  private color: string = '';
  showAlert: boolean = false;
  alertMessage: string = '';
  onSubmit: boolean = false;
  iconLoad = faArrowRotateForward;
  contactFormValues = {
    name: '',
    email: '',
    body: '',
  };
```

> * Class methods:

```js
get alertColor() {
  return `text-${this.color}-400`;
}

hideAlert() {
  setTimeout(() => {
    this.showAlert = false;
  }, 5000);
}

async submitEmail(contactForm: NgForm) {
  this.onSubmit = true;
  // -- set formData values
  let formData: FormData = new FormData();
  formData.append('name', this.contactFormValues.name);
  formData.append('email', this.contactFormValues.email);
  formData.append('body', this.contactFormValues.body);
  // -- email customization
  formData.append('access_key', environment.form_access_key);
  formData.append('subject', 'Email Support From Your Site');
  formData.append('from_name', 'Contact Notification');

  try {
    // -- send email
    const res = await this.mailService.sendEmail(formData);
    if (!res.ok) {
      throw new Error();
    }
    this.alertMessage = 'Email sent successfully!';
    this.color = 'green';
    contactForm.reset();
  } catch (err) {
    // handle error
    this.alertMessage = 'Something went wrong, try again later!';
    this.color = 'red';
  }
  // -- reset submit and hide alert
  this.onSubmit = false;
  this.showAlert = true;
  this.hideAlert();
}
```

## Class properties explanation:

* `showAlert: boolean = false;` To display alert message (success or fail).
* `alertMessage: string = '';` To hold the alert message.
* `onSubmit: boolean = false;` To set and track submit state.
* `iconLoad = faArrowRotateForward;` To define and rename the icon from (fontAwesome library).
* contactFormValues `contactFormValues = { name: '', email: '', body: '', };`

To hold the inputs' values with the help of the template forms of Angular.

## Class methods explanation:

* `hideAlert()` To hide the alert message after 5 seconds.
* `submitEmail(contactForm)` An async function that accepts an instance of the ***NgForm*** to handle the submit form and in this method let's explain 3 parts of it:

1. Create a formData instance and append values (contactFormValues) because it is the way that *Web3Forms* accepts the form.

* `formData.append('name', this.contactFormValues.name);` add input value (***name***) from template to formData, follow the same steps to add the other inputs' values (***email***, ***body***).
* grab your ***access key*** from email you received earlier and add it into the environment variables, in our case we called it (***form\_access\_key***) see example below:
* `formData.append('access_key', environment.form_access_key);`
* `formData.append('subject', 'Email Support From Your Site');` to set subject text.
* `formData.append('from_name', 'Contact Notification');` to set a name for the form.

You can read more about customizations here: [Web3Forms Customization](https://docs.web3forms.com/getting-started/customizations)

2. `try | catch` blocks, in the `try` block we are calling the `mailService.sendEmail()` method to submit the form and in case the form was successfully submitted we show a success message and reset the values to `null` by the help of the instance `NgForm` that has `reset()` method, in our case it is `contactForm.reset()`, and in case there is an error we added a ***guard clause*** and inside its block we throw an error to force the code to jump to the `catch` block and show an error message.
3. and at the end of the method we reset `onSubmit` property to `false`, `showAlert` to `true` and call the `hideAlert()` method.

***

> ***Congratulations! You are all set up and ready to go.***

***

*This article is written by* [*CoderNadir*](https://dev.to/codernadir)


# Alpine.js

Here's a simple Alpine.js Contact Form Code example with Web3Forms

```markup
<form x-data="contactForm()" @submit.prevent="submit">
    <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE">
    <input type="text" name="name" required />
    <input type="email" name="email" required />
    <textarea name="message" required rows="3"></textarea>
    <button type="submit" :disabled="loading">Submit</button>
    <div x-text="status"></div>
</form>

<script>
function contactForm() {
  return {
    buttonText: "Submit",
    loading: false,
    status: "",
    async submit(event) {
      const formData = new FormData(event.target);
      const object = Object.fromEntries(formData);
      const json = JSON.stringify(object);

      this.status = "Submitting...";
      this.loading = true;

      const response = await fetch("https://api.web3forms.com/submit", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Accept: "application/json"
        },
        body: json
      });
      const result = await response.json();
      if (result.success) {
        console.log(result);
        this.status = result.message || "Success";
      }
      this.loading = false;
    }
  };
}
</script>
```


# Site Builders


# Webflow

Here's a guide on how to integrate Web3Forms with Webflow using Form Block and HTML Embed

**Example Demo:** [**https://web3forms-contact-form.webflow.io/**](https://web3forms-contact-form.webflow.io/)

### 1. Create a Form Block in Webflow

First, you need to drag the form block element from the Webflow sidebar to your website.

<figure><img src="/files/lJAnazmjkCEKU06qWMFc" alt="" width="282"><figcaption><p>Drag the form block the canvas</p></figcaption></figure>

### 2. Create a hidden input field in Webflow

To add our access key, we need to create a hidden input field in webflow to make our contact form work. For that, we use the HTML Embed Option.

<figure><img src="/files/hwL7W2U11NxwMmVc29PE" alt="" width="245"><figcaption><p>Drag Embed Option inside the &#x3C;Form> Block</p></figcaption></figure>

### 3. Add Access Key inside the HTML Embed Block

Now, add the hidden HTML Code as shown below inside the code editor and click Save.

<figure><img src="/files/2zUuTY8XKaTS8NZSlEtn" alt="" width="563"><figcaption></figcaption></figure>

Make sure the embed block is inside the Form Block.

<figure><img src="/files/huhlHD7ERRmPnknBFQcu" alt="" width="241"><figcaption></figcaption></figure>

### 4. Add Form Action URL

Now, setup the form action URL by selecting the form element and choose "Settings" from the right sidebar. Make sure you select **`POST`** as method.

Action URL: `https://api.web3forms.com/submit`

<figure><img src="/files/KXjScWDWrbIv0tlqPImv" alt="" width="240"><figcaption></figcaption></figure>

### 5. Done.

That's it. Web3forms Contact form will work with your Webflow Website now. You can add more customization features like custom redirect, email subject etc using the hidden field similar to step 3. Refer to the [Customizations](/getting-started/customizations) section for more details.


# Framer

Here's a guide on how to integrate Custom Contact Forms in Framer using Web3Forms

Here's a step by step instructions on how to setup Web3Forms with the new Framer Forms feature.

**Live Demo /Remix:** [**https://web3forms-remix.framer.website/**](https://web3forms-remix.framer.website/)

### Framer forms Pricing

Framer forms is providing only 50 submissions per month for free. Once you upgrade to Basic which is $15/m or Pro for $30/mo, you will get 500 & 2500 submissions per month respectively.

In contrast, using Web3Forms, you will get 250 free submissions per month. Web3Forms provides unlimited submissions for Pro plans which start from $8/mo.

*Source:* [*https://www.framer.com/pricing/*](https://www.framer.com/pricing/) *&* [*https://web3forms.com/pricing*](https://web3forms.com/pricing)

However, you can now use Web3Forms in Framer. Here are the step by step instructions on how you can use it.

{% hint style="info" %}
Currently, Framer uses their own proxy for the Web3Forms endpoint which is causing to hit the Framer limit once 50 submissions are reached. You must contact Framer support and ask them to remove the proxy and let you use our endpoint directly.
{% endhint %}

## Step 1: Drag and Drop the form builder

Once you are on the framer project, Click on Insert -> Form -> Form Builder. The drag them to your canvas.

<figure><img src="/files/9QJsgrgRFfcjvcSsKqQP" alt=""><figcaption></figcaption></figure>

## Step 2: Add Web3Forms Access Key

Once you drag and drop the form, you can then add a hidden access\_key you have generated from Web3Forms Home Page.

Click on the + button below the form and add a new "Text" field.

<div align="center"><figure><img src="/files/CL0o8DOkOfFnOlbkjnlA" alt="" width="563"><figcaption></figcaption></figure></div>

Click on the **Label** and remove it. We do not need that for this input.

Now, click on that textbox field which opens up a right side panel. Click on the **+** button right to the text Input and choose **Hidden.** Now click the + again to add the **Value** field.

<figure><img src="/files/0VB1s8TbEqRpYzm16aCN" alt=""><figcaption></figcaption></figure>

Now, edit the following:

Change Type to Text.

Name: access\_key

Value: Insert your access\_key here

Placeholder: Remove Value

Required: Yes

<figure><img src="/files/RjHcWFfsg92Cv4B1QCLn" alt="" width="334"><figcaption></figcaption></figure>

## Step 3: Add Web3Forms Endpoint

Now, click on the main Form wrapper which opens up a Form panel in the right sidebar.

Click on the Send To dropdown and choose Webhook. Then add the Web3Forms API endpoint in the Popup. Our endpoint is: `https://api.web3forms.com/submit`

<figure><img src="/files/GDenDlftbz5IKF2NS6AM" alt="" width="563"><figcaption></figcaption></figure>

## Step 4: Test & Publish

That's it. Done. You can customize form fields as per your requirement or add more hidden inputs for customizing email subject, from\_name etc. Once done. Click on the Play button to preview the website. If everything's good, you can publish the framer website. Now you have a fully customizable working contact form in Framer.

{% hint style="danger" %}
Currently, Framer uses their own proxy for the Web3Forms endpoint which is causing to hit the Framer limit once 50 submissions are reached. You must contact Framer support and ask them to remove the proxy and let you use our endpoint directly.
{% endhint %}

If this method does not work for you, you can choose the old method which still works. Here are the steps:

## Framer Forms - Old Method

Framer default contact form is limited. It only allows 2-3 fields and only support a single form backend solution. Using Web3Forms, you can setup a free custom contact form in framer without any custom code. Open the demo website, duplicate the page and you can copy-paste the section to your own project and add unlimited fields and inputs without limitation.

**Example Demo:** [**https://web3forms.framer.website/**](https://web3forms.framer.website/)

### **Step 1: Remix / Duplicate the Form Component**

Visit our demo link above and click on the Remix / Duplicate link in the top right corner. Then a copy of the same page will be opened in your Framer Workspace.

<figure><img src="/files/sf50H2P2jkTwSRwUJz2A" alt="" width="563"><figcaption><p>Remix Button in the Pre-made Demo</p></figcaption></figure>

### Step 2: Add Access Key in a hidden input field

Once you duplicated the project, you can copy it again to your project. Once it's on the page you wanted, click on the Web3Forms Form Area and it will open the Sidebar with customization options.

<figure><img src="/files/uuY09KY5S4HCFHNzBYyT" alt="" width="252"><figcaption><p>Web3Forms Customization Options</p></figcaption></figure>

Now, Click on the **Inputs** and choose Access Key in the bottom.

<div align="center"><figure><img src="/files/UaxwBlrOEYkK9w1JHcBn" alt="" width="250"><figcaption></figcaption></figure></div>

Then, in the panel, replace the `YOUR_ACCESS_KEY_HERE` value with your own access key from Web3Forms.

<figure><img src="/files/9VTqUTRH3WpWyR64oLBR" alt="" width="248"><figcaption><p>Replace Access Key with yours</p></figcaption></figure>

### Step 3: Customize yourself

You can add more inputs, change name, values or even style by double clicking and edit the code. Have fun!


# Carrd.co

{% hint style="warning" %}
This documentation is work in progress. Feel free to [contribute on Github](https://github.com/surjithctly/web3forms-docs).
{% endhint %}


# Squarespace

{% hint style="warning" %}
This documentation is work in progress. Feel free to [contribute on Github](https://github.com/surjithctly/web3forms-docs).
{% endhint %}


# Wix

Setup Web3Forms Form Submission in your Wix Website

## Step 1: Login to your Account

Login to your Wix Account and visit your Dashboard. There you can see the your Website Name. Just click the **Site Actions** Dropdown and then click **Edit Site**. See screenshot below.

![](/files/-MQS2kw_ePSMy4jz9woQ)

## Step 2: Add the Widget

Now Click on the **+ Add** icon from the left menu and choose **Embed** => **Custom Embeds** => **Embed a Widget**. See screenshot below

![](/files/-MQS3egjFCHJcX2iHND1)

## Step 3: Add the Form

Now, you can use the code from[ HTML & JavaScript](/how-to-guides/html-and-javascript) page to paste it in the textbox. Then edit the **form fields** and your **Access Key**.

## Step 4: Save & Publish

That's it. Now you can Save & Publish your page. Then open the page you've added the form in the browser. You might need to clear the cache if you don't see the changes instantly.


# Dorik

{% hint style="warning" %}
This documentation is work in progress. Feel free to [contribute on Github](https://github.com/surjithctly/web3forms-docs).
{% endhint %}


# Static Site Generators


# Next.js

## Simple example using in Next.js

A simple example of implementing Web3Forms in a Next.js project. You can see an advanced version using [react-hook-form here](https://docs.web3forms.com/how-to-guides/js-frameworks/react-js)

```jsx
export function Contact() {
    async function handleSubmit(e) {
        e.preventDefault();
        const response = await fetch("https://api.web3forms.com/submit", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                Accept: "application/json",
            },
            body: JSON.stringify({
                access_key: "YOUR_ACCESS_KEY_HERE",
                name: e.target.name.value,
                email: e.target.email.value,
                message: e.target.message.value,
            }),
        });
        const result = await response.json();
        if (result.success) {
            console.log(result);
        }
    }

  return (
    <>
      <form onSubmit={handleSubmit}>
          <div>
              <label htmlFor="name">Name</label>
              <input type="text" name="name" required placeholder="Your name" />
          </div>
          <div>
              <label htmlFor="email">Email</label>
              <input type="email" name="email" required placeholder="email@example.com" />
          </div>
          <div>
              <label htmlFor="message">Message</label>
              <textarea name="message" required rows="3" placeholder="Enter Message"></textarea>
          </div>
          <button type="submit">Submit Form</button>
      </form>
    </>
  );
}
```

## File Upload Form in Next.js

Here's a simple example code for a file upload contact form in Next.js using React Hook Form.

```jsx
import React from "react";
import { useForm } from "react-hook-form";

function App() {
    const { register, handleSubmit } = useForm();

    const onSubmit = async (data) => {
        const formData = new FormData(data);
        
        formData.append("access_key", "YOUR_ACCESS_KEY_HERE");
        formData.append("file", data.file[0]);

        const res = await fetch("https://api.web3forms.com/submit", {
            method: "POST",
            body: formData,
        }).then((res) => res.json());
        
        if (res.success) {
            console.log("Success", res);
        } else {
        console.log("Error", res);
        }
    };

    return (
        <div className="App">
            <form onSubmit={handleSubmit(onSubmit)}>
                <input type="text" name="name" />
                <input type="file" {...register("file")} />

                <input type="submit" />
            </form>
        </div>
    );
}

export default App;
```


# Astro

Custom Contact form for Astro

Here's a working contact form example for Astro with Web3Forms

```html
---
import Button from "./ui/button.astro";
---

<!-- // Styling Requires Tailwind CSS -->
<form
  action="https://api.web3forms.com/submit"
  method="POST"
  id="form"
  class="needs-validation"
  data-astro-reload
  novalidate>
  
   <!-- Add your Web3Forms Access Key -->
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE" />
  
  <input type="checkbox" class="hidden" style="display:none" name="botcheck" />
  <div class="mb-5">
    <input
      type="text"
      placeholder="Full Name"
      required
      class="w-full px-4 py-3 border placeholder:text-slate-400 rounded-md outline-none focus:ring-4 border-slate-300 focus:border-slate-600 ring-slate-100"
      name="name"
    />
    <div class="empty-feedback invalid-feedback text-red-400 text-sm mt-1">
      Please provide your full name.
    </div>
  </div>
  <div class="mb-5">
    <label for="email_address" class="sr-only">Email Address</label><input
      id="email_address"
      type="email"
      placeholder="Email Address"
      name="email"
      required
      class="w-full px-4 py-3 border placeholder:text-slate-400 rounded-md outline-none focus:ring-4 border-slate-300 focus:border-slate-600 ring-slate-100"
    />
    <div class="empty-feedback text-red-400 text-sm mt-1">
      Please provide your email address.
    </div>
    <div class="invalid-feedback text-red-400 text-sm mt-1">
      Please provide a valid email address.
    </div>
  </div>
  <div class="mb-3">
    <textarea
      name="message"
      required
      placeholder="Your Message"
      class="w-full px-4 py-3 border placeholder:text-slate-400 rounded-md outline-none h-36 focus:ring-4 border-slate-300 focus:border-slate-600 ring-slate-100"
    ></textarea>
    <div class="empty-feedback invalid-feedback text-red-400 text-sm mt-1">
      Please enter your message.
    </div>
  </div>
  <Button type="submit" size="lg" block>Send Message</Button>
  <div id="result" class="mt-3 text-center"></div>
</form>

<style>
  .invalid-feedback,
  .empty-feedback {
    display: none;
  }

  .was-validated :placeholder-shown:invalid ~ .empty-feedback {
    display: block;
  }

  .was-validated :not(:placeholder-shown):invalid ~ .invalid-feedback {
    display: block;
  }

  .is-invalid,
  .was-validated :invalid {
    border-color: #dc3545;
  }
</style>

<script is:inline>

  // use astro:page-load event if you are using View Transitions

  document.addEventListener("DOMContentLoaded", () => {
  
      const form = document.getElementById("form");
      const result = document.getElementById("result");

      form.addEventListener("submit", function (e) {
        e.preventDefault();
        form.classList.add("was-validated");
        if (!form.checkValidity()) {
          form.querySelectorAll(":invalid")[0].focus();
          return;
        }
        const formData = new FormData(form);
        const object = Object.fromEntries(formData);
        const json = JSON.stringify(object);

        result.innerHTML = "Sending...";

        fetch("https://api.web3forms.com/submit", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            Accept: "application/json",
          },
          body: json,
        })
          .then(async (response) => {
            let json = await response.json();
            if (response.status == 200) {
              result.classList.add("text-green-500");
              result.innerHTML = json.message;
            } else {
              console.log(response);
              result.classList.add("text-red-500");
              result.innerHTML = json.message;
            }
          })
          .catch((error) => {
            console.log(error);
            result.innerHTML = "Something went wrong!";
          })
          .then(function () {
            form.reset();
            form.classList.remove("was-validated");
            setTimeout(() => {
              result.style.display = "none";
            }, 5000);
          });
      });
    },
    { once: true },
  );
</script>
```


# Nuxt.js

Create a working contact form in nuxt 3 using web3forms.

Here's a simple Contact form Example Code for Nuxt 3 with Web3Forms

```markup
<template>
  <form @submit.prevent="submitForm">
    <input type="text" name="name" v-model="form.name" />
    <input type="email" name="email" v-model="form.email" />
    <textarea name="message" v-model="form.message"></textarea>
    <button type="submit">Send Message</button>
  </form>
</template>

<script setup>
const form = ref({
  access_key: "YOUR_ACCESS_KEY_HERE",
  subject: "New Submission from Web3Forms",
  name: "",
  email: "",
  message: "",
});

const result = ref("");
const status = ref("");

const submitForm = async () => {
  try {
    status.value = "loading";
    const response = await $fetch("https://api.web3forms.com/submit", {
      method: "POST",
      body: form.value,
    });
    console.log(response);
    result.value = response.message;
    if (response.status === 200) {
      status.value = "success";
    } else {
      console.log(response); // Log for debugging, can be removed
      status.value = "error";
    }
  } catch (error) {
    console.log(error); // Log for debugging, can be removed
    status.value = "error";
    result.value = "Something went wrong!";
  } finally {
    // Reset form after submission
    form.value.name = "";
    form.value.email = "";
    form.value.message = "";

    // Clear result and status after 5 seconds
    setTimeout(() => {
      result.value = "";
      status.value = "";
    }, 5000);
  }
};
</script>
```

## Nuxt UI

Here's another example if you are using Nuxt UI

```html
<template>
  <UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
    <UFormGroup label="Name" name="name">
      <UInput v-model="state.name" />
    </UFormGroup>

    <UFormGroup label="Email" name="email">
      <UInput v-model="state.email" />
    </UFormGroup>

    <UFormGroup label="Message" name="message">
      <UTextarea v-model="state.message" type="text" />
    </UFormGroup>

    <UButton type="submit"> Submit </UButton>
  </UForm>
</template>

<script setup>
import { z } from "zod";

const schema = z.object({
  name: z.string().min(2, "Must be at least 2 characters"),
  email: z.string().email("Invalid email address"),
  message: z.string().min(10, "Must be at least 10 characters"),
  subject: z.string().min("Subject required"),
  access_key: z.string().min("Access key is required"),
});

const state = reactive({
  access_key: "YOUR_ACCESS_KEY_HERE",
  subject: "New Submission from Web3Forms",
  name: "",
  email: "",
  message: "",
});

async function onSubmit(event) {
  result.value = "Please wait...";
  try {
    const response = await $fetch("https://api.web3forms.com/submit", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: form.value,
    });

    console.log(response); // You can remove this line if you don't need it

    result.value = response.message;

    if (response.status === 200) {
      status.value = "success";
    } else {
      console.log(response); // Log for debugging, can be removed
      status.value = "error";
    }
  } catch (error) {
    console.log(error); // Log for debugging, can be removed
    status.value = "error";
    result.value = "Something went wrong!";
  } finally {
    // Reset form after submission
    form.value.name = "";
    form.value.email = "";
    form.value.message = "";

    // Clear result and status after 5 seconds
    setTimeout(() => {
      result.value = "";
      status.value = "";
    }, 5000);
  }
}
</script>
```


# Hugo

Here's a working contact form example for Hugo with Web3Forms

```markup
<form action="https://api.web3forms.com/submit" method="POST">

    <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE">

    <input type="text" name="name" required>
    <input type="email" name="email" required>
    <textarea name="message" required></textarea>
    <button type="submit">Submit Form</button>

</form>
```


# Jekyll

```markup
<form action="https://api.web3forms.com/submit" method="POST">

    <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE">

    <input type="text" name="name" required>
    <input type="email" name="email" required>
    <textarea name="message" required></textarea>
    <button type="submit">Submit Form</button>

</form>
```


# Gatsby

Gatsby Contact Form - Simple Working Example Code with Web3Forms

```jsx
import React from "react";

export default function ContactPage() {
  return (
      <form method="POST" action="https://api.web3forms.com/submit">

        <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE">

        <input type="text" name="name"/>
        <input type="email" name="email"/>
        <textarea name="message"></textarea>
        <button type="submit">Submit Form</button>
      </form>
  );
}
```


# Gridsome

Here's a simple Contact form Working Example for Gridsome with Web3Forms

```markup
<template>
    <form @submit.prevent="submitForm">
      <input type="text" name="name" v-model="name"/>
      <input type="email" name="email"  v-model="email"/>
      <textarea name="message" v-model="message"></textarea>
      <button type="submit">Send Message</button>
    </form>
  </template>

  <script>
  const WEB3FORMS_ACCESS_KEY = "YOUR_ACCESS_KEY_HERE";

  export default {
    data() {
      return {
        name: "",
        email: "",
        message: "",
      };
    },
    methods: {
      async submitForm() {
        const response = await fetch("https://api.web3forms.com/submit", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            Accept: "application/json",
          },
          body: JSON.stringify({
            access_key: WEB3FORMS_ACCESS_KEY,
            name: this.name,
            email: this.email,
            message: this.message,
          }),
        });
        const result = await response.json();
        if (result.success) {
          console.log(result);
        }
      },
    },
  };
  </script>
```


# Eleventy

Eleventy Contact form working code example with Web3Forms

```html
<form action="https://api.web3forms.com/submit" method="POST">

    <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE">

    <input type="text" name="name" required>
    <input type="email" name="email" required>
    <textarea name="message" required></textarea>
    <button type="submit">Submit Form</button>

</form>
```


# Hosting Providers


# Vercel

Here's how to setup a Working HTML Contact Form on Websites hosted with Vercel Platform.

**Vercel Platform Guide:** [**https://web3forms.com/platforms/vercel-contact-form**](https://web3forms.com/platforms/vercel-contact-form)

### Step 01: Create an HTML Form

First of all, we need to create a `html` page with web3forms. Learn how to setup on our [installation](https://docs.web3forms.com/getting-started/installation) page.

### Step 02: Create a GIT Repository

Now, you should create a new GitHub repository and add your `html` files to your repo.

### Step 03: Create a New Project in Vercel

Now, click [New Project](https://vercel.com/new) button from your dashboard.

### Step 04: Import GIT Repository to Vercel

![](/files/-MZHb_gntclGi8M2V-v0)

Now, you can see your repos, click on **Import** button near the repo you want to import.

### Step 05: Deploy Vercel App

![](/files/-MZHb_gpiUq3ep9CLPDf)

Configure you name and settings. Click on **Deploy** button. You're good to go!

### Step 06: Congratulations! You're App is deployed

![](/files/-MZHb_gqdL2Qc3xo3RbP)

Congrats, You're app is now deployed on vercel. You can now visit it! It will work absolutely fine. Well done! 👏

### Test App

![](/files/-MZHb_grqys97iaWKG1G)

Now, here comes the final part! It is time to test. Head over to the app, and submit the form. Open your mail, you can see a new one. It will look like this 👇

![](/files/-MZHb_gsnIvh0zTh3QwW)


# Netlify

## Step 01: Create HTML Form

First of all we need to create a `html` page with web3forms. Learn how to setup on our [installation](https://docs.web3forms.com/getting-started/installation) page.

## Step 02: Create an account on Github

![](/files/-MZHb_gl9eEyU5WrAmRi)

First Step is to create a Github account if you don't already have one.

## Step 03: Create a GIT Repository

Now, you should create a new GitHub repository and add your `html` code to your repo.

## Step 04: Create an account on Netlify

![](/files/-MZMxof4cVxu9riQ_rqy)

Head over to <http://netlify.com/> and create an account on Netlify. If you already have one, sign in to your account. You will be redirected to your dashboard.

## Step 05: Create a New Project

![](/files/-MZMxof5doYIOsBkq-IZ)

Now, click [New Site From GIT](https://app.netlify.com/start) button from your dashboard.

## Step 06: Connect GIT Repository

![](/files/-MZMxof6DtGZpziDXNZA)

Now, just click on **Github** button to connect Netlify with your Github Account.

## Step 07: Choose Github Repository

![](/files/-MZMxof71jjaVsOwnAgC)

You will now be able to see your repos. Just click on the repository you want to deploy!

## Step 08: Deploy on Netlify

![](/files/-MZMxof84747v26yVtk7)

You can now add your details, Finally lets click on **Deploy Site** button and you're good to go!

## Step 09: Congratulations! You're App is deployed

![](/files/-MZMxof9FyMFJSNQOK59)

Congrats, You're app is now deployed on Netlify. If you wish to change your domain, just click on **Domain Settings** and change your domain. You can now visit your App! It will work absolutely fine. Well done! 👏

## Test App

![](/files/-MZHb_grqys97iaWKG1G)

Now, here comes the final part! It is time to test. Head over to the app, and submit the form. Open your mail, you can see a new one. It will look like this 👇

![](/files/-MZHb_gsnIvh0zTh3QwW)


# Digital Ocean

{% hint style="warning" %}
This documentation is work in progress. Feel free to [contribute on Github](https://github.com/surjithctly/web3forms-docs).
{% endhint %}


# AWS

{% hint style="warning" %}
This documentation is work in progress. Feel free to [contribute on Github](https://github.com/surjithctly/web3forms-docs).
{% endhint %}


# Github

## Step 01: Create HTML Form

First of all we need to create a `html` page with web3forms. Learn how to setup on our [installation](https://docs.web3forms.com/getting-started/installation) page.

## Step 02: Create an account on Github

![](/files/-MZHb_gl9eEyU5WrAmRi)

First Step is to create a Github account if you don't already have one.

## Step 03: Create a GIT Repository

Now, you should create a new GitHub repository and add your `html` code to your repo.

## Step 04: Add code to GIT repository

Follow the code to initialise and add your code files to your repo.

```bash
git init
git add index.html
git commit -m "first commit"
git branch -M main
git remote add origin your_origin_url
git push -u origin main
```

## Step 05: Go to Settings

![](/files/-MZSBQN5-aoo3RgwxpzM)

On your github repository, you can see a tab called **Settings**, just click on the tab.

## Step 06: Go to Pages Table

![](/files/-MZSBQN6bYoEsg4c9v4W)

On your settings page, you can see a tab called **Pages** on the left. Just click on tab.

## Step 07: Choose Branch

![](/files/-MZSBQN7SM7RgTRkarH9)

Here, you can should set your branch as `main` and click on **Save** button. You're good to go!

## Step 08: Congratulations! You're App is deployed

![](/files/-MZSBQN8_V4mxBHFmAQg)

Congrats, You're app is now deployed on github. Your hosting url will be *username.github.io/repo* You can now visit it! It will work absolutely fine. Well done! 👏

## Test App

![](/files/-MZHb_grqys97iaWKG1G)

Now, here comes the final part! It is time to test. Head over to the app, and submit the form. Open your mail, you can see a new one. It will look like this 👇

![](/files/-MZHb_gsnIvh0zTh3QwW)


# Cloudflare

{% hint style="warning" %}
This documentation is work in progress. Feel free to [contribute on Github](https://github.com/surjithctly/web3forms-docs).
{% endhint %}


# JAM Stack

{% hint style="warning" %}
This documentation is work in progress. Feel free to [contribute on Github](https://github.com/surjithctly/web3forms-docs).
{% endhint %}


# Landing Page Builders


# Unbounce

{% hint style="warning" %}
This documentation is work in progress. Feel free to [contribute on Github](https://github.com/surjithctly/web3forms-docs).
{% endhint %}


# Instapage

{% hint style="warning" %}
This documentation is work in progress. Feel free to [contribute on Github](https://github.com/surjithctly/web3forms-docs).
{% endhint %}


# Pagewiz

{% hint style="warning" %}
This documentation is work in progress. Feel free to [contribute on Github](https://github.com/surjithctly/web3forms-docs).
{% endhint %}


# Groovefunnels

{% hint style="warning" %}
This documentation is work in progress. Feel free to [contribute on Github](https://github.com/surjithctly/web3forms-docs).
{% endhint %}


# WordPress

For WordPress usage, you can use this community wp plugin:

{% embed url="<https://github.com/anjanesh/web3forms-wp-plugin>" %}

<figure><img src="/files/OkL55DipnXO2awZYXtYW" alt=""><figcaption></figcaption></figure>


# Elementor

{% hint style="warning" %}
This documentation is work in progress. Feel free to [contribute on Github](https://github.com/surjithctly/web3forms-docs).
{% endhint %}


# Oxygen Builder

{% hint style="warning" %}
This documentation is work in progress. Feel free to [contribute on Github](https://github.com/surjithctly/web3forms-docs).
{% endhint %}


