> ## Documentation Index
> Fetch the complete documentation index at: https://docs.loqate.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Email Validation Implementation Guide

> Add email validation to your website with copy-paste code examples

export const GistEmbed = ({url, height = "500px"}) => {
  const [htmlContent, setHtmlContent] = useState('');
  const [copied, setCopied] = useState(false);
  const [rawCode, setRawCode] = useState('');
  const [isDark, setIsDark] = useState(true);
  useEffect(() => {
    const checkTheme = () => {
      const htmlElement = document.documentElement;
      const computedStyle = window.getComputedStyle(htmlElement);
      const colorScheme = computedStyle.getPropertyValue('color-scheme');
      const isDarkMode = htmlElement.classList.contains('dark') || htmlElement.getAttribute('data-theme') === 'dark' || colorScheme.includes('dark') || window.matchMedia('(prefers-color-scheme: dark)').matches;
      setIsDark(isDarkMode);
    };
    checkTheme();
    const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
    mediaQuery.addEventListener('change', checkTheme);
    const observer = new MutationObserver(checkTheme);
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['class', 'data-theme', 'style']
    });
    return () => {
      mediaQuery.removeEventListener('change', checkTheme);
      observer.disconnect();
    };
  }, []);
  useEffect(() => {
    fetch(url).then(r => r.text()).then(code => {
      setRawCode(code);
      const bgColor = isDark ? '#0a0c0e' : '#ffffff';
      const textColor = isDark ? '#c9d1d9' : '#24292e';
      const scrollTrack = isDark ? '#161b22' : '#f6f8fa';
      const scrollThumb = isDark ? '#30363d' : '#d1d5da';
      const scrollThumbHover = isDark ? '#484f58' : '#959da5';
      const iframe = `
          <!DOCTYPE html>
          <html>
            <head>
              <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
              <style>
                body {
                  margin: 0;
                  padding: 0;
                  background: ${bgColor};
                  overflow: auto;
                }
                pre {
                  margin: 0;
                  background: transparent !important;
                }
                code {
                  font-family: 'JetBrains Mono', JetBrains Mono, monospace !important;
                  font-size: 14px !important;
                  line-height: 1.7 !important;
                  background: transparent !important;
                  padding: 0 !important;
                }
                .hljs {
                  background: transparent !important;
                  color: ${textColor} !important;
                }
                ::-webkit-scrollbar {
                  width: 12px;
                  height: 12px;
                }
                ::-webkit-scrollbar-track {
                  background: ${scrollTrack};
                  border-radius: 10px;
                }
                ::-webkit-scrollbar-thumb {
                  background: ${scrollThumb};
                  border-radius: 10px;
                  border: 2px solid ${scrollTrack};
                }
                ::-webkit-scrollbar-thumb:hover {
                  background: ${scrollThumbHover};
                }
                * {
                  scrollbar-width: thin;
                  scrollbar-color: ${scrollThumb} ${scrollTrack};
                }
              </style>
            </head>
            <body>
              <pre><code class="language-html">${escapeHtml(code)}</code></pre>
              <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
              <script>hljs.highlightAll();</script>
            </body>
          </html>
        `;
      setHtmlContent(iframe);
    }).catch(e => {
      setRawCode('Error loading code');
      setHtmlContent('<pre>Error loading code</pre>');
    });
  }, [url, isDark]);
  const escapeHtml = text => {
    return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#039;');
  };
  const copyToClipboard = () => {
    navigator.clipboard.writeText(rawCode);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };
  const containerBg = isDark ? '#0a0c0e' : '#ffffff';
  const containerBorder = isDark ? '#30363d' : '#e1e4e8';
  return <div style={{
    position: 'relative',
    marginBottom: '1.5rem',
    marginTop: '1.5rem',
    background: containerBg,
    borderRadius: '12px',
    border: `1px solid ${containerBorder}`,
    padding: '16px 20px'
  }}>
      <button onClick={copyToClipboard} style={{
    position: 'absolute',
    top: '12px',
    right: '32px',
    padding: '8px',
    background: 'rgba(255, 255, 255, 0.08)',
    backdropFilter: 'blur(4px)',
    border: '1px solid rgba(255, 255, 255, 0.1)',
    borderRadius: '6px',
    cursor: 'pointer',
    fontSize: '13px',
    fontWeight: '500',
    color: 'rgba(255, 255, 255, 0.8)',
    zIndex: 10,
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    transition: 'all 0.15s',
    fontFamily: 'system-ui, -apple-system, sans-serif',
    width: '32px',
    height: '32px'
  }} onMouseEnter={e => {
    e.currentTarget.style.background = 'rgba(255, 255, 255, 0.12)';
  }} onMouseLeave={e => {
    e.currentTarget.style.background = 'rgba(255, 255, 255, 0.08)';
  }}>
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
          {copied ? <polyline points="20 6 9 17 4 12" /> : <>
              <rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
              <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
            </>}
        </svg>
      </button>
      <iframe srcDoc={htmlContent} style={{
    width: '100%',
    height: height,
    border: 'none',
    overflow: 'auto',
    background: 'transparent'
  }} title="Code Example" />
    </div>;
};

Reduce bounced emails and improve data quality by validating email addresses at checkout, in contact forms, or during registration.

## Who Should Use This Guide

**For:** Business owners and developers integrating email validation without complex setup.

**You'll need:** A Loqate API key and basic HTML knowledge.

**Not covered:** Tag-based integrations ([see Tag Setup](/our-services/tag-setup-guide)) or pre-built platform integrations ([see Integrations](/integrations/all-integrations)).

***

## What You'll Build

An email validation form that:

* Validates email addresses in real-time
* Displays success or error states
* Prevents form submission with invalid emails
* Detects disposable and high-risk addresses

***

## Quick Start

### Get Your API Key

To set up Email Validation, you'll need an API key. Find out how to get yours [here](/loqate-basics/create-an-api-key/).

### Choose Your Approach

<Tabs>
  <Tab title="Standalone Form">
    **Use case:** Testing the API or adding to a static page

    A self-contained HTML file you can copy and use immediately.

    Jump to [standalone HTML example](#standalone-html-example)
  </Tab>

  <Tab title="Integrate with Existing Form">
    **Use case:** Add validation to your current checkout or contact forms

    Step-by-step guide to add validation code to forms you already have.

    Jump to [integration example](#integration-example)
  </Tab>
</Tabs>

**Using Shopify or WordPress?** Check [pre-built integrations](/integrations/all-integrations).

### Add Your Key

Replace `YOUR_API_KEY` in the code with your actual Loqate API key.

### Test

1. Open your page
2. Enter `test@example.com`
3. Validation result appears

<Note>The API validates email format, domain existence, and account validity where possible.</Note>

***

## Sample Project: Checkout Integration

This walkthrough shows how to add email validation to a checkout form. Follow along to see a basic form transform into a validation-enabled checkout.

<Note>This is a detailed walkthrough. If you just want working code, skip to [Integration Example](#integration-example) or [Standalone HTML Example](#standalone-html-example).</Note>

### Before: Basic Checkout

A checkout form without validation:

<GistEmbed url="https://raw.githubusercontent.com/loqate/javascript-docs-sample/refs/heads/main/email-validation/start/basic-checkout-form.html" height="450px" />

**This form works, but doesn't validate email addresses.** Let's add validation.

***

## How Email Validation Works

The integration includes four key components:

### 1. Validation Function

A JavaScript function that sends email addresses to the Loqate API and returns validation results. The function handles API requests, timeout configuration, and response parsing.

### 2. Visual Feedback

CSS classes and a message element that show users three states:

* **Checking:** Yellow background while validating
* **Valid:** Green background for valid emails
* **Invalid:** Red background for invalid or high-risk emails

### 3. Real-Time Validation

An event listener on the email input field that triggers validation when users finish typing (on blur). This provides immediate feedback without requiring form submission.

### 4. Form Submission Control

Logic that prevents form submission if the email address is invalid, ensuring only validated data is processed.

***

## Standalone HTML Example

A minimal email validation form for quick testing:

<GistEmbed url="https://raw.githubusercontent.com/loqate/javascript-docs-sample/refs/heads/main/email-validation/finish/simple-email-validation.html" height="450px" />

**Perfect for:**

* Quick API testing
* Learning how email validation works
* Simple integrations without checkout flows

**To use:**

1. Copy the code
2. Replace `YOUR_API_KEY`
3. Save and test with different email addresses

<Note>Test with various email formats including disposable addresses to see different validation responses.</Note>

***

## Code on GitHub

If you'd like to browse the code snippets in this implementation guide or clone them, visit the repository on [GitHub](https://github.com/loqate/javascript-docs-sample/tree/main/email-validation).

## Integration Example

Here's the checkout form with all validation components integrated:

<GistEmbed url="https://raw.githubusercontent.com/loqate/javascript-docs-sample/refs/heads/main/email-validation/finish/complete-checkout-with-email-validation.html" height="700px" />

**To use this code:**

1. Copy the code
2. Replace `YOUR_API_KEY` with your actual Loqate API key
3. Save as an HTML file
4. Open in a browser to test
5. Customize styling to match your brand

**Key features in this example:**

* Real-time validation on field exit
* Visual feedback for all validation states
* Form submission prevention for invalid emails
* Success message display for valid submissions
* Clean, production-ready code structure

<Note>This example includes a 15-second timeout for validation. Adjust the timeout parameter based on your needs.</Note>

***

## Integration Tips

### Adding to Your Existing Forms

To add email validation to your current forms:

1. **Add the validation function** from the integration example to your page's `<script>` section
   * Handles API requests and response parsing

2. **Add validation styles** from the integration example to your page's `<style>` section
   * Provides visual feedback (valid/invalid/checking states)

3. **Add the validation message element** next to your email input field
   * `<span id="emailValidation"></span>`

4. **Add the event listeners** to trigger validation and control form submission
   * Blur event for real-time validation
   * Submit event to prevent invalid submissions

Reference the [integration example](#integration-example) above for all the code you need.

***

### Timeout Customization

The `Timeout` parameter controls how long the API attempts validation (in milliseconds):

* Default: `15000` (15 seconds)
* Minimum: `1` millisecond
* Maximum: `15000` milliseconds

**Recommended:** Use at least 5 seconds (`5000`) to minimize timeout responses.

```javascript theme={null}
body: new URLSearchParams({
    Key: apiKey,
    Email: email,
    Timeout: 5000  // 5 seconds
})
```

***

### Validation Timing Options

**Current examples use:** Validation on field exit (blur event) - validates when users click or tab away from the email field.

**Alternative approaches:**

**On button click:**
Add a separate "Validate" button that triggers validation manually.

**While typing (debounced):**
Validate as users type, with a short delay to avoid excessive API calls. Add a 1-second timeout that resets with each keystroke.

**On form submission only:**
Validate only when the user submits the form, showing errors before processing.

***

### Handling Response Codes

The API returns different response codes indicating validation status:

| Code             | Meaning                             | Action                    |
| ---------------- | ----------------------------------- | ------------------------- |
| `Valid`          | Email fully validated               | Accept the email          |
| `Valid_CatchAll` | Domain validated, account uncertain | Accept with caution       |
| `Invalid`        | Email is invalid                    | Reject the email          |
| `Timeout`        | Validation incomplete               | Retry with higher timeout |

**Example handling:**

```javascript theme={null}
const result = await validateEmail(email);

if (result.ResponseCode === "Valid") {
    // Accept email
    showSuccess("Email validated successfully");
} else if (result.ResponseCode === "Valid_CatchAll") {
    // Accept but flag for review
    showWarning("Email validated (catch-all domain)");
} else if (result.ResponseCode === "Timeout") {
    // Retry or accept with warning
    showWarning("Validation timeout - please try again");
} else {
    // Reject email
    showError("Invalid email address");
}
```

***

### Risk Assessment

Use the `Risk` field to identify potentially problematic emails:

* `Low` - Safe to send
* `Medium` - Use caution
* `High` - Likely to bounce
* `Unknown` - Unable to determine

**Check disposable emails:**

```javascript theme={null}
if (result.IsDisposableOrTemporary) {
    showWarning("Disposable email detected");
}
```

***

### Styling Customization

The examples use minimal styling. Customize the CSS classes (`.email-valid`, `.email-invalid`, `.email-checking`) to match your brand:

* Change colors to match your design system
* Adjust padding and border-radius
* Add icons or animations
* Modify font sizes and weights

***

## Troubleshooting

### Invalid API Key

Verify you've replaced `YOUR_API_KEY` with your actual key from your Loqate account.

***

### Emails Not Validating

**Check:**

* You have available credits in your account
* API key hasn't been restricted by domain, IP, or rate limits (check account settings)
* Timeout value is sufficient (recommended: at least 5 seconds)
* Network connection is stable

***

### Timeout Responses

If you're getting frequent timeout responses:

1. Increase the `Timeout` parameter (try 10-15 seconds)
2. Check your network connection
3. Verify the email domain is accessible

***

### Form Not Appearing

Ensure you copied the complete HTML file including all `<style>` and `<script>` sections. The examples are self-contained and include all required code.

***

### CORS Errors

The examples must be hosted on a web server, not opened as local `file://` URLs. Upload to your website or use a development server like Python's `http.server` or Node's `http-server`.

***

## Data Privacy

* Email addresses validated through Loqate's API
* Stored in infrastructure logs for 30 days for operational purposes
* Results returned immediately
* See [Privacy Policy](https://www.loqate.com/en-gb/legal/privacy-policy/) for complete details

***

## Support

* [API Reference](/api-reference/email-validation/individual)
* [Contact](https://www.loqate.com/en-gb/contact/customer-support/)

***

## Related

* [API Security](/loqate-basics/api-security)
* [Pricing](https://www.loqate.com/en-gb/pricing/)
