Track a USPS package and read its scan history

Site usps.comTask track-packageVersion v3Updated Sep 18, 2026Category logistics

Look up a USPS tracking number in the public browser interface and report the displayed shipment status, latest scan location, delivery estimate, and available event history, with explicit handling for unavailable results and access failures. This skill was captured from a live agent session on usps.com and is published here as a reusable recipe for agents.

NoteSelectors and URL schemes drift as sites change. A skill is a snapshot of what worked when it was captured, not a contract — agents re-learn it when it stops working.

Follow a USPS shipment from its public tracking result. Collect the current summary and the expanded history together, so a caller can distinguish a delivery estimate from a completed delivery and a purchased label from an accepted shipment. Return what USPS displays, retaining missing fields and ambiguous outcomes instead of filling them from assumptions.

Use Cases

  • Answer where a shipment was last scanned and what USPS currently says about its progress.
  • Retrieve a delivery estimate alongside the events supporting the current status.
  • Identify a delivery attempt, pickup instruction, or other exception that needs the caller's attention.
  • Check several supplied identifiers independently without combining their shipment histories.

Automation Flow

  1. Prepare one lookup. Keep the requested identifier as a string and remove formatting whitespace without dropping leading zeroes. Do not reject it solely because it exceeds a presumed domestic length. If the input appears to contain several identifiers, separate the lookups before navigation; never choose a candidate result on the caller's behalf.

  2. Open the public result in a browser. Start with https://tools.usps.com/go/TrackConfirmAction?qtc_tLabels1={encoded-tracking-id}, URL-encoding the cleaned identifier. If USPS redirects to /tracking/{tracking-id}, follow that navigation. If it returns an empty entry form, use the visible tracking input and submit once. The homepage's #home-input is an alternative starting point; when duplicate submit controls interfere, submit the visible input's own form.

  3. Check access and rendering before interpreting the shipment. Inspect both the page title and the result region. An access-denied screen, challenge, or blank document is a retrieval failure, not a package status. Wait for the result region to settle rather than relying only on the navigation load event. If the session remains blocked, report that limitation; a different browser or permitted proxy configuration is a troubleshooting option, not a guaranteed prerequisite or cure.

  4. Bind the result to the request. Read the identifier displayed with the shipment, normalize its whitespace, and compare it with the requested value. The URL alone is insufficient proof of identity. If the displayed number differs, stop and retry a fresh lookup. If several shipments are offered, return their candidate identifiers for selection. If a populated result has no readable identifier, report that identity could not be verified rather than attaching its events to the request.

  5. Capture the current summary. Locate the status within the matching result region, not a general page heading or help article. The .tracking-progress-bar-status-container anchor from the source notes is a candidate to inspect, not a required selector: use the current DOM and accessible labels if that structure has changed. Record the exact status text and explanatory text before assigning a broad category:

    Evidence in the shipment resultCategory and interpretation
    A completed delivery statementdelivered; preserve the actual delivery time separately from any estimate.
    An explicit out-for-delivery statementout_for_delivery; do not count it as delivered.
    Acceptance, possession, facility movement, or transit informationin_transit; possession of the item must not be classified as label creation.
    A label or pre-shipment statement explicitly saying USPS is awaiting the itemawaiting_item; do not infer a physical scan.
    A failed attempt, notice, or availability-for-pickup statementdelivery_action; preserve the instruction without initiating an action.
    A delay or routing/address problem that does not fit the categories aboveexception; include USPS's wording so the category does not conceal the cause.
    An unavailable-status message without a usable shipment summaryunavailable; retain the explanation without asserting the number is invalid or that USPS has never received the item.
    An explicit statement that the lookup could not locate the requested informationnot_found; describe this lookup outcome, not the package's existence.
    A readable status whose meaning is unclearunknown; return its exact wording for interpretation.

    A populated result must not fall through to “not loaded” simply because its heading differs from an unavailable-result heading.

  6. Read locations and delivery timing as separate fields. Capture the location associated with the latest scan, using city, state, and postal code when available. Keep a facility label separately if USPS supplies one; do not turn it into an inferred street address. For an estimate, retain the displayed date and time window verbatim. For completed delivery, retain the actual delivery text instead. Do not invent an ISO timestamp or timezone from a date-only label, and do not treat an old estimate as proof of delivery.

  7. Expand the event history. Find the visible history control and open it only if collapsed. Read every loaded event row within this shipment, including its status, date/time text, and location. If a “more” control loads additional events, continue until no additional rows appear or retrieval fails. Preserve the displayed order and state which order it is; reverse or sort only when the timestamps establish chronology. Keep distinct scans even when they share a status label. Open Product Information separately when needed to read the service name.

  8. Return the shipment with an extraction report. Include these fields, keeping unavailable values null:

    • trackingId, displayedTrackingId, and identityVerified.
    • statusCategory, statusText, and message.
    • currentLocation, expectedDeliveryText, deliveredAtText, and serviceType.
    • events, with each row's statusText, timestampText, and locationText.
    • historyState: loaded, partial, unavailable, or not_extracted; also include eventOrder, sourceUrl, and retrievedAt.

    Use events: null when the history was not extracted or could not be opened. Use an empty array only when the inspected result actually presents no events. If some rows were collected before an interruption, keep them with historyState: partial. “Loaded” describes the available page content, not a guarantee that USPS exposes every scan it holds internally.

  9. Finish without changing delivery preferences. Leave notification enrollment, delivery instructions, holds, and redelivery untouched. Close or release a session created solely for this lookup. When sharing debug output, mask tracking identifiers in URLs, page captures, and logs, and omit street-level delivery details.

Params

ParamPurposeHandling
tracking-idThe identifier supplied by the callerPreserve as text; remove whitespace and URL-encode for navigation.
include-historyWhether the caller needs the available scan rowsWhen omitted, include history; when false, return historyState: not_extracted.
include-serviceWhether to inspect Product InformationReturn null if the service is not displayed.

Possible Friction Points

ObservationResponse
The page contains a valid delivery or transit resultRead the summary and history. An unavailable-only heading check is not a tracking extractor.
A general FAQ mentions an unavailable statusIgnore it; classification must come from the matching shipment's result region.
The result number cannot be matched to the inputStop before returning shipment fields. Report the mismatch or missing identity evidence.
A history control expands but rows are still appearingWait and inspect again. Mark a partial collection if loading never finishes.
USPS presents an unavailable heading without a displayed numberPreserve the message and requested identifier, but set identityVerified: false; do not claim a verified shipment record.
Dates omit a year, timezone, or time of dayPreserve their text and report the missing precision. Do not manufacture a sortable timestamp.
Direct requests to a page-internal JSON endpoint failContinue through the rendered browser interface; this recipe does not assume an anonymous API contract for internal endpoints.
Repeated lookups encounter challenges or access failuresReduce request frequency and stop sustained retries. No tested universal request quota or proxy requirement is established here.
The application needs an authenticated tracking integrationConsult the current USPS developer portal. Do not build a new integration around legacy Web Tools, whose registration site reports its retirement.

Before moving this draft into the published catalog, validate a real populated lookup end to end: matching identifier, current summary, location/timing fields when present, and expanded scan rows. Also exercise an unavailable result and an access or loading failure. Record which states were actually observed; fabricated fixtures and source notes can check logic but cannot establish live coverage.

Call it

GET https://production-sfo.browserless.io/skills?token=TOKEN-HERE&domain=usps.com&task=track-package