> ## 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.

# Address Verify Implementation Guide

> Add address verification and cleansing 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>;
};

**Validate and correct addresses in real-time to reduce delivery failures and ensure data quality.**

## Who Should Use This Guide

**For:** Business owners and developers integrating address verification 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)), batch processing of large address lists, or CASS/SERP certification workflows.

## What You'll Build

An address verification form that:

* Validates addresses against postal datasets
* Corrects errors and typos automatically
* Standardizes address formatting
* Shows match quality scores (AVC codes)
* Works with addresses in 250+ countries

## Quick Start

To set up Address Verify, 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 verification to your current checkout or registration forms

    Step-by-step guide to add verification 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 an address with typos like "123 Mane Street, Bostan MA"
3. Click verify
4. See the corrected address: "123 Main Street, Boston MA"

<Note>
  Address Verify validates against postal datasets for 250+ countries. Match quality is indicated by AVC codes (V44 = perfect match, V33 = good match, etc.).
</Note>

***

## Sample Project: Checkout Form Integration

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

<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: Unverified Address Entry

A checkout form without verification:

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

**This form works, but doesn't verify or correct addresses.** Let's add verification.

***

## How Address Verify Works

Address Verify validates addresses in a single API call:

### The Verification Process

**Input:** You send address fields (street, city, postal code, country)

**Processing:** The API:

1. Parses the input fields
2. Matches against postal reference data
3. Corrects typos and standardizes formatting
4. Returns match quality scores

**Output:** You receive:

* Corrected address in standardized format
* AVC code indicating match quality
* Original input for comparison

### Understanding AVC Codes

The AVC (Address Verification Code) tells you match quality:

**Format:** `V44-I44-P7-100`

**Key components:**

* **First character:** Verification status
  * `V` = Verified (use this address)
  * `P` = Partially verified (check details)
  * `U` = Unverified (rejected)

* **Match level (2nd-3rd characters):**
  * `44` = Premise level (street + number) - Best
  * `33` = Street level
  * `22` = Locality level (city)
  * Lower = Less precise

* **Final number:** Match percentage
  * `100` = Perfect match, no changes
  * `95-99` = Minor corrections
  * `80-94` = Significant corrections
  * Below 80 = Major issues

**Decision guide:**

* `V44` with 95+ matchscore = Accept automatically
* `V33` or `V44` with 80-94 = Review changes, usually accept
* `V22` or below = Reject or ask user to verify
* `P` or `U` = Reject

***

## Standalone HTML Example

A minimal address verification form for quick testing:

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

**Perfect for:**

* Quick API testing
* Learning how address verification works
* Simple integrations without checkout flows

**To use:**

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

<Note>
  This example shows original vs corrected addresses side-by-side with the AVC code for learning purposes.
</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/address-verify).

## Integration Example

Here's the checkout form with full address verification integrated:

<GistEmbed url="https://raw.githubusercontent.com/loqate/javascript-docs-sample/refs/heads/main/address-verify/finish/complete-checkout-with-address-verify.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 verification on form submission
* Shows before/after comparison
* Automatic field updates with corrected values
* Accept/reject workflow based on AVC
* Clean, production-ready code structure

<Note>
  This example accepts addresses with V44/V33 match levels and 80+ matchscore. Adjust thresholds based on your requirements.
</Note>

***

## Integration Tips

### Adding to Your Existing Forms

To add address verification to your current forms:

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

2. **Add verification UI styles** from the integration example to your page's `<style>` section
   * Shows before/after comparison
   * Displays AVC codes and match quality

3. **Add the comparison display element** to show verification results
   * `<div id="verificationResult"></div>`

4. **Add the event listeners** to trigger verification and handle acceptance
   * Submit event to verify before processing
   * Accept button to use corrected address

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

### Choosing Input Format

Address Verify accepts two input formats:

**Structured (Recommended):**

```javascript theme={null}
const addressData = {
    Address1: document.getElementById('street').value,
    Locality: document.getElementById('city').value,
    AdministrativeArea: document.getElementById('state').value,
    PostalCode: document.getElementById('zip').value,
    Country: document.getElementById('country').value
};
```

**Unstructured (Simple):**

```javascript theme={null}
const addressData = {
    Address: "123 Main St, Boston MA 02129",
    Country: "USA"
};
```

**Tip:** Structured input provides better match rates. Always separate the `Country` field even in unstructured requests.

### Deciding Match Acceptance

Set thresholds based on your use case:

**E-commerce / Standard shipping:**

```javascript theme={null}
function isAcceptable(avc, matchscore) {
    // Accept V44 or V33 with 80+ matchscore
    return (avc.startsWith('V44') || avc.startsWith('V33')) && 
           matchscore >= 80;
}
```

**High-precision (direct mail, medical):**

```javascript theme={null}
function isAcceptable(avc, matchscore) {
    // Only accept V44 with 95+ matchscore
    return avc.startsWith('V44') && matchscore >= 95;
}
```

**Lenient (email signup, low-priority):**

```javascript theme={null}
function isAcceptable(avc, matchscore) {
    // Accept any verified address
    return avc.startsWith('V');
}
```

### Handling Verification Results

**Scenario 1: Perfect Match (V44-I44-P7-100)**

* No changes made
* Accept automatically
* No user intervention needed

**Scenario 2: Minor Corrections (V44-I44-P7-95)**

* Small typos fixed
* Show user what changed
* Usually auto-accept with notification

**Scenario 3: Major Corrections (V33-I33-P6-82)**

* Significant changes
* Require user confirmation
* Show before/after clearly

**Scenario 4: Failed Verification (U11)**

* Address not found
* Ask user to re-enter
* Consider offering manual override for edge cases

### Updating Form Fields

**Option A: Automatic update (aggressive):**

```javascript theme={null}
if (isAcceptable(result.AVC, result.Matchscore)) {
    document.getElementById('street').value = result.Address1;
    document.getElementById('city').value = result.Locality;
    document.getElementById('state').value = result.AdministrativeArea;
    document.getElementById('zip').value = result.PostalCode;
}
```

**Option B: User confirmation (recommended):**

```javascript theme={null}
showComparison(originalAddress, correctedAddress, result.AVC);
document.getElementById('acceptBtn').addEventListener('click', () => {
    updateFormFields(correctedAddress);
    submitForm();
});
```

### Showing Verification Status

Provide clear feedback to users:

```javascript theme={null}
function displayVerificationStatus(avc, matchscore) {
    const statusDiv = document.getElementById('verificationStatus');
    
    if (avc.startsWith('V44') && matchscore >= 95) {
        statusDiv.innerHTML = `
            <div class="status-success">
                Address verified successfully
                <small>Match quality: ${matchscore}%</small>
            </div>
        `;
    } else if (avc.startsWith('V') && matchscore >= 80) {
        statusDiv.innerHTML = `
            <div class="status-warning">
                Address verified with corrections
                <small>Please review changes below</small>
            </div>
        `;
    } else {
        statusDiv.innerHTML = `
            <div class="status-error">
                Could not verify address
                <small>Please check and try again</small>
            </div>
        `;
    }
}
```

### Styling Customization

Customize the verification UI to match your design:

```css theme={null}
.verification-result {
    border: 2px solid #4CAF50;
    padding: 20px;
    border-radius: 8px;
    margin: 20px 0;
}

.address-comparison {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}

.original-address {
    opacity: 0.6;
    text-decoration: line-through;
}

.corrected-address {
    font-weight: 600;
    color: #4CAF50;
}

.avc-badge {
    display: inline-block;
    padding: 4px 12px;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 600;
}

.avc-verified {
    background: #d4edda;
    color: #155724;
}

.avc-partial {
    background: #fff3cd;
    color: #856404;
}

.avc-failed {
    background: #f8d7da;
    color: #721c24;
}
```

***

## Troubleshooting

### Invalid API Key

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

### Address Not Verifying

**Check:**

* Country field is provided (required)
* Address format matches country standards
* You have available credits in your account
* API key hasn't been restricted by domain, IP, or rate limits
* Postal code matches locality/administrative area

### All Addresses Return Low Matchscore

**Common causes:**

* Using unstructured input (single Address field) - use structured input instead
* Missing country field
* Incorrect country code
* Address format doesn't match country conventions

### Form Not Appearing

Ensure you copied the standalone 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

* Addresses verified 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/address-verify/international-batch-cleanse)
* [AVC Code Documentation](/report-codes/address-verification-code/)
* [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/)
