Last updated: June 2026.
Here is the thing nobody tells you before you set out to "add DHL to PrestaShop": DHL, DPD and UPS are not three versions of the same job. One of them is a single global company with one API. The other two are federations of national branches that share a logo and almost nothing else. The DHL module that prints labels in Germany has no idea what to do with a French address, and the DPD account that works in Poland is useless in France. Pick the wrong integration path and you discover this after you've configured everything, when a real order to the wrong country bounces. This guide is about getting these three specific carriers wired into a PrestaShop store correctly. Which module to install, where the settings actually live in the back office, and the fragmentation traps that turn a one-afternoon job into a three-week one.
It is deliberately not a guide to shipping zones, rate tables or free-shipping thresholds, that's a separate problem with its own deep treatment. If you haven't laid the foundation yet, start with our complete PrestaShop shipping configuration guide and the mechanics of setting up carrier modules step by step. This page assumes those basics are in place and focuses on the three carriers themselves.
How PrestaShop sees a carrier in the first place

Before you touch a single carrier module, it helps to know what you're actually creating. In PrestaShop a "carrier" is a row in the ps_carrier table, managed under Shipping → Carriers in the back office. Each carrier carries a delivery method (price-based or weight-based), a tracking-URL template, a tax rule, and an assignment to one or more zones (zones themselves live under International → Locations → Zones, and you attach them to a carrier under Shipping → Carriers). A carrier module (the DHL, DPD or UPS plugin) does one of two things on top of that: it either creates and manages those carrier rows for you, or it registers itself as a real-time rate provider through PrestaShop's carrier-module shipping-cost methods (the module's own getOrderShippingCost() / external shipping-cost logic) so the price comes back live from the carrier's servers instead of from a table you typed in by hand. Checkout display hooks like displayCarrierExtraContent only add extra UI such as a pickup-point selector. They are not where the live price itself is calculated.
That distinction, label-and-fulfilment module versus live-rate module, matters more than the carrier brand. A label module makes your warehouse faster (it prints the right sticker and writes the tracking number back to the order). A live-rate module makes your checkout accurate (the customer sees the real cost for their address). Many merchants install one expecting the other and are confused when checkout still shows their old flat rate. Know which problem you're solving before you start.
The three carriers, and what changes for PrestaShop
| Carrier | Structure | PrestaShop reality | Strongest for |
|---|---|---|---|
| UPS | Single global company, one unified REST API | The cleanest integration of the three. One module, one set of API credentials and a comparatively unified API and account model, though available services and rates still depend on your shipper account, origin country and module | Transatlantic, B2B, high-value parcels where tracking reliability matters |
| DHL | Several distinct businesses under one brand (DHL Paket, DHL Express, DHL eCommerce) | Module depends on which DHL you actually have a contract with, they don't interchange | Domestic Germany (Paket), worldwide express (Express) |
| DPD | Federation of independent national branches | The DPD Germany module won't serve DPD France; multi-country DPD often means multiple modules or one API-based third-party module | EU cross-border ground, pickup-point delivery |
So what does that mean when you sit down to configure? With UPS you connect one account and you're broadly done. With DHL you first have to identify which DHL product your contract is for, a German store shipping domestically wants DHL Paket; a store shipping worldwide express wants DHL Express; these are different modules with different credentials. With DPD you have to map your shipping countries to the right national branch and accept that a genuinely multi-country DPD setup is the hardest of the three to keep tidy.
DHL: which "DHL" do you actually mean?
The single most common DHL mistake on PrestaShop is installing the wrong product's module. There are three DHL businesses a merchant runs into:
- DHL Paket, domestic German parcels, 1–2 days. This is the one most German stores want. The official module handles label generation and writes tracking numbers back onto the order. It talks to DHL's business-customer portal (Geschäftskundenportal) and needs your business-customer (GKP) credentials. It is excellent for domestic Germany and limited for anything else.
- DHL Express, worldwide express, 1–3 days, with a proper real-time rating API and customs-document handling. This is the module you want if international express is your business, but it is a different module with different credentials, not a setting inside the Paket module.
- DHL eCommerce. Cost-optimised international for lighter parcels. Rate behaviour depends heavily on your contract terms.
Practically: in Shipping → Carriers after installing the DHL module you'll get one or more carrier rows. Set the tracking URL on each to DHL's pattern: https://www.dhl.com/global-en/home/tracking.html?tracking-id=@, where PrestaShop's @ token is replaced by the order's tracking number at send time. Confirm the carrier is attached to the zones you actually ship to under Shipping → Carriers (the zones themselves are defined under International → Locations → Zones), because a freshly created carrier defaults can leave whole regions uncovered and the carrier silently won't appear at checkout for those addresses.
DPD: the federation problem, and how to dodge it
DPD's national branches operate independently, and that bleeds straight into PrestaShop. DPD Germany, DPD France and DPD Poland each have their own modules with their own feature sets and their own API endpoints. If you ship from one country to customers in that same country, pick that country's module and you're fine. The pain starts when you ship DPD across borders from multiple origins or want one unified label workflow across countries, the official per-branch modules simply weren't built to cooperate.
There are two clean ways out. The first is DPD Web Services, DPD's own API, which requires a business contract and API credentials and gives you a more uniform programmatic interface than the per-country plugins. The second is a third-party multi-branch module that sits on top of those web services and presents a single configuration screen. Either way, the decision to make early is: am I a single-branch DPD shipper (use the official national module) or a multi-branch one (budget for the API route)? Deciding that on day one saves you from installing three modules that fight over the same carrier rows.
DPD's tracking template for PrestaShop is https://tracking.dpd.de/status/en_US/parcel/@ for the German branch; other branches use their own tracking hosts, which is one more reason multi-branch DPD needs deliberate setup rather than copy-paste. DPD's Predict service (the one-hour delivery window and proactive notifications) is a genuine reason customers like DPD, if your module exposes it, it's worth surfacing at checkout.
UPS: the straightforward one
UPS is the path of least resistance precisely because it's one company with one API. The UPS module connects with a single set of API credentials and can do real-time rating for every service level (UPS Standard, Express Saver, Express) at checkout, generate labels (PDF or ZPL for thermal printers), and pull tracking worldwide. It is more unified than DHL or DPD, but the exact services, negotiated rates and enabled features still depend on your shipper account, origin country and the module you run. Its tracking URL pattern in Shipping → Carriers is https://www.ups.com/track?tracknum=@.
The trade-off isn't integration difficulty, it's price: UPS typically costs more than DHL or DPD for standard intra-European ground parcels. Where it earns that premium is transatlantic shipping (the strongest US network of the three), B2B, and high-value goods where tracking granularity and reliability are worth paying for. If your catalogue is domestic-EU and price-sensitive, UPS is often the express/premium option you offer alongside a cheaper carrier rather than your default.
Live rates vs. rate tables: the checkout-speed decision
Real-time rating, querying the carrier's servers at checkout so the customer sees the exact cost for their address, weight and dimensions, is the most-requested feature and the one most likely to slow your checkout to a crawl. Each carrier API call typically takes one to three seconds. Query all three live at once and your delivery step can sit blank for the better part of ten seconds while the customer wonders whether the page broke. PrestaShop runs these calls server-side during the delivery step of the order controller, so the customer feels every one of them.
How the three behave:
- UPS. The most mature live-rating API; reliable real-time quotes across services, well worth it for international where the cost genuinely varies by destination.
- DHL. DHL Express rates live cleanly through its API; DHL Paket is domestic and zone/weight-predictable enough that a rate table is usually fine and faster.
- DPD. Live rating is the least standardised; many DPD merchants deliberately use PrestaShop's own weight- or price-based rate tables (Shipping → Carriers → Shipping locations and costs) rather than fight the API.
The pragmatic pattern most stores land on is a hybrid: live rates only where they pay off (international, where being wrong is expensive), and a maintained rate table for predictable domestic shipping. The deeper question of which pricing model to charge customers at all, live-calculated, flat, or free above a threshold, is its own decision, covered in free vs flat-rate vs calculated shipping.
Labels and warehouse flow
For any store shipping more than a handful of orders a day, label generation is where a carrier module earns its keep. All three carriers can produce labels in PDF for A4/A6 printers and in ZPL for thermal label printers, which is the format you want once volume justifies a dedicated label printer. DHL Paket integrates with the German business-customer portal for bulk label runs; DPD labels come through Web Services or its MyShipping portal (and bulk printing sometimes routes through DPD's own tool rather than directly from PrestaShop); UPS produces labels straight from the module and offers WorldShip for high-volume desktop workflows. When you move an order to a shipped status and a tracking number is present, the customer receives the tracking email only if that order status is configured to send an email and uses a template that includes the tracking link (built from the template you set on the carrier), so the label step and the customer-notification step are linked, but only when the status is set up to notify.
If keeping customers informed after dispatch is the part you care most about, the notification and tracking-link side of this has its own playbook in tracking numbers and delivery notifications.
The mistakes that cost real money
Two of these silently drain margin, so they're worth more than a bullet:
- Inaccurate product weights and dimensions. Every live rate is only as good as the weight and dimension fields on your products (Catalog → Products → Shipping tab). Missing or guessed weights mean you either undercharge, eating the difference on every parcel, or overcharge and lose the order at checkout. This is unglamorous catalogue hygiene, and it's the single highest-impact fix for shipping-cost accuracy.
- Ignoring dimensional weight. All three carriers bill bulky-but-light parcels on volumetric (DIM) weight, not actual weight. A 500 g cushion in a 40×40×20 cm box is charged like several kilos. If you sell bulky light goods and your module isn't fed dimensions, you'll undercharge on every single one, a slow leak that only shows up when you reconcile the carrier invoice.
- Hard-coding rates and never revisiting them. A rate table you typed in 2024 is wrong the moment the carrier publishes new rate cards (which happens at least yearly). Either rate live, or diarise a review every time the carrier updates its tariffs.
- Not test-driving the checkout per zone. After setup, place test orders to a domestic, an EU and a non-EU address and confirm the right carriers appear at the right prices. A carrier missing from a zone, or appearing with a nonsense price, is invisible until a customer hits it.
Which carrier for which job
There is no single "best" carrier. The honest answer is that most growing European stores end up offering two or three and letting the customer choose a budget, a standard and an express option. As a starting map:
| Shipping job | Usual first choice | Why |
|---|---|---|
| Domestic Germany | DHL Paket | Cheapest and most trusted at home; clean official module |
| EU cross-border ground | DPD Classic | Often the lowest cross-border ground price |
| Worldwide express | DHL Express or UPS | Both have real express networks and live rating |
| Transatlantic / US | UPS | Strongest US network and tracking reliability |
| High-value / B2B | UPS | Tracking granularity worth the premium |
Several markets are better served by a national champion than by any of these three, and forcing DHL/DPD/UPS where a local carrier dominates costs you conversions. For those, see the dedicated guides: Colissimo for France, InPost Paczkomaty for Poland, Mondial Relay relay-point delivery, and GLS for multi-country shipping. And if you're shipping from more than one origin, carrier choice intertwines with stock location, that's multi-warehouse management.
When the default carrier system isn't enough
PrestaShop's native carrier system handles zones, rate tables, tracking templates and the standard per-carrier modules well. Where it runs out of room is the logic around the carriers: conditionally hiding a carrier for certain products or cart contents, comparing live rates from several carriers and showing only the cheapest, or applying custom rules like "free DPD over €80 but UPS always paid." That's the gap our mypresta.rocks shipping modules are built to fill, extending the carrier display and rule logic from the back office without core edits, so the customisation survives your next PrestaShop upgrade instead of breaking with it. The benefit is concrete: the right carriers appear for the right orders at the right price, automatically, without you maintaining a tangle of rules by hand.
The order to do this in: get one carrier, the one that covers your primary market, fully working and tested end to end (checkout price, label, tracking email) before you add a second. A single carrier configured perfectly beats three configured half-way, and once the first one is solid the rest follow the same pattern. If speed expectations are part of your offer, decide what you can actually promise before you advertise it, same-day and next-day delivery for small stores and setting realistic delivery dates keep that promise honest.
Frequently asked questions
I installed the DHL module but checkout still shows my old flat rate, why?
You almost certainly installed a label-and-fulfilment module when you wanted a live-rate one. A label module makes your warehouse faster, it prints the right sticker and writes the tracking number back to the order, but it doesn't quote prices at checkout; the customer still sees whatever rate table you typed in. A live-rate module queries the carrier's servers during the delivery step so the price reflects the real address and weight. Confirm which job your module does before assuming it's broken: many merchants install one expecting the other.
The DPD module that works in Germany won't ship from France. Is that a bug?
No, it's the federation. DPD is a group of independent national branches, and DPD Germany, DPD France and DPD Poland each have their own modules, feature sets and API endpoints, they weren't built to cooperate. If you ship from a single country, install that country's official module and you're fine. If you ship cross-border from multiple origins, budget for the API route instead: DPD Web Services (their own API, behind a business contract) or a third-party multi-branch module that sits on top of it and presents one configuration screen.
What tracking URL do I put on the carrier in PrestaShop?
Each carrier row in Shipping → Carriers takes a tracking-URL template with PrestaShop's @ token, which is replaced by the order's tracking number at send time. The patterns are: DHL, https://www.dhl.com/global-en/home/tracking.html?tracking-id=@; DPD Germany, https://tracking.dpd.de/status/en_US/parcel/@ (other DPD branches use their own tracking hosts); UPS, https://www.ups.com/track?tracknum=@. The tracking email only goes out if the order status that sets "shipped" is configured to send mail and its template includes the tracking link.
Why is my checkout slow when I enable live rates?
Each carrier API call typically takes one to three seconds, and PrestaShop runs them server-side during the delivery step, so the customer feels every one. Query all three carriers live at once and the delivery step can sit blank for the better part of ten seconds. The pragmatic fix most stores land on is a hybrid: live rates only where they pay off (international, where being wrong is expensive) and a maintained weight- or price-based rate table for predictable domestic shipping, which is both faster and one fewer API to depend on.
I keep undercharging on bulky parcels. What am I missing?
Dimensional (volumetric) weight. All three carriers bill bulky-but-light parcels on DIM weight, not actual weight. A 500 g cushion in a 40×40×20 cm box is charged like several kilos. If your products have no dimensions set, your live rates are computed on actual weight alone and you eat the difference on every parcel. Fill in both weight and dimensions on the Catalog → Products → Shipping tab; it's unglamorous catalogue hygiene but the single highest-impact fix for shipping-cost accuracy.
Which of the three should I start with?
Whichever covers your primary market, and only that one to begin with. Get a single carrier fully working and tested end to end, checkout price, label, tracking email, before adding a second. A starting map: DHL Paket for domestic Germany, DPD for EU cross-border ground, DHL Express or UPS for worldwide express, and UPS for transatlantic, B2B and high-value parcels where tracking reliability earns its premium. One carrier configured perfectly beats three configured half-way.