Updated May 2026 — the integration is now a proper Home Assistant custom component, no Multiscrape required.
If you’re like me and rely heavily on Home Assistant to keep your smart home organized, you probably also want to track your incoming parcels alongside your automations. For quite some time, I used the PostNL integration in Home Assistant. It started as a core integration but eventually broke due to security restrictions on PostNL’s side. Later, it came back to life via a custom integration—only to break again when PostNL tightened their API access.
These days, PostNL tracking works again thanks to a browser extension for authentication, and it has been stable enough for me to get parcel updates reliably.
However, only about 50% of my packages are handled by PostNL. The other 50% typically come via DHL, with the occasional delivery from DPD or UPS. So naturally, I also wanted my DHL packages to show up in Home Assistant, providing a more complete overview of what’s on the way to my doorstep.
What You’ll Need
- A valid DHL account at my.dhlecommerce.nl
- HACS installed in Home Assistant
Note: The DHL API used here is unofficial (reverse-engineered). Any changes on DHL’s side can break this setup without warning.
Installation
- Open HACS in Home Assistant and go to Integrations.
- Click the three-dot menu (top right) → Custom repositories.
- Add
https://github.com/peternijssen/ha-dhl-nlas an Integration. - Search for DHL NL and install it.
- Restart Home Assistant.
Configuration
After restarting, go to Settings → Devices & Services → Add Integration and search for DHL NL.
You will be asked for your DHL account email address and password. The integration validates your credentials against the live API before saving. If you use multiple DHL accounts, you can add the integration multiple times.
No YAML configuration is needed.
Sensors
The integration creates the following sensors per account:
| Sensor | Description |
|---|---|
| DHL Incoming Parcels | Count of active incoming parcels. The parcels attribute contains the full list with sender, barcode, status, and delivery window. |
| DHL Outgoing Parcels | Count of active outgoing shipments. The shipments attribute contains the full list with recipient, destination, and status. |
| DHL Next Delivery | Timestamp of the earliest expected delivery across all active parcels. Useful for automations like “notify me 1 hour before delivery”. |
| DHL Parcels En Route to ServicePoint | Count of parcels being shipped to a DHL ServicePoint (not yet arrived). |
| DHL Parcels Awaiting Pickup | Count of parcels that have arrived at a ServicePoint and are ready for collection. |
DHL Parcel <barcode> | One sensor per active parcel. State is the parcel status; all parcel details are in the attributes. These sensors are automatically created and removed as parcels come and go. |
The integration polls the DHL API every 30 minutes.
Dashboard Card
Here is a Markdown card that shows your incoming parcels in a table:
- type: markdown
content: >
{% set parcels = state_attr('sensor.dhl_incoming_parcels', 'parcels') %}
{% if parcels and parcels | count > 0 %}
| Carrier | Sender | Expected |
|---|---|---|
{% for p in parcels %}
| DHL | {{ (p.sender or {}).get('name', 'Unknown') }} | {{ (p.receivingTimeIndication or {}).get('moment', 'Unknown') | as_datetime | as_local if (p.receivingTimeIndication or {}).get('moment') else 'Unknown' }} |
{% endfor %}
{% else %}
No active DHL parcels.
{% endif %}And a conditional card that only shows up when there are parcels to pick up at a ServicePoint:
- type: conditional
conditions:
- condition: numeric_state
entity: sensor.dhl_parcels_awaiting_pickup
above: 0
card:
type: entities
title: DHL Pickup Ready
entities:
- sensor.dhl_parcels_awaiting_pickupAutomations
Because DHL Next Delivery is a proper timestamp sensor, you can trigger automations relative to it:
automation:
- alias: "DHL delivery reminder"
trigger:
- platform: template
value_template: >
{% set next = states('sensor.dhl_next_delivery') | as_datetime %}
{% if next %}
{{ (next - now()).total_seconds() < 3600 }}
{% else %}
false
{% endif %}
action:
- service: notify.mobile_app_your_phone
data:
message: "DHL delivery start expected within the hour!"Notes
- The integration uses the same unofficial API that the DHL eCommerce app uses. It has been working reliably but is not officially supported by DHL.
- For issues or feature requests, visit the GitHub repository.
Conclusion
Once the integration is running, you rarely think about it. DHL shipments appear in Home Assistant automatically, the dashboard card keeps the status visible, and the automation handles the notification at the right moment. No need to check tracking emails or open an app.
The integration covers the most common scenarios without any YAML configuration. If you also receive PostNL packages, the PostNL integration works the same way and sits neatly alongside it.
Join the discussion in the Home Assistant Community to see other implementations suggested by others.
Hi,
I keep getting error 400, does the DHL scrapping work for you ?
Deze fout is ontstaan door een aangepaste integratie.
Logger: custom_components.multiscrape.coordinator
Bron: custom_components/multiscrape/coordinator.py:174
integratie: Multiscrape (documentatie, problemen)
Eerst voorgekomen: 11:37:25 (3 gebeurtenissen)
Laatst gelogd: 13:25:14
DHL packages # Updating failed with exception: Client error ‘400 Bad Request’ for url ‘https://my.dhlecommerce.nl/receiver-parcel-api/parcels’ For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400
thanks,
Rien
Hi Rien! Still working here. So must be something wrong in your config 🙁
My status remains unavailable
This is what my log says:
This error occurred due to a custom integration.
Logger: custom_components.multiscrape.coordinator
Source: custom_components/multiscrape/coordinator.py:174
Integration: Multiscrape (documentation, issues)
First occurred: 3:10:28 PM (1 event)
Last logged: 3:10:28 PM
Scraper_noname_1 # Updating failed with exception: Client error ‘400 Bad Request’ for url ‘https://my.dhlecommerce.nl/receiver-parcel-api/parcels’. For more information, check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400
Hi Peter,
Thanks for sharing the knowledge regarding Multiscraper. I did had the same issue like Rien and Rene did, but Gemini helped out:
multiscrape:
– name: DHL Tracker
resource: “https://my.dhlecommerce.nl/receiver-parcel-api/parcels”
scan_interval: 1800
log_response: True
# The form_submit block handles the login and keeps the session alive
form_submit:
submit_once: True
resource: “https://my.dhlecommerce.nl/api/user/login”
method: “post”
headers:
Content-Type: “application/json”
# Adding a User-Agent helps bypass basic bot detection
User-Agent: “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36”
payload: ‘{“email”:”EMAIL”,”password”:”PASSWORD”}’
sensor:
– unique_id: dhl_packages
name: DHL Pakketten
value_template: “{{ value_json.parcels | selectattr(‘category’, ‘search’, ‘(PROBLEM|CUSTOMS|DATA_RECEIVED|EXCEPTION|INTERVENTION|IN_DELIVERY|LEG|UNDERWAY|UNKNOWN)’) | list | count }}”
attributes:
– name: parcels
value_template: “{{ value_json.parcels | selectattr(‘category’, ‘search’, ‘(PROBLEM|CUSTOMS|DATA_RECEIVED|EXCEPTION|INTERVENTION|IN_DELIVERY|LEG|UNDERWAY|UNKNOWN)’) | list }}”
In my error log I had this:
Invalid value for: cookie X-AUTH-TOKEN (missing)
Hi, it did work for a long time..
But now i noticed that the API URL won’t work anymore.
https://my.dhlecommerce.nl/receiver-parcel-api/parcels
It give a error
Yeah I noticed. They upped their API requests. I vibe-coded a custom component together. Not sure though if it works. See https://github.com/peternijssen/ha-dhl-nl