Why Test Addresses Fail AVS and ZIP+City+State Validation

Published June 26, 2026 · 9 min read

You generated a clean-looking US address for a QA fixture. The street looks plausible, the city is real, the ZIP code starts with the right digits, and the phone area code lines up. You paste it into a staging checkout, and the form rejects it: “The ZIP code you entered does not match the city and state.” Or worse, the payment gateway returns an AVS_MISMATCH response and the charge fails.

Both of these failures are doing their job. This article explains the two systems that produce them — USPS-driven ZIP·city·state validation and Address Verification System (AVS) checks — so you can design your test fixtures around their rules instead of fighting them.

The two validation layers, briefly

A US shipping form typically runs an address through two independent layers:

  1. USPS deliverability validation. Confirms that the city, state, and ZIP code refer to the same USPS-recognized post office area, and optionally that the street number and street name exist on a real USPS delivery route. This is the layer that fires the “ZIP doesn’t match city/state” error.
  2. AVS — Address Verification System. A check by the card network (Visa, Mastercard, Amex, Discover) that compares the numeric portion of the billing street address and the billing ZIP code against what the cardholder’s bank has on file. This is the layer that fires AVS_MISMATCH, AVS_ZIP_ONLY_MATCH, and friends in payment gateway responses.

Note that these are different validations against different data sources. A synthetic address can satisfy layer 1 and still fail layer 2, because the bank has never heard of the cardholder living there.

How USPS ZIP matching works

USPS maintains a database where every ZIP code is associated with one or more preferred city names and a state. A bare ZIP code like 19801 unambiguously belongs to Wilmington, DE. If you submit 19801 paired with Dover, DE, validation fails because Dover’s ZIP codes are 19901 and 19904 — a different post office.

Edge cases the USPS database handles that catch out home-grown matchers:

For test fixtures, the practical takeaway is: sample your city, state, and ZIP from the same state record. The US Tax-Free State Address Generator does exactly this — if it picks Delaware, it picks a Delaware city and one of that city’s real ZIPs. Layer 1 will always pass.

How AVS works

AVS lives at the payment network level. When a merchant authorizes a card transaction with a billing address, the issuer compares two specific tokens to its records:

The response is a single letter code returned with the authorization. Common values:

CodeMeaning
YStreet and ZIP both match.
AStreet matches, ZIP does not.
Z5-digit ZIP matches, street does not.
NNeither matches.
UIssuer did not respond / address unavailable.
GNon-US issuer, AVS not supported.

Merchant gateways such as Stripe, Adyen, Braintree, and Authorize.Net surface this code and let the merchant decide what to do with each value — auto-decline on N, soft-decline on A or Z, and so on.

Because AVS reads from the bank’s records of the actual cardholder, no synthetic address can ever pass real AVS. A randomly generated street and ZIP only match if a real cardholder happens to live there — which is exactly the situation AVS is designed to detect.

Designing test fixtures that work in each environment

Here is a practical playbook for using synthetic addresses without fighting validation:

1. Use a state-consistent generator for unit tests and UI demos

For form validation, layout testing, screenshot fixtures, and seed data, you want consistent-looking addresses but you do not need to pass any external API. A small generator like the one on this site provides addresses whose city, state, and ZIP always match.

2. Use the official test cards plus the AVS test ZIPs in payment-gateway sandboxes

Stripe, Braintree, and Adyen all publish test cards plus magic addresses that force a chosen AVS response in their sandbox environments. For example, in Stripe’s test mode, a billing ZIP of 42424 deterministically returns N (no match), and any other 5-digit ZIP returns Y. Use those documented magic values instead of generic synthetic addresses for AVS-specific scenarios.

// Stripe test mode — deterministic AVS outcomes
const billing = {
  line1:      '1 Test Lane',
  postal_code: '42424',  // forces AVS code N
};
const intent = await stripe.paymentIntents.create({ ... });

3. Mock the address-verification call in unit tests

If your code talks to USPS Address Information API, Smarty (formerly SmartyStreets), Lob, or Google Address Validation, stub those clients in unit tests. The synthetic addresses do not need to pass — they only need to flow through your code path. Verify that your code handles each documented response shape, including the partial-match and not-found cases.

4. Use real bank addresses for end-to-end production tests

If you must run an end-to-end test in production with a real card, use the cardholder’s real billing address. There is no shortcut around the bank’s records. Production tests with synthetic addresses are a known footgun for getting your merchant account flagged.

When a checkout still complains about “ZIP doesn’t match”

If your address came from the tax-free state generator and the checkout still complains, one of the following is usually true:

Summary

Two validation layers, two different data sources, two different failure modes. USPS ZIP-city-state checks are about internal consistency — you can satisfy them with a state-matched synthetic address. AVS is about matching the bank’s real records on a real cardholder — no synthetic address can ever pass it. Design your fixtures and tests accordingly, and a lot of mysterious test-failure tickets will stop appearing.

Sources & further reading

Specific AVS response codes, USPS database fields, and gateway documentation cited above come from the following authoritative sources. AVS code semantics are gateway-specific, so always check the gateway you actually use:

Related reading