A custom Home Assistant integration for tracking PostNL packages. Uses a headless Playwright service for fully automated OAuth — no browser extension required.
The original PostNL integration requires a browser extension to intercept the OAuth flow. This version replaces that with a lightweight Playwright service that handles login automatically. Enter your email and password, and it just works.
- Fully automated login — no browser extension, no manual OAuth redirects
- Auto token refresh — access tokens refresh silently every ~5 minutes
- Auto reauth — when refresh tokens expire (~2 weeks), Playwright re-logs in automatically
- Package tracking — incoming, sent, delivered, and missed deliveries
- Tracking details — sender name, delivery windows, tracking URLs, shipment type
You need a running Playwright service accessible from Home Assistant. A Docker image is provided.
Create a directory and add these files:
docker-compose.yml:
services:
playwright-service:
container_name: playwright-service
build: .
restart: unless-stopped
ports:
- "5050:5000"
environment:
- PYTHONUNBUFFERED=1
mem_limit: 512mDockerfile:
FROM python:3.11-slim
RUN pip install playwright fastapi uvicorn
RUN playwright install chromium
RUN playwright install-deps
WORKDIR /app
COPY app/ ./app/
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "5000"]The Playwright service source is available in the playwright-service/ directory of this repo.
docker compose up -dVerify it's running:
curl http://localhost:5050/health
# Should return: {"status":"healthy"}- Open HACS → Integrations
- Three dots (⋮) → Custom repositories
- Add
https://github.com/JasonKrijgsman/ha-postnl-robustas Integration - Search for "PostNL" and install
- Restart Home Assistant
- Copy the
custom_components/postnl/folder to your HA config directory - Restart Home Assistant
- Settings → Devices & Services → Add Integration → PostNL
- Enter:
- Playwright Service URL:
http://localhost:5050(or your Docker host IP) - Email: Your PostNL / jouw.postnl.nl account email
- Password: Your PostNL password
- Playwright Service URL:
- Submit — Playwright logs in automatically, tokens are stored
| Entity | Description |
|---|---|
sensor.post_nl_delivered |
Recently delivered packages |
sensor.post_nl_delivering |
Packages currently in transit |
sensor.post_nl_missed_delivery |
Failed delivery attempts |
sensor.post_nl_packages |
Total packages |
Each sensor has a tracking_# attribute containing package details (sender, tracking URL, delivery window, etc.).
type: markdown
title: Packages In Transit
content: >
{% for package in state_attr('sensor.post_nl_delivering', 'tracking_#') %}
- **{{ package.name }}** — {{ package.status_message }}
{% endfor %}Home Assistant
│
├── PostNL Integration
│ ├── Config Flow → Playwright login → OAuth tokens
│ ├── Token refresh every ~5 minutes (no Playwright needed)
│ └── Full reauth every ~2 weeks (Playwright needed)
│
└── Playwright Service (Docker :5050)
└── Headless Chromium → PostNL Azure B2C login
The OAuth scope is incorrect. The authorize URL must include scope=openid+profile+email+poa-profiles-api and audience=poa-profiles-api. If you see this error, update config_flow.py and re-add the integration.
curl http://localhost:5050/health
docker logs playwright-service --tail 20Playwright uses ~150-300MB. Set mem_limit: 512m in docker-compose to cap it. If running on a memory-constrained system (e.g., Synology NAS with 4GB RAM), consider stopping Playwright when not needed — it's only required for full reauth every ~2 weeks.
If you're running on a system with limited RAM, you can schedule Playwright to run briefly each day instead of permanently:
# Cron job or Synology Task Scheduler — daily at 4 AM
docker start playwright-service
sleep 300
docker stop playwright-serviceThis gives PostNL a 5-minute window to refresh tokens daily, using ~0MB the rest of the time.
Based on the ha-postnl integration by @arjenbos. This fork replaces the browser extension OAuth flow with automated Playwright login.
Apache-2.0 — see LICENSE