Skip to content
Code Recycle

Component · for humans & their agents

Address Normalize

verified · first-partyactively maintained$0 during beta (was $79)

A fuzzy match scores "123 Main St E" and "123 Main St W" as near-identical -- one character apart, and two different streets half a mile apart. The merge is destructive: the losing record's data is gone.

by Code Recycle

Get it free — beta

Every claim on this page is refundable if it is untrue — refund policy.

Verified: 111 tests

Normalizes US street addresses to USPS Publication 28 conventions and compares two addresses as SAME, DIFFERENT or UNKNOWN, with a reason that names which component decided it.

Normalizes US street addresses to USPS Publication 28 conventions and compares two addresses as SAME, DIFFERENT or UNKNOWN, with a reason that names which component decided it.

THE SILENT FAILURE. Address matching is usually done one of two ways, and both are quietly wrong in opposite directions, and neither errors when it is wrong.

STRING EQUALITY CREATES DUPLICATES. '123 N Main St Apt 4' and '123 North Main Street #4' are the same physical mailbox and are not equal as strings, so a customer or an account gets created twice. Nothing throws; the duplicate surfaces months later because one copy got the invoice and the other got the notice.

FUZZY MATCHING DESTROYS DATA. '123 Main St E' and '123 Main St W' differ by one character and score as near-identical under a fuzzy ratio -- and are two different streets half a mile apart. A fuzzy merge silently combines two customers' records, and the merge is destructive: the losing record's data is gone. This library never computes an edit distance; addresses are parsed into structured fields first, and only the field that actually differs is compared.

THE ONE-SIDED UNIT. '500 Oak Ave Apt 12B' versus '500 Oak Ave' is not a match and not a non-match -- it is genuinely unknown whether the second record omitted the apartment number or really is the whole building's address. Answering that as a boolean is guessing, and whichever way it guesses is silently wrong some fraction of the time. This library's answer is a third value, UNKNOWN, and that is the point of the product, not a failure mode of it.

A TRAILING CITY WAS SILENTLY ABSORBED. An earlier version of this library accepted '123 Main St, Springfield' as valid, absorbing the city into the street name and setting the suffix and postdirectional to null -- then reported a confident DIFFERENT against the same address written with its city, on the most ordinary input shape there is: a caller who has not split line1 from city perfectly. The comma is now treated as structure: everything after it must be a complete secondary unit, or the input is refused by name.

VERIFIED: 111 tests, re-measured by running the suite, 6 deliberate defects applied to compareAddresses — 4 caught, 2 measured provably equivalent (houseNumber and boxNumber are always strings, so loose vs strict equality cannot differ for them; the proof ships in mutations.json)

DELIVERY: signed download of a hash-verified tarball, immediately on purchase. Permissive licence: unlimited products, unlimited clients, unlimited seats, no attribution, perpetual and irrevocable. One restriction, do not republish the source as source.

Interface

What you call, and what comes back. Types and signatures only — the implementation ships with the source.

  export function compareAddresses(rawA: string, rawB: string): ComparisonResult;
  export function normalizeAddress(input: string): NormalizeResult;
  export function parseAddress(input: string): ParseResult;
  export type NormalizeResult = NormalizeSuccess | Exclude<ParseResult, { ok: true }>;
  export type Directional = 'N' | 'S' | 'E' | 'W' | 'NE' | 'NW' | 'SE' | 'SW';
  export type SecondaryDesignator = string;
  export type ParsedAddress = StreetAddress | PoBoxAddress;
  export type ParseResult = ParseSuccess | ParseFailure;
  export type Verdict = 'SAME' | 'DIFFERENT' | 'UNKNOWN';

01Capabilities

Does

  • + Input validation
  • + Entity resolution

Doesn’t

  • No exclusions declared

02Requirements & stack

Depends on

No declared dependencies

Credentials needed

None declared

Stack

typescript

03Community

No endorsements yet

No verified confirmations yet — be the first.

Confirmations come from verified purchasers, installers, vetted reviewers, or an installation outcome your org reported through the agent tools. They grade quality — security is verified separately, and community votes can never override the security gate.

Open an issue

Sign in to confirm — weight comes from verified usage, not vote count.

0 open · 0 answered · 0 fixed · 1 said it worked

04Trust Passport

Full passport →
–/100

0/0 automated components pass. An automated score is never a security guarantee.

✓ Verified · first-partyreviewed Sep 20, 2026 · re-verification due Dec 19, 2026
  • publisher identity Publisher status verified; 1 verification(s) on file
  • malicious pattern scan No known malicious-behavior patterns across 19 source file(s) plus listing text
  • capability contract All 0 observed capability reference(s) match the declared manifest
  • agent safety scan No injection patterns in agent-readable content
  • provenance No release signature or provenance attestation
  • behavioral sandbox Not performed in this environment — requires the production isolated runner (docs/sandbox-requirements.md). No untrusted code is ever executed on the application host.

Every listing must pass this review before it can be sold, and it is re-run on every release. Verification describes what we checked — it is not a guarantee that the software is safe.

VersionChannelReleasedNotes
1.0.0stableAug 5, 2026First public release.