Cette page est disponible en anglais uniquement. La navigation reste dans votre langue.

Testing & QA · 6 min read

Address Parser in 2026: Tokenization, Ambiguity, Fallbacks

How to build an address parser that admits uncertainty: a staged pipeline, country-aware field order, ambiguity handling, confidence scores, and golden cases.

By Charlie Simmon ·

On this page
  1. What parsing can and cannot recover
  2. A four-stage pipeline
  3. Country-aware field order
  4. The ambiguous cases worth handling
  5. Confidence scoring and thresholds
  6. Error states you should return
  7. Building a golden corpus and mutating it
  8. When not to parse at all
  9. Questions

An address parser converts one string into structured fields: line 1, line 2, city, region, postal code, and country. That sounds like splitting on commas until you meet a German address where the postal code precedes the city, a Japanese address written largest-unit-first, or a US line where "St" is part of a city name rather than a street suffix.

This guide describes a parser that is honest about ambiguity. The design rule is simple: parse only what the grammar supports, score what you parsed, and return the original string untouched when confidence is low. A parser that silently returns wrong fields is worse than one that refuses, because the wrong fields get stored and the original is thrown away.

What parsing can and cannot recover

Parsing recovers structure that was present in the text: the postal code, the region code, the city, and the street line, in that order of reliability. It cannot recover information that was never written down. A string with no unit designator does not contain a unit number, and no amount of inference should invent one.

It also cannot confirm that the fields are true. Parsing "123 Main St, Springfield, IL 62701" produces coherent fields, and the address may still be fictional or the city may not match the ZIP. Parsing is a text operation. Verification is a data operation, and the two should never share a function name or a success message.

  • Recoverable: postal code, region, city, street line, unit designator
  • Not recoverable: a missing unit, a missing country, a wrong city
  • Never infer a country from a phone prefix or a language
  • Never fill an empty field with a plausible default

A four-stage pipeline

Stage one is normalization: trim, collapse internal whitespace, replace non-breaking spaces, normalize punctuation variants, and decide whether to uppercase. Keep the original untouched for the fallback. Stage two is segmentation: split on commas when they exist, otherwise split on the country grammar. Stage three is classification: label each segment as postal, region, city, street, or unit using the country rule set. Stage four is assignment: map labels to fields, resolve conflicts, and score the result.

Keeping the stages separate makes the failure modes separable. A segmentation bug looks different from a classification bug, and each stage can be unit tested with its own corpus. It also lets you stop early: if the country is unknown, skip classification entirely and return the segments with per-field confidence marked as unknown.

  • Normalize without destroying the original
  • Segment by comma first, grammar second
  • Classify with a country-specific rule set
  • Assign, then score, then decide whether to accept

Country-aware field order

Field order is the single biggest source of wrong parses, because the same tokens move around. The United States, Canada, the United Kingdom, and Australia put the postal code after the city. Germany, France, the Netherlands, and Belgium put it before the city. Japan puts it first, before the prefecture. Brazil places the postal code after the state with a separator.

That is why the parser must know the country before it classifies anything. Inferring the country from the string itself is circular: the postal pattern can suggest one, but many patterns overlap. Ask for the country from the form, the locale, or an explicit selector, and mark the parse as low confidence when it is missing rather than guessing from a two-letter token that might be a state or a country.

CountryOrderExample
United StatesStreet, city, ST ZIP1420 SW Alder St, Portland, OR 97205
CanadaStreet, city, ST A1A 1A188 Queen St W, Toronto, ON M5H 2M5
GermanyStreet, ZIP cityUnter den Linden 77, 10117 Berlin
FranceNumber street, ZIP city12 Rue de Rivoli, 75004 Paris
NetherlandsStreet number, ZIP cityDamrak 1, 1012 LG Amsterdam
JapanZIP, prefecture, city, street100-0001 Tokyo, Chiyoda, Chiyoda 1-1
BrazilStreet, city - ST, ZIPAv. Paulista 1000, Sao Paulo - SP, 01310-100

The ambiguous cases worth handling

Secondary unit designators are the most common ambiguity. "Apt", "Ste", "Unit", "Fl", and "Rm" are reliable when followed by an identifier, but "Unit 5" can also be a street name, and "Building 3" can be the primary address of a campus. A parser should extract a unit only when the designator is followed by a number or a short alphanumeric token and appears after the street number.

Street suffixes are the second trap. A token like "Way", "Court", or "Park" can be a suffix, a street name, or a city. Directionals have the same problem: "N" can be a predirectional, a street name abbreviation, or a region. Use position relative to the house number and the comma structure, and when two readings are both plausible, keep the original segment and lower the confidence instead of choosing.

InputPlausible readingsSafe handling
12 Court StStreet suffix or part of nameKeep full street line
Unit 5, 100 Main StUnit before streetAssign unit, keep street
100 N Park AveDirectional plus suffixKeep the street tokens in order
Springfield Rd, SpringfieldSuffix in city namePrefer the comma boundary
Tokyo, Chiyoda 1-1City and blockUse the country grammar
Apt 4B 12 MainUnit without a commaExtract then re-score

Confidence scoring and thresholds

Score each field, then the record. A field is high confidence when it matched an anchored country pattern and its position agreed with the expected order. It is medium when the pattern matched but the position was inferred, and low when it was assigned by elimination. A record is only high confidence when every required field is high and there are no unplaced segments.

Set a threshold and enforce it. Above the threshold, accept and store. Below it, keep the original string and flag the record for review rather than writing a guess into the structured columns. Expose the score and the reasons in the API response, because the reviewer needs to know which field failed, not just that something did.

FieldHigh confidence signalLow confidence signal
PostalAnchored match, correct positionPattern matched but moved
RegionKnown code for the countryTwo-letter token with no match
CityLeft of the postal or right of the streetAssigned by elimination
StreetContains a house number and a nameBare name with no number
UnitDesignator plus identifier after streetDesignator inside the street name

Error states you should return

A parse result should have explicit outcomes, not a boolean. Missing country means the grammar cannot run. Missing postal code matters in countries that have one and is normal in Hong Kong and the UAE. An unplaceable segment means the comma structure and the grammar disagree, and the record needs human eyes.

Give each outcome a stable code so callers can branch without parsing prose. Return the normalized input, the original input, the field values with confidence, and the list of unplaced segments. That payload lets a UI highlight the exact token that failed instead of showing a generic error at the top of the form.

  • MISSING_COUNTRY: no grammar available, do not guess
  • MISSING_POSTAL: an error where the country has codes, normal where it does not
  • UNPLACED_SEGMENT: a comma-delimited part matched no field
  • AMBIGUOUS_UNIT: a unit designator with more than one reading
  • REGION_MISMATCH: region code not valid for the supplied country

Building a golden corpus and mutating it

Start with a small hand-verified corpus, one to three addresses per country, each with the expected field values written by someone who reads that country's mail. Twenty to forty cases is enough to catch structural regressions and small enough to review in a pull request. Store it as data, not as assertions buried in test code.

Then mutate each case mechanically: remove commas, change case, collapse double spaces, insert a non-breaking space, swap two lines, abbreviate a suffix, and append a unit. The expected output for a mutation is not always identical, but it should stay within a defined tolerance, and the confidence should fall rather than the fields silently changing. Track precision and recall per field so a fix for city does not quietly break postal.

MutationExample changeExpected behaviour
Drop commas1420 SW Alder St Portland OR 97205Same fields, lower confidence
Lowercaseportland, or 97205Same fields after normalization
Double spacePortland, OR 97205Same fields, whitespace collapsed
NBSP between city and statePortland, OR with U+00A0Same fields, NBSP normalized
Swap city and regionOR Portland 97205Flagged, not silently swapped
Truncate the street1420 SW AlderStreet kept, city still found

When not to parse at all

Do not parse freeform notes, delivery instructions, or anything a human wrote as prose. "Leave at the side gate, second house after the blue one" has no fields, and extracting tokens from it produces confident garbage. Keep it as a text blob attached to the order.

Do not parse scripts your rule set does not cover. A Japanese address in Kanji needs a Japanese grammar; running a Latin-script tokenizer over it will split on the wrong boundaries and lose the prefecture. Do not parse addresses that have no street number or that use a building name as the primary locator, which is common in parts of Asia and in campus addresses. In all of these cases the correct output is the original string plus a clear "not parsed" status.

  • Delivery instructions: store as text, never as fields
  • Unsupported scripts: return the original with an explicit status
  • Building-name addresses: do not force a house number
  • PO boxes and rural routes: parse with a country-specific rule, not a generic one
  • Anything already structured: validate it instead of re-parsing it

Questions

Can an address parser guarantee correct fields?+
No. It recovers structure that is present in the text and scores its own confidence. Fields that were never written down cannot be recovered, and parsing never proves an address is real.
Why does country matter before parsing?+
Field order differs: Germany and Japan put the postal code before the city, Japan puts it first, and the US puts it last. Without a country rule set, the same tokens get assigned to the wrong fields.
What should a parser do with low confidence?+
Keep the original string, return the partial fields with their scores, and flag the record for review. Writing a guess into structured columns loses the only reliable copy of the input.
How many test addresses do I need?+
Twenty to forty hand-verified cases, one to three per country, plus mechanical mutations. That is enough to catch structural regressions without creating a corpus nobody reviews.
Does the site parse addresses for me?+
The address parser tool exposes the field model and the format rules. It does not verify deliverability and does not claim that parsed fields describe a real location.

Examples are synthetic. Do not use a generated address for identity checks, account registration, or delivery.

Reference standards

Read next

All guides