ScreenshotNeo

BlogHow-to

How to Scrape DHL Parcel Tracking Data in 2026

DHL documents APIs and tracking links for authorized integrations. Learn which option fits your region, how to handle limits, and why browser scraping is risky.

By the ScreenshotNeo team1 October 20269 min read

Short answer: Do not build an automated scraper for DHL’s Developer Portal or APIs. DHL’s general Developer Portal Terms of Use prohibit automated systems from accessing, scraping, or retrieving portal/API content and prohibit bypassing access controls or call limits. For a compliant integration, identify the DHL division and country, request the documented API access, use the parameterized DHL tracking link when a link is enough, or subscribe to Unified Tracking Push where your service is supported.

The mechanics below focus on DHL Parcel Germany because its public documentation describes the clearest parcel-specific interfaces. DHL Express, DHL eCommerce Americas, Global Forwarding, Supply Chain, Freight, and other regions have different products, identifiers, permissions, data scopes, and terms.

What “DHL parcel tracking” means in 2026

“DHL Parcel” is not one global API. Start by identifying:

  • Division and product: Parcel Germany, Express, eCommerce, Supply Chain, or another DHL business unit.
  • Region: the API and eligibility can change by country.
  • Shipment ownership: some interfaces expose only shipments belonging to the authenticated business or pickups authorized for that API user.
  • Update model: request/response polling, a direct DHL tracking link, or push events.
  • Data sensitivity: business queries can return customer or recipient information that must remain inside the permitted internal use.

DHL Parcel Germany’s documentation covers DHL Paket, returns, Warenpost, two-man handling, and import shipments. It directs DHL Express users to the separate MyDHL API.

Choose the supported integration

Option Use it when Important constraints
DHL Parcel Germany public query You need public tracking details in a customer experience. Access is required; up to 15 shipment or reference numbers per request; searches the previous three months; references must identify one shipment; a recipient postcode may be required for some location data.
DHL Parcel Germany business query You operate an internal service for your own contract shipments. Requires the right business-customer permission, including the “Track parcels & goods” function; up to 20 numbers; collective queries do not accept a postcode; data is intended for internal systems.
Parameterized DHL tracking link You only need to send a customer to DHL’s current result page. Use the direct-link format documented by DHL for your division. This avoids extracting DHL’s HTML.
Unified Tracking Push API You need ongoing events without frequent polling. Confirm that the exact service is supported. Your receiver needs a valid SSL certificate and must return HTTP 200 within five seconds. DHL documents retries after one hour and then six hours after the second failed delivery.

Step 1: identify the DHL service and request access

  1. Record the country where the shipment was accepted and the DHL product named on the label or contract.
  2. Open that product’s official developer documentation. Do not assume a Parcel Germany credential works for Express or eCommerce Americas.
  3. Request an application/API credential and the required business permissions. Keep credentials server-side and never place them in browser JavaScript or a public repository.
  4. Confirm the permitted data fields, shipment ownership rules, rate limits, retention rules, and whether customer-facing display is allowed.

DHL’s general portal terms state that automated systems such as crawlers, spiders, search bots, browser plug-ins, extensions, add-ons, or similar processes may not access, scrape, modify, copy, download, or retrieve content from the Developer Portal or its APIs. The same terms prohibit overriding security measures and bypassing access controls or API call limits. Treat the documented API contract as the automation route.

Step 2: build a compliant request layer

The exact endpoint, authentication scheme, and field names depend on your DHL product. Copy those values from the relevant official portal instead of guessing them. The examples below show a safe request shape without inventing an endpoint.

cURL template

curl --fail-with-body --request GET \
  --url "$DHL_API_ENDPOINT" \
  --header "Authorization: Bearer $DHL_ACCESS_TOKEN" \
  --header "Accept: application/json" \
  --data-urlencode "shipmentNumber=$SHIPMENT_NUMBER"

Replace DHL_API_ENDPOINT, the authentication header, and parameter names with the values in your product’s DHL documentation. If the API uses an API key, client certificate, or OAuth flow instead, follow that product’s instructions.

Python template

import os
import requests

endpoint = os.environ["DHL_API_ENDPOINT"]
token = os.environ["DHL_ACCESS_TOKEN"]
shipment_number = os.environ["DHL_SHIPMENT_NUMBER"]

response = requests.get(
    endpoint,
    headers={
        "Authorization": f"Bearer {token}",
        "Accept": "application/json",
    },
    params={"shipmentNumber": shipment_number},
    timeout=30,
)
response.raise_for_status()
data = response.json()
print(data)

Node.js template

const endpoint = process.env.DHL_API_ENDPOINT;
const token = process.env.DHL_ACCESS_TOKEN;
const shipmentNumber = process.env.DHL_SHIPMENT_NUMBER;

const url = new URL(endpoint);
url.searchParams.set('shipmentNumber', shipmentNumber);

const response = await fetch(url, {
  headers: {
    Authorization: `Bearer ${token}`,
    Accept: 'application/json'
  }
});

if (!response.ok) {
  throw new Error(`DHL request failed: ${response.status} ${await response.text()}`);
}

console.log(await response.json());

Step 3: respect query limits and shipment scope

For the Germany public query, batch no more than 15 shipment or reference numbers in one request and expect a three-month search window. A reference must map uniquely to a shipment. The Germany business query allows up to 20 numbers for that authenticated business customer and does not allow a postcode on collective queries.

  • Validate and deduplicate numbers before sending a request.
  • Keep a local status timestamp so you do not poll unchanged shipments unnecessarily.
  • Use exponential backoff for transient failures, while honoring DHL’s documented limits.
  • Queue large imports in batches instead of creating one request per shipment at the same instant.
  • Do not mix shipments from unrelated customers or accounts in a business query.

DHL documents a parameterized direct tracking link to dhl.de for order overviews and shipping emails. Generate that link using the exact template and parameter name in the documentation for your service. A link is often the best choice when the customer only needs the current DHL result page and your system does not need to store event data.

# Pseudocode: copy the documented DHL template for your product.
tracking_url = DHL_DOCUMENTED_TRACKING_TEMPLATE.replace(
    "{tracking-number}", shipment_number
)
print(tracking_url)

Do not copy the rendered DHL page with a headless browser merely because a link is inconvenient. Browser automation can violate the portal/API terms, break when markup changes, and expose personal data to your infrastructure.

Step 5: receive events with Unified Tracking Push

Check the supported-product list before implementing a receiver. Your HTTPS endpoint must present a valid SSL certificate and return HTTP 200 within five seconds of an event POST. Validate signatures or credentials exactly as DHL specifies, persist the event idempotently, and acknowledge quickly before doing heavier work.

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.post("/webhooks/dhl")
def dhl_webhook():
    event = request.get_json(force=True)
    # Validate the authentication required by your DHL product.
    # Store using an idempotency key before dispatching background work.
    save_event_if_new(event)
    return jsonify({"received": True}), 200

Design for retries. DHL documents a retry after one hour and another six hours after the second failed delivery. Returning a non-200 response because downstream processing is slow can therefore create duplicate deliveries.

Data handling, retention, and privacy

Apply the terms for the specific DHL service you use. Do not generalize one division’s retention policy to every DHL API. DHL Supply Chain Track & Trace terms, for example, describe tracking data as confidential, restrict it to legitimate tracking purposes, prohibit combining it with advertising, and require deletion 120 days after delivery unless otherwise agreed. Business interfaces can expose sensitive recipient data, so restrict logs, encrypt stored responses, minimize fields, and delete records according to the applicable contract.

Why HTML scraping fails in production

  • Terms and access controls: DHL’s portal terms prohibit automated access to the portal and APIs and bypassing limits.
  • Markup churn: a selector that works today can fail after a redesign or localization change.
  • Authentication state: consent, bot checks, and session state make results inconsistent.
  • Data ambiguity: a page may show a human-readable status but omit structured event identifiers or timestamps.
  • Operational cost: browsers consume more CPU, memory, and network bandwidth than a documented API call.

Or skip the browser setup

If you are authorized to capture a public DHL tracking page for a support record or customer workflow, ScreenshotNeo provides a single screenshot request. Its API accepts a URL and returns PNG, JPEG, WebP, or PDF; see the ScreenshotNeo documentation for all options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://www.dhl.de -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://www.dhl.de"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://www.dhl.de' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed; response headers identify the page verdict and billing result. An MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 shots. Use it only for pages and data you are authorized to capture. Create a free ScreenshotNeo account.

Troubleshooting

Symptom Likely cause Fix
401 or 403 Wrong division credential, missing permission, expired token, or unauthorized shipment. Confirm the product, region, account scope, and required business function; rotate the credential if needed.
Too many requests Polling faster than the documented limit. Back off, batch within the product limit, cache unchanged results, or use push events.
No shipment found Number is mistyped, outside the search window, or belongs to another account. Validate the identifier, check the three-month Germany public window, and verify shipment ownership.
Missing location or recipient field Public scope is narrower or a postcode is required. Supply the permitted postcode for a single query or use the authorized business interface.
Webhook retries Receiver did not return HTTP 200 within five seconds. Return immediately after validation and enqueue processing; ensure the certificate is valid.
Browser capture shows a challenge or blank page Bot protection, a failed load, or a page that requires a session. Prefer the authorized DHL API or direct link. If you are authorized to capture the page, inspect ScreenshotNeo’s verdict headers and fix authentication or URL access.

Performance, reliability, and cost

  • Performance: API requests are lighter than launching browsers. Batch only within the documented per-request limit and avoid polling unchanged shipments.
  • Reliability: make consumers idempotent, retry transient network errors with backoff, and record request ids and timestamps without logging secrets.
  • Freshness: polling frequency should match the business need; Unified Tracking Push can reduce repeated requests where supported.
  • Cost: DHL access and quotas are governed by the relevant product agreement. Browser infrastructure adds compute and maintenance cost. ScreenshotNeo bills only clean shots; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed.

FAQ

Is scraping the public DHL tracking website allowed?

The supplied DHL terms prohibit automated access to the Developer Portal and its APIs. They do not establish a general legal conclusion about every public DHL webpage. Use the documented API or direct tracking link and obtain legal guidance for any broader question.

Can I use one DHL API for every country?

No. DHL divisions and regions have separate interfaces and eligibility rules. The Germany mechanics in this guide do not automatically apply elsewhere.

How many Germany tracking numbers fit in one request?

The public query supports up to 15 shipment or reference numbers; the business query supports up to 20 for that business customer.

When should I choose push instead of polling?

Choose Unified Tracking Push when your exact DHL service is supported and you can operate an HTTPS receiver that acknowledges events within five seconds.

Can ScreenshotNeo replace the DHL tracking API?

No. It captures an authorized webpage for a visual record. It does not grant DHL shipment access or replace a service’s API permissions.