DHL Parcel Prices Scraper
Pricing
from $5.95 / 1,000 results
DHL Parcel Prices Scraper
Scrape DHL Germany parcel and packet list prices from dhl.de page URLs: product, price in EUR, max weight and dimensions, tracking and liability flags and order link. The default page gives 7 domestic products; the international price page adds destination and zone.
Pricing
from $5.95 / 1,000 results
Rating
0.0
(0)
Developer
Axiom Works
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Returns: one row per DHL product offer with productId, title, priceEur, isFromPrice, maxWeightKg, maxDimensionsCm, category, sourceUrl.
Input: {"startUrls": [{"url": "https://www.dhl.de/de/privatkunden.html"}], "maxItems": 20}
Best for: DHL price monitoring, carrier price comparison, shipping cost spreadsheets.
{"id": "PAECKS","productId": "PAECKS","title": "2 kg - Päckchen S","priceEur": 4.19,"isFromPrice": false,"maxWeightKg": 2,"category": "packet","sourceUrl": "https://www.dhl.de/de/privatkunden.html"}
What does DHL Parcel Prices Scraper do?
This DHL scraper provides structured records for workflows that need a DHL API for public catalogue prices. DHL Parcel Prices Scraper reads the parcel and packet prices that DHL publishes on dhl.de and returns them as structured records. Each record is one product offer, for example "2 kg - Paket" at 6.19 EUR, together with its weight limit, its maximum dimensions and whether liability and tracking are included.
You can use it to:
- Track DHL list prices over time by running it on a schedule and comparing datasets.
- Compare DHL domestic list prices with the prices of other carriers.
- Feed a price table, spreadsheet or dashboard without copying numbers by hand.
- Check which products carry liability and tracking and which do not.
The Actor reads public pages only. It does not log in, it does not solve CAPTCHAs, and it scrapes only www.dhl.de. Only if the parser cannot read a value, text from that card may also be sent to a third-party AI processor (TypeSafe AI) to pick it (see the FAQ). By default it reads the private-customer home page, which lists seven domestic products. It can also read the international price page, where each row is a product and price zone, and it follows links from an overview page to the price pages it links to when the start page itself shows no prices.
Offers that appear more than once on a page, for example in a desktop and a mobile layout, are returned once. Every record has a stable id, so ids never repeat within a run.
This is an independent tool. It is not affiliated with or endorsed by DHL.
What data can you get?
Each dataset item is one product offer. Fields that a page does not show are null instead of being guessed.
| Field | Type | Description |
|---|---|---|
id | string | Stable id: the product id, plus the destination country for international offers, e.g. PAK02 or PAK02-AUT. |
productId | string | DHL product id taken from the offer's order link, e.g. PAK02. |
title | string | Product name as shown on the page, e.g. 2 kg - Paket. |
priceEur | number | List price in EUR, e.g. 6.19. |
isFromPrice | boolean | true when the page shows the price as "ab ..." (from). |
maxWeightKg | number or null | Maximum weight in kilograms, e.g. 31.5. |
maxDimensionsCm | string or null | Maximum dimensions in centimetres, e.g. 120 x 60 x 60 cm. |
liabilityIncluded | boolean or null | Whether liability is included. null if the page does not say. |
trackingIncluded | boolean or null | Whether tracking is included. null if the page does not say. |
destinationCountry | string or null | Destination country code from the order link. Only set on the international price page. |
destinationZone | string or null | Price zone heading the offer is listed under. Only set on the international price page. |
orderUrl | string or null | The page's online-franking link for the offer. |
pricePerKgEur | number or null | priceEur divided by maxWeightKg, rounded to cents; null when no weight is in the product name. |
category | string or null | packet, parcel or letter, derived from the product name (Päckchen = packet, Paket = parcel). null if the name is unclear. |
sourceUrl | string | The page the record came from. |
scrapedAt | string | ISO timestamp of when the record was created. |
rawText | string | Only when includeRawText is on: the card or table-row text the values were read from. |
How to use
- Open the Actor in Apify Console and go to the Input tab.
- Leave the start URL as the private-customer home page, or paste one or more
dhl.depage URLs that list parcel or packet prices. - Set the maximum number of records you want.
- Click Start. The run normally finishes within a minute, because it fetches only a few pages.
- Open the Output tab to view the table, or download it as JSON, CSV or Excel.
To monitor prices, create a schedule for the Actor (daily or weekly is enough, since list prices change rarely) and compare each run's dataset with the previous one, for example by id and priceEur.
If you give a page that shows no prices itself, such as a "send parcels" overview, the Actor reads the price pages that page links to. In that case sourceUrl on each record names the page the price was actually read from.
Input
| Field | Type | Description |
|---|---|---|
startUrls | array | dhl.de pages that list parcel or packet prices. Default https://www.dhl.de/de/privatkunden.html returns the 7 domestic products. For prices per destination country use https://www.dhl.de/de/privatkunden/pakete-versenden/weltweit-versenden/preise-international.html (ids like PAK02-AUT). Overview pages without prices are followed to the price pages they link. Only dhl.de and www.dhl.de URLs are accepted. |
maxItems | integer | Shared limit across all URLs, after filters and duplicate removal. 1-500 recommended; default 50, prefilled with 20. Stops at this count when enough matching offers exist. |
categories | array | Only return these categories: packet, parcel, letter. Empty returns all. |
destinationCountries | array | Country codes from international order links, e.g. ["AUT","FRA"], ignoring case. Use an international price URL: domestic records have no country and cannot match. Default [] keeps all. |
maxPriceEur | number | Nonnegative ceiling, e.g. 10; omit for no ceiling. Combined with all other filters. A ceiling below every published offer returns zero records successfully. |
includeRawText | boolean | Set true to add the visible card or row text as rawText. Default false omits it. |
proxyConfiguration | object | Connection settings, e.g. {"useApifyProxy":false} (default). Blocked requests retry with fresh proxy sessions when available. |
Example input:
{"startUrls": [{ "url": "https://www.dhl.de/de/privatkunden.html" }],"maxItems": 20,"includeRawText": false}
The optional proxyConfiguration field defaults to a direct connection. If dhl.de answers 403, 429 or a 5xx error, the Actor retries with backoff on Apify datacenter proxy and then on residential proxy.
All filters apply together. If a run succeeds with no matching offers, remove categories, destinationCountries or maxPriceEur to broaden the request. The final status explains this. An unavailable page is skipped; other supplied URLs still run. The same-language homepage fallback remains available when at least one supplied page loads but produces no matching records. If every supplied target is unavailable, the run succeeds with zero items and a status message explaining which URLs to check. An unavailable URL never causes unrelated homepage offers to be returned on its own.
Invalid input stops the run straight away with a clear error message. This covers an empty startUrls list, a URL that is not on dhl.de, and a maxItems that is not a positive integer.
Output
The output below comes from a local run on 14 October 2026 with the prefill input. The private-customer home page listed 13 offers including duplicates, and the Actor returned 7 unique records. The first record:
{"id": "PAECKS","productId": "PAECKS","title": "2 kg - Päckchen S","priceEur": 4.19,"isFromPrice": false,"maxWeightKg": 2,"pricePerKgEur": 2.1,"maxDimensionsCm": "35 x 25 x 10 cm","liabilityIncluded": false,"trackingIncluded": false,"destinationCountry": null,"destinationZone": null,"orderUrl": "https://www.dhl.de/int-versenden/gw/rest/init?domain=de&force=true&shoppingcart.items.0.product.id=PAECKS&shoppingcart.items.0.type=ShipmentItem&tid=hp-teaser-minimodul-paecks","category": "packet","sourceUrl": "https://www.dhl.de/de/privatkunden.html","scrapedAt": "2026-10-14T05:01:50.051Z"}
All seven records from that run, in summary:
| id | title | priceEur | maxWeightKg | maxDimensionsCm | liability | tracking |
|---|---|---|---|---|---|---|
PAECKS | 2 kg - Päckchen S | 4.19 | 2 | 35 x 25 x 10 cm | false | false |
PAECK | 2 kg - Päckchen M | 5.19 | 2 | 60 x 30 x 15 cm | false | false |
PAK02 | 2 kg - Paket | 6.19 | 2 | 60 x 30 x 15 cm | true | true |
PAK05 | 5 kg - Paket | 7.69 | 5 | 120 x 60 x 60 cm | true | true |
PAK10 | 10 kg - Paket | 10.49 | 10 | 120 x 60 x 60 cm | true | true |
PAK20 | 20 kg - Paket | 18.99 | 20 | 120 x 60 x 60 cm | true | true |
PAK31 | 31,5 kg - Paket | 23.99 | 31.5 | 120 x 60 x 60 cm | true | true |
category is derived from the product name, so it is filled for every record above. Prices are the list prices shown on the website at the time of the run and may differ from what you pay at checkout or under a business contract.
How much does it cost?
The Actor uses pay-per-event pricing: you are charged per result, meaning one charge for each record pushed to the dataset. There is no extra charge for category, because it is derived from the product name. See the Pricing tab of the Actor for the current rates. Compute and proxy costs are included in the event price. A default run reads a single page and returns seven records, so it is small.
Use with AI agents (MCP)
You can call this Actor from an AI assistant through the Apify MCP server. Add it to your MCP client configuration with the Actor selected by the tools parameter:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com/?tools=axiomworks/dhl-parcel-prices-scraper"}}}
- "Get the current DHL Germany parcel prices and tell me which product is cheapest for a 5 kg parcel."
- "List all DHL products from the private-customer page that include tracking and liability."
- "Fetch the DHL international price page and show the price for Austria."
When asking an agent for Austria offers, supply the international price page and destinationCountries: ["AUT"]. Keep maxItems large enough to include the matching products. A small limit selects the first matching offers in page order; it does not select the cheapest or best shipment service. Use maxWeightKg, maxDimensionsCm and the feature flags in the returned records to make that comparison.
Integrations and API
You can start the Actor from code, and connect it to schedules, webhooks and Apify integrations such as Google Sheets, Make, Zapier or n8n. Set your own API token in the APIFY_TOKEN environment variable.
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('axiomworks/dhl-parcel-prices-scraper').call({startUrls: [{ url: 'https://www.dhl.de/de/privatkunden.html' }],maxItems: 20,});const { items } = await client.dataset(run.defaultDatasetId).listItems();// Inspect items or pass them to your application.
Python
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("axiomworks/dhl-parcel-prices-scraper").call(run_input={"startUrls": [{"url": "https://www.dhl.de/de/privatkunden.html"}],"maxItems": 20,})items = client.dataset(run["defaultDatasetId"]).list_items().itemsprint(items)
cURL
curl -X POST "https://api.apify.com/v2/acts/axiomworks~dhl-parcel-prices-scraper/run-sync-get-dataset-items" \-H "Authorization: Bearer $APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"startUrls":[{"url":"https://www.dhl.de/de/privatkunden.html"}],"maxItems":20}'
FAQ
Where does category come from?
It is derived in code from the product name: names with "Päckchen" give packet, "Paket" gives parcel, and letter products give letter. No AI is involved and nothing extra is charged.
Does the Actor use AI? Only as a fallback. If the normal parser cannot read a product id, title or price from a card, the Actor may send the candidate text spans from that card to a third-party AI processor (Jev by TypeSafe AI) to pick the right one. This only happens when such a value is missing, is capped per run and is not charged separately.
Which pages can I scrape?
Pages on dhl.de or www.dhl.de that show parcel or packet prices: the private-customer home page and the national and international price pages, in German or English. URLs on other hosts are rejected.
Why did I get fewer records than maxItems?
maxItems is an upper limit. The private-customer home page lists seven distinct products, so a run with only that page returns seven records even if you ask for 20.
Why is liabilityIncluded or trackingIncluded false or null?
false means the page lists the product without that feature (the Päckchen products in the output above). null means the page does not say either way.
Why is destinationCountry empty?
It is only set on the international price page, where offers are listed per destination country and price zone. Domestic offers have null there.
Are these the price I will pay? No. They are list prices as displayed on the website. They are not a complete rate table and do not include business contract prices or surcharges.
A run failed. What should I check?
Read the error in the run log. Invalid input, such as an empty URL list or a non-dhl.de URL, stops the run immediately with a message. A valid request with no matching offers succeeds with an empty dataset and a status message explaining which URLs or filters to change. Unavailable targets are logged and skipped. If the site changes its layout, report it through the Issues tab with the input and run link.
Is it legal to scrape DHL Germany?
The Actor collects only publicly visible price information that loads without logging in, and it does not collect personal data. It requests few pages at a modest rate. Laws and site terms differ by country and use case, and the site's terms may restrict automated access or commercial reuse, so check them and take your own legal advice before using the data commercially. This is not legal advice.
Feedback
If you find a bug, a page that returns no prices, or a field you would like added, open an issue from the Actor's Issues tab in Apify Console. Include the run link and the input you used so the problem can be reproduced.