UK address autocomplete API: UX patterns and implementation guide

Address autocomplete is one of the highest-ROI UX improvements you can make to a UK checkout or registration form. Replacing a free-text address field with a postcode-driven typeahead reduces form abandonment, eliminates entry errors, and improves delivery success rates.

But while the concept is simple, many implementations fail in subtle ways — missing debounce, poor accessibility, or incorrect data storage. This guide walks through the correct UX patterns and working implementations using a UK address autocomplete API.


The two-step UK address lookup pattern

Most UK address autocomplete implementations follow a two-step flow — and for good reason.

Step 1 — Postcode lookup

User enters postcode → API returns all matching addresses.

Step 2 — Address selection

User selects address → form fields auto-fill.

Why this pattern works

PatternBest forCostCompleteness
Postcode → SelectCheckout, CRMLow (1–2 calls)Full structured data
Full typeaheadSearch barsHigh (per keystroke)Partial until selected
Manual entryEdge casesZeroUnreliable

👉 For UK use cases, postcode-first is faster, cheaper, and more reliable.

Implementation — vanilla JavaScript

Works in any HTML form.

const API_KEY = "your_apitier_key";

async function lookupPostcode(postcode) {
  const clean = postcode.replace(/\s/g, "").toUpperCase();
  const res = await fetch(
    `https://postcode.apitier.com/v1/postcodes/${clean}?x-api-key=${API_KEY}`
  );
  if (!res.ok) return [];
  const data = await res.json();
  return data.addresses || [];
}

async function initAddressAutocomplete({ postcodeInput, dropdown, fields }) {
  let debounceTimer;

  postcodeInput.addEventListener("input", () => {
    clearTimeout(debounceTimer);
    const val = postcodeInput.value.trim();

    if (val.length < 5) {
      dropdown.innerHTML = "";
      return;
    }

    debounceTimer = setTimeout(async () => {
      const addresses = await lookupPostcode(val);
      renderDropdown(addresses, dropdown, fields);
    }, 300);
  });
}

function renderDropdown(addresses, dropdown, fields) {
  dropdown.innerHTML = "";

  if (!addresses.length) return;

  addresses.forEach(addr => {
    const li = document.createElement("li");
    li.textContent = addr.formatted_address;
    li.setAttribute("role", "option");

    li.addEventListener("click", () => {
      fields.line1.value = addr.line_1 || "";
      fields.line2.value = addr.line_2 || "";
      fields.town.value = addr.town_or_city || "";
      fields.county.value = addr.county || "";
      dropdown.innerHTML = "";
    });

    dropdown.appendChild(li);
  });

}

Implementation — React hook

import { useState, useCallback, useRef } from "react";

const API_KEY = process.env.REACT_APP_APITIER_KEY;

export function useAddressLookup() {
  const [addresses, setAddresses] = useState([]);
  const [loading, setLoading] = useState(false);
  const debounce = useRef(null);

  const lookup = useCallback((postcode) => {
    clearTimeout(debounce.current);

    if (postcode.replace(/\s/g,"").length < 5) {
      setAddresses([]);
      return;
    }

    debounce.current = setTimeout(async () => {
      setLoading(true);

      try {
        const clean = postcode.replace(/\s/g,"").toUpperCase();
        const res = await fetch(
          `https://postcode.apitier.com/v1/postcodes/${clean}?x-api-key=${API_KEY}`
        );
        const data = await res.json();
        setAddresses(data.addresses || []);
      } finally {
        setLoading(false);
      }
    }, 300);
  }, []);

  return { addresses, loading, lookup };

}

Accessibility requirements (WCAG 2.1 AA)

If your dropdown is not accessible, it can fail compliance — especially for UK public sector or fintech apps.

Required attributes:

  • role="combobox" (input)
  • role="listbox" (dropdown)
  • role="option" (items)
  • aria-expanded
  • aria-activedescendant

Keyboard support:

  • Arrow keys → navigate
  • Enter → select
  • Escape → close

👉 Also announce results:

“5 addresses found. Use arrow keys to select.”

Four UX mistakes most developers make

1. No debounce

Calling API on every keystroke = wasted requests
Fix: 300ms debounce

2. No manual fallback

Some postcodes fail
Fix: show “Enter address manually”

3. Poor handling of multiple addresses

Some postcodes return 50+ results
Fix:

  • Limit visible items (6–8)
  • Add scroll container

4. Storing formatted address only

Bad for filtering & analytics
Fix: store structured fields:

  • line_1
  • town
  • postcode
  • UPRN

Build a complete UK data validation stack

Frequently asked questions

How many addresses does a UK postcode return?

1 to ~100 (average ~15). Urban areas return more.

Should I cache results?

Yes — cache for 24 hours to reduce API calls by 60–80%.

Does it support Northern Ireland?

Yes — BT postcodes included with townland data.

Why this matters for your product

A properly implemented UK address autocomplete:

  • Reduces checkout friction
  • Improves delivery accuracy
  • Saves support cost
  • Improves CRM data quality

And importantly — it takes less than 1 hour to implement correctly.

Start building with APITier

Free tier available — no credit card required

Final thoughts

Most address autocomplete implementations fail not because of the API — but because of poor UX decisions.

If you follow:

  • Two-step lookup
  • Debouncing
  • Accessibility
  • Structured storage

You’ll have a production-ready, scalable solution.