Why Test Addresses Fail AVS and ZIP+City+State Validation
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:
- 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.
-
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:
-
Acceptable alternate city names.
19711is officially Newark, DE, but USPS accepts University of Delaware as an alternate name for mail addressed there. Most third-party validators reject the alternate even though USPS would deliver it. - ZIP boundaries that cross neighborhoods. A single ZIP code can span more than one city name and even more than one county. Checkout forms commonly accept any of the recognized names; CRMs sometimes overwrite the user’s entry with the “preferred” one.
- ZIP+4 specificity. The 4-digit suffix narrows a ZIP down to a block face or building. Most checkout forms accept and ignore it; some shipping APIs require it for discounted commercial rates.
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 numeric portion of the street address.
123 Main Stand123 Maple Aveboth reduce to the same AVS token,123. Some issuers ignore everything past the digits. - The 5-digit ZIP code.
The response is a single letter code returned with the authorization. Common values:
| Code | Meaning |
|---|---|
Y | Street and ZIP both match. |
A | Street matches, ZIP does not. |
Z | 5-digit ZIP matches, street does not. |
N | Neither matches. |
U | Issuer did not respond / address unavailable. |
G | Non-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:
- The checkout is calling a commercial address-validation API (Smarty, Lob, USPS Web Tools) that goes further than ZIP/city/state and requires the specific street number to exist on USPS’ delivery list for that ZIP. Synthetic street numbers won’t pass that.
- The checkout is doing AVS at the “place order” step and decoding the AVS response as a form error. The fix is to either disable AVS in your sandbox or document the expected failure for the testing team.
- The form’s ZIP database is out of date and does not recognize a recently added or renamed ZIP code. Updating the dataset is the right fix, not changing the test address.
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:
- Stripe — Decline codes & AVS results — gateway-side reference for card-issuer AVS responses.
- Braintree — AVS and CVV rules — programmable rules around AVS responses.
- Authorize.Net — Response code reference — the canonical AVS letter-code table (Y, A, Z, N, U, R, S, E, G).
- USPS Web Tools APIs — ZIP+4, address standardization, and city/state lookup.
- USPS PostalPro — deliverability and CASS certification documentation.
- Smarty — US Street Address API — commercial CASS-certified verification provider used as a reference for the validation layers described above.