Skip to content
All Posts
Replacement Guide

usps-api and usps-webtools Are Dead: the 2026 Replacement

·Updated ·9 min read·By RevAddress·Replacement Guide

If your USPS integration stopped working and you are running any of these packages, the package is not the problem. The API behind it is gone.

USPS retired the Web Tools XML API at secure.shippingapis.com on January 25, 2026. Every one of these depended on that host:

Package Registry Last published Status
usps-api PyPI 0.5, July 2020 Dead
usps-webtools npm 1.0.7, July 2021 Dead
usps-webtools-promise npm 6.1.0, December 2023 Dead

All three still install cleanly and still see download traffic from developers who have not learned that the endpoint behind them no longer answers. Nothing in the package is broken. The install works, the import works, the API call does not.

The error you are staring at

What a dead package looks like at runtime
# usps-api — broken since January 25, 2026
from usps import USPSApi

usps = USPSApi("YOUR_USER_ID")
address = usps.validate_address(
  "1600 Pennsylvania Ave NW",
  "Washington",
  "DC",
)

# ConnectionError: HTTPSConnectionPool(host='secure.shippingapis.com')
# Max retries exceeded — the host is gone, not slow.

No retry count, timeout increase, or version pin changes this. There is no redirect and no compatibility shim.

Why dead packages keep getting installed

Three reasons, and the first one is the expensive one.

Lockfiles do not know the API died. CI resolves the dependency, the build goes green, the deploy succeeds. The USPS calls fail at runtime, in production, and unless you monitor USPS responses specifically, the first signal is a customer reporting that checkout will not accept their address.

The tutorials outrank the obituary. Search for USPS API integration in any language and results written years before the retirement still sit at the top, linking straight to the registry page. They rank because they accumulated backlinks while the API was alive.

Nobody published a deprecation notice. None of the three packages shipped a final release warning that the upstream was scheduled for retirement. The READMEs still describe a working integration.

The replacement

usps-v3 targets the current REST API at apis.usps.com. Same postal data, different protocol and different authentication.

Swap the dependencybash
# Python
pip uninstall usps-api
pip install usps-v3

# Node.js
npm uninstall usps-webtools usps-webtools-promise
npm install usps-v3
Old packages usps-v3
Host secure.shippingapis.com (gone) apis.usps.com
Format XML JSON
Auth User ID in the request OAuth 2.0, handled by the SDK
Errors Parse the XML error string Typed exceptions
Maintained No Yes

The credential changes shape. The old packages took a Web Tools User ID. The v3 API issues a Consumer Key and Consumer Secret against an app you register at developer.usps.com. Registering is free. Note that registering is not the same as being licensed to call the Addresses API, which is covered below.

Address validation, old and new

Address validation after the swap
from usps_v3 import Client

# Or set USPS_CLIENT_ID and USPS_CLIENT_SECRET and call Client().
client = Client(client_id="your_client_id", client_secret="your_client_secret")

result = client.addresses.validate(
  street_address="1600 Pennsylvania Ave NW",
  city="Washington",
  state="DC",
  zip_code="20500",
)

# The Python SDK returns plain dictionaries, not objects.
print(result["address"]["streetAddress"])   # 1600 PENNSYLVANIA AVE NW
print(result["address"]["ZIPPlus4"])        # 0005

Two details cost people an afternoon each. The Python SDK exports Client and returns dictionaries, so result["address"]["ZIPPlus4"] is right and result.address.zip_plus_4 is not. And the Node SDK takes ZIPCode with a capital ZIP, matching the USPS schema rather than the camelCase convention around it; passing zipCode sends nothing.

Tracking, old and new

Tracking after the swap
info = client.tracking.track("9400111899223033005282")

print(info["statusCategory"])   # "Delivered"

The method is track, on both. If you are porting from a guide that calls tracking.get(), that guide predates the current SDK.

What each operation is called now

Operation Web Tools XML Python Node.js
Validate address AddressValidateRequest addresses.validate() addresses.validate()
City/state from ZIP CityStateLookupRequest addresses.city_state() addresses.cityState()
Track a package TrackFieldRequest tracking.track() tracking.track()
Domestic rates RateV4Request prices.domestic() prices.domestic()
International rates prices.international() prices.international()
Delivery estimates standards.estimates() standards.estimates()
Drop-off locations locations.dropoff() locations.dropoff()
Create a label eVSRequest labels.create() labels.create()

Errors you can actually catch

The largest practical gain over the old packages. Web Tools returned errors as XML strings you had to parse and pattern-match; the SDK raises typed exceptions.

Typed error handling
from usps_v3 import Client, AuthError, ValidationError, RateLimitError, APIError

try:
  result = client.addresses.validate(street_address="123 Main St")
except ValidationError as e:
  print(f"Bad input on {e.field}: {e}")
except RateLimitError as e:
  print(f"Rate limited — retry after {e.retry_after}s")
except AuthError as e:
  print(f"Auth failed: {e}")
except APIError as e:
  print(f"USPS error {e.status_code}: {e}")

RateLimitError is the one you will meet. USPS caps an application at 60 requests per hour across every endpoint, a limit Web Tools never enforced.

What is free now, and what is not

This is where guides written before August 2026 mislead.

Tracking, pricing, and service standards sit outside the USPS fee curve. Register an app, authenticate, call them.

Address validation does not. Since August 1, 2026 the Addresses API requires a signed license agreement and bills on a consumption-tier curve. That is a DocuSign round trip and a funded Enterprise Payment Account before your first validated address, not a checkbox. What the USPS API actually costs walks the curve and the enrollment order.

Labels need more than OAuth. Label creation requires a CRID, Mailer IDs, an Enterprise Payment Account, and COP claims linking. Both SDKs accept those as constructor arguments, but obtaining them is an enrollment project. The CRID and MID enrollment guide documents each step.

If you only need addresses standardized and geocoded rather than USPS-verified, there is a route with no license at all: RevAddress runs standardization, geocoding, and address extract against US Census Bureau data at no per-lookup cost. It will not return DPV or ZIP+4, because those are USPS data. For DPV, rates, and tracking, connect your own USPS license and the OAuth lifecycle, caching, and retries are handled on your credentials.

Token handling you no longer write

Both SDKs cache the OAuth token and refresh it about 30 minutes before the 8-hour expiry. Python also persists the token to ~/.usps-v3/tokens.json, which matters for short-lived processes: a cron job that runs every five minutes will reuse one token instead of requesting a new one per run, and token requests draw on the same 60-per-hour ceiling as everything else.

Start here

Questions

Is the usps-api Python package still working?
No. usps-api targets the USPS Web Tools XML API, which was retired on January 25, 2026. The package installs and imports without complaint and then fails at runtime with a connection error. The replacement is pip install usps-v3, which targets the v3 REST API.
What replaced usps-webtools and usps-webtools-promise?
npm install usps-v3. Both legacy packages spoke the retired Web Tools XML API. The replacement covers the same address validation and tracking operations against the v3 REST API, with JSON responses, automatic OAuth token handling, and TypeScript definitions.
Why did my build succeed if the package is dead?
Because nothing about the package is broken. The registry entry, the install, and the import all work. What is gone is the API host it calls. The failure only appears when a request goes out, which is why lockfile-driven CI keeps shipping the dependency and the breakage surfaces as a customer report.
Do I need new credentials to migrate?
Yes. The old packages took a Web Tools User ID string. The v3 API uses OAuth 2.0, so you register an app at the USPS Developer Portal and use a Consumer Key and Consumer Secret. The SDK exchanges and refreshes tokens for you.
Is address validation still free on the v3 API?
No. Since August 1, 2026 the Addresses API requires a signed license agreement and bills on a consumption-tier curve. Tracking, pricing, and service standards sit outside that fee curve. Any guide that still calls v3 address validation free predates the change.