Carriers

CouriersPlease Tracking API & MCP

Query live CouriersPlease (couriersplease) consignment status and scan history in a single synchronous GET request or MCP tool call. lastscanned auto-detects the 14-character CP consignment numbers and batches up to 10 numbers into one upstream request.

Overview & Quick Facts

PropertyValue
Carrier slug (?carrier=)couriersplease
Brand & service aliasesCouriersPlease, Couriers Please, CP
CategoryAustralian domestic courier
Single-package REST endpointGET https://api.lastscanned.com/v1/track/{trackingNumber} (add ?carrier=couriersplease where noted below)
Batch REST endpointGET https://api.lastscanned.com/v1/track?numbers=CPABCDE0012345,...
MCP server (https://mcp.lastscanned.com)track_package, track_packages, list_carriers (claude mcp add --transport http lastscanned https://mcp.lastscanned.com)
Authentication & pricingAuthorization: Bearer lsk_live_... · 1 free keyless lookup/day per IP · Free tier (5 unique numbers/day, $0) · Pro ($4.99/mo for 1,000 unique numbers, unlimited re-polls, $0.015/extra) · HTTP 402 Stripe MPP ($0.50 for 25-number lsk_pack_ key or $0.02/number in USDC on Tempo)

Tracking Number Formats & Auto-Detection

PassRule / RegexCheck DigitExamples
Pass 1 (matches)/^CP[A-Z]{5}\d{7}$/—CPABCDE0012345
Pass 2 (mayMatch)None——
Explicit (?carrier=couriersplease)Any other CouriersPlease consignment or item (coupon) number——

Consignment numbers are 14 characters: CP, five letters, seven digits. Item (coupon) numbers and other shapes work with ?carrier=couriersplease.

Synchronous GET Request & Normalized JSON Response

curl

curl -s "https://api.lastscanned.com/v1/track/CPABCDE0012345?carrier=couriersplease" \
  -H "Authorization: Bearer $LASTSCANNED_API_KEY"

JavaScript / TypeScript (fetch)

const res = await fetch("https://api.lastscanned.com/v1/track/CPABCDE0012345?carrier=couriersplease", {
  headers: { Authorization: `Bearer ${process.env.LASTSCANNED_API_KEY}` },
});
const pkg = await res.json();
console.log(pkg.status, pkg.events[0]);

MCP track_package tool call

{
  "tool": "track_package",
  "arguments": {
    "tracking_number": "CPABCDE0012345",
    "carrier": "couriersplease"
  }
}

Normalized TrackingResult JSON response

{
  "carrier": "couriersplease",
  "trackingNumber": "CPABCDE0012345",
  "status": "in_transit",
  "statusDescription": "Parcel is progressing through our network",
  "service": null,
  "deliveredAt": null,
  "deliveredAtLocal": null,
  "signedBy": null,
  "destination": null,
  "estimatedDelivery": "2026-10-28",
  "message": null,
  "events": [
    {
      "timestamp": "2026-10-26T04:10:00Z",
      "localTime": "2026-10-26T15:10:00",
      "status": "in_transit",
      "description": "Parcel is progressing through our network",
      "location": "NSW",
      "code": "status"
    },
    {
      "timestamp": "2026-10-24T22:45:00Z",
      "localTime": "2026-10-25T09:45:00",
      "status": "in_transit",
      "description": "Picked up from sender",
      "location": "VIC",
      "code": "pickup"
    }
  ]
}

Status Notes

  • Access: CouriersPlease's site only accepts calls that look like its own frontend, so lastscanned loads the tracking page first to get its CSRF token and cookie, then makes the lookup with the matching headers.
  • Times: scan times are local to the scan's state. The state code gives the zone, so timestamp is set when the state is known and only localTime otherwise.
  • Delivery estimate: estimatedDelivery is the page's Delivery ETA date when it has one.

On this page