# DHL Parcel Netherlands Tracking API & MCP

URL: https://docs.lastscanned.com/carriers/dhlparcelnl

Query live **DHL Parcel NL** (`dhlparcelnl`) package status and scan history in a single synchronous `GET` request or MCP tool call.

`dhlparcelnl` covers DHL Parcel in the Netherlands and Benelux and DHL eCommerce Europe's `JVGL…` numbers.

**Source**: Plain `GET https://api-gw.dhlparcel.nl/track-trace?key={number}`, no key needed. An unknown number is a 404.

## Overview & Quick Facts

| Property | Value |
|---|---|
| **Carrier slug (`?carrier=`)** | `dhlparcelnl` |
| **Brand aliases** | DHL Parcel NL, DHL Parcel Benelux, DHL eCommerce Europe, DHL Parcel Connect, JVGL |
| **Category** | International parcels |
| **Single-package REST endpoint** | `GET https://api.lastscanned.com/v1/track/{trackingNumber}?carrier=dhlparcelnl` |
| **Batch REST endpoint** | `GET https://api.lastscanned.com/v1/track?numbers=...,...&carrier=dhlparcelnl` |
| **MCP server (`https://mcp.lastscanned.com`)** | `track_package`, `track_packages`, `list_carriers` |
| **Authentication & pricing** | `Authorization: Bearer lsk_live_...` · 1 free keyless lookup/day per IP |

## Tracking Number Formats & Auto-Detection

| Pass | Rule / Regex | Check Digit | Examples |
|---|---|---|---|
| **Pass 1 (`matches`)** | `/^JVGL\d{20}$/` | none | `JVGL01234567890123456789` |
| **Pass 2 (`mayMatch`)** | none | none | none |

`JVGL…` numbers belong to this network alone, so `?carrier=` is optional for them. DHL Parcel's own `3S…` barcodes are also used by PostNL, so pass `?carrier=dhlparcelnl` for those.

## Synchronous `GET` Request & Normalized JSON Response

```bash
curl -s "https://api.lastscanned.com/v1/track/JVGL01234567890123456789?carrier=dhlparcelnl" \
  -H "Authorization: Bearer $LASTSCANNED_API_KEY"
```

```json
{
  "carrier": "dhlparcelnl",
  "trackingNumber": "JVGL01234567890123456789",
  "status": "delivered",
  "statusDescription": "Collected at parcelstation",
  "service": null,
  "deliveredAt": "2026-08-21T14:17:19Z",
  "deliveredAtLocal": "2026-08-21T16:17:19",
  "signedBy": null,
  "destination": {
    "city": null,
    "state": null,
    "country": "NL"
  },
  "events": [
    {
      "timestamp": "2026-08-21T14:17:19Z",
      "localTime": "2026-08-21T16:17:19",
      "status": "delivered",
      "description": "Collected at parcelstation",
      "location": null,
      "code": "COLLECTED_AT_PARCELSTATION"
    },
    {
      "timestamp": "2026-08-21T11:57:41Z",
      "localTime": "2026-08-21T13:57:41",
      "status": "exception",
      "description": "Delivered at parcelshop",
      "location": null,
      "code": "DELIVERED_AT_PARCELSHOP"
    },
    {
      "timestamp": "2026-08-21T08:49:06Z",
      "localTime": "2026-08-21T10:49:06",
      "status": "out_for_delivery",
      "description": "Out for delivery",
      "location": null,
      "code": "OUT_FOR_DELIVERY"
    }
  ]
}
```

## Notes

- **Statuses**: the carrier's category and status code set `status`. `description` is the status code in plain words, and `code` keeps the code. A parcel waiting at a parcelshop or locker for the receiver shows as `exception` (ready for collection) until it is collected.
- **Time zone**: times are ISO with their own offset, so `timestamp` and `localTime` are exact.

## Related Resources

- **Regex & check digits**: [Tracking number formats & auto-detection](/formats)
