A Brisbane skincare and apparel brand ships about 3,000 orders a year into Europe. For years the parcels slid in under the €150 customs exemption, so the only tax question was VAT, and IOSS handled that at checkout. On 1 July 2026 the exemption stopped working. Every distinct product line in every parcel now carries a flat €3 customs duty. For that brand, on a realistic basket mix, the new charge is roughly $23,786 AUD a year, and almost none of it was in anyone’s budget.
This is the article on what the EU €3 duty actually is, how it is counted, who ends up paying it on Shopify, and the catalogue work that decides whether it costs you one line or four. It is written for Australian merchants selling into the EU, and for the developers and agencies who configure the stores. We have kept it to what the primary sources say, and where sources disagree, particularly about a second fee due on 1 November 2026, we say so rather than pick a winner.
It also builds on two earlier Insiteful pieces. Our guide to duties and import taxes on Shopify covers the global picture across the US, EU and UK. This one goes deep on a single rule that now touches every EU order, and on the numbers behind it.
What changed on 1 July 2026, and what is coming next
The Council of the EU agreed on 12 December 2025 to “apply a fixed customs duty of €3 on small parcels valued at less than €150”. The duty applies from 1 July 2026. The Council’s release states that it “will be applied to each different item, according to their tariff headings, contained in a consignment”, and that it covers goods for which non-EU sellers are registered in the import one-stop shop (IOSS), which the Council says accounts for 93 per cent of e-commerce flows into the EU. The measure is temporary: it stays in force until a permanent arrangement agreed in November 2025 takes over, at which point goods under €150 face the normal EU tariff for each product.
Shopify published its own notice on 26 June 2026. It describes the change as a flat €3 per tariff line on qualifying orders up to €150 shipped into the EU from outside it, and says a parcel of only apparel pays €3 while a parcel of apparel, cosmetics, shoes and jewellery pays €12. The notice also says the fee is charged on top of VAT and any national handling fees.
| Date | What happens | Status |
|---|---|---|
| 1 Jul 2026 | Flat €3 customs duty per tariff line on B2C consignments under €150 | In force (Council of the EU, 12 Dec 2025) |
| 1 Nov 2026 | EU customs handling fee, expected to start; amount not set by the Commission as at the sources we read | Unconfirmed amount; trade press floats about €2 |
| 1 Nov 2026 | Product-level identifiers on customs declarations (per one trade source) | Single secondary source; verify with your carrier |
| 2028 | Permanent regime: normal tariffs on goods under €150, €3 interim duty ends | Agreed in principle; trade sources differ on the exact date |
Two cautions about that table. First, the 1 November handling fee is not settled. A September 2026 trade report says the legal basis exists but the amount does not, and that a delegated act is still needed. Another source describes it as roughly €2 per item line, a third as per parcel. Treat any figure as a planning scenario. Second, the permanent regime date appears as March 2028 in one source and 1 July 2028 in another. We will update this post when the delegated acts land.
How the duty is counted: lines, not parcels
The single most expensive misunderstanding we see is that the duty is “€3 per order”. It is not. It is €3 per distinct tariff line in the consignment. Five identical T-shirts are one line and cost €3. A T-shirt and a watch are two lines and cost €6. Shopify’s own example of apparel, cosmetics, shoes and jewellery in one parcel is four lines and €12.

At the exchange rate recorded on 2 October 2026 (1 AUD buys 0.61674 EUR, or about 1.6214 AUD per euro), one line costs $4.86 AUD. That sounds small until you set it against an order value. On a $60 AUD order, one line is 8.1 per cent of the sale. A four-line basket at that value would be 32.4 per cent. The same four lines on a $350 AUD order are 5.6 per cent.
Heading or subheading? The ambiguity that matters
The Council text refers to tariff headings. Shopify’s notice and most trade commentary say tariff lines. In the Harmonised System, a heading is the first four digits and a subheading the first six. Two products can share a heading and still sit on different six-digit subheadings, for example different cosmetics under heading 3304. Which one customs counts depends on how the carrier or customs broker declares the goods. One vendor guide says plainly that grouping “depends on how your carrier or customs broker declares the goods”, and we agree with the caution that you should not assume identical-looking products will always collapse into one charge.
For planning, we use the conservative assumption: count by six-digit subheading, and treat any consolidation into a shared heading as an upside you confirm with your freight forwarder. Our audit script below reports both numbers so you can see the spread.
Who pays: IOSS, DDP and what Shopify does automatically
IOSS settles VAT at checkout. It does not settle customs duty. The Council’s framing is that the duty rides on goods from sellers registered in IOSS, and a separate trade guide says that with IOSS the carrier collects the duty and invoices the merchant, so the customer pays nothing extra on delivery. Without IOSS, the same guide says parcels face delays and customers pay carrier handling fees that are often well above €3. For an Australian brand that wants repeat European customers, the unregistered path is the worse one.
That leaves a commercial decision, not a technical one: who bears the €3. There are three honest answers.
| Approach | What the customer sees | Who funds the duty | Best for |
|---|---|---|---|
| Collect at checkout (DDP) | Duty line in the total; nothing at the door | Customer, upfront | Most brands; lowest abandonment risk at delivery |
| Absorb into price | Higher EU prices, no duty line | You, via margin | Premium brands with room in EU pricing |
| Absorb with a threshold | Duty-free above an order value | You, on large baskets only | Brands that want to lift average order value |
On Shopify, the mechanics depend on which product you use. Shopify’s 26 June notice says that with Managed Markets the €3 is calculated, displayed and collected at checkout, with Global-e as merchant of record remitting the duty, and that duty amounts shown at checkout are guaranteed. For stores using Shopify’s duties and import taxes feature, the notice says the fee is included in the duty amount shown at checkout so you can collect it from the customer with other duties. In both cases Shopify says no settings change is required. The notice does not use the terms DDP or DDU.
Two limits are worth knowing before you rely on that. Shopify’s help page for charging duties at checkout says you need HS codes and a country of origin on products, that your carrier must support DDP labels if you buy labels through Shopify, and that stores using Shopify Fulfillment Network cannot use the feature. It also lists a transaction fee of 0.85 or 1.5 per cent depending on the payment provider, charged even when the calculated duty is zero. The page we read does not state whether Australia is a supported origin for the feature, so confirm that against your own admin before you commit your pricing to it. Our merchant of record guide for Australian stores covers the Managed Markets side of that question.
The AUD model: what the duty costs a real store
A flat fee per line behaves very differently from an ad valorem tariff. It punishes small baskets and multi-category baskets, and it barely registers on a single high-value item. Before you decide who funds it, model your own basket mix. This script does that. The constants at the top are the ones to change: the exchange rate, your order count and your mix of one-line, two-line, three-line and four-line orders.
#!/usr/bin/env python3
"""EU low-value duty model: flat EUR 3 per tariff line, plus an optional handling-fee scenario."""
import sys
DUTY_EUR = 3.00 # Council of the EU, 12 Dec 2025, applies from 1 Jul 2026
AUD_PER_EUR = 1.6214 # exchange-rates.org, 2 Oct 2026 (1 AUD = 0.61674 EUR). Update before use.
HANDLING_EUR = 2.00 # UNOFFICIAL trade-press estimate, per parcel, not confirmed
# share of EU orders by number of distinct tariff lines in the basket (assumption: replace with your data)
MIX = {1: 0.55, 2: 0.30, 3: 0.12, 4: 0.03}
def duty_aud(lines):
return lines * DUTY_EUR * AUD_PER_EUR
def pct_of_order(lines, aov_aud):
return duty_aud(lines) / aov_aud * 100
def annual(orders, mix=MIX, handling=False):
lines = sum(orders * share * n for n, share in mix.items())
eur = lines * DUTY_EUR + (orders * HANDLING_EUR if handling else 0)
return lines, eur, eur * AUD_PER_EUR
if __name__ == "__main__":
orders = int(sys.argv[1]) if len(sys.argv) > 1 else 3000
print(f"EUR {DUTY_EUR:.2f} = ${duty_aud(1):.2f} AUD per line at {AUD_PER_EUR} AUD/EUR")
print()
print("Duty as % of order value (AUD)")
print("AOV 1 line 2 lines 3 lines 4 lines")
for aov in (60, 90, 130, 200, 350):
row = " ".join(f"{pct_of_order(n, aov):5.1f}%" for n in (1, 2, 3, 4))
print(f"${aov:<6} {row}")
print()
lines, eur, aud = annual(orders)
print(f"{orders} EU orders/yr, mix {MIX}")
print(f" tariff lines/yr : {lines:,.0f} (avg {lines/orders:.2f} per order)")
print(f" duty : EUR {eur:,.0f} = ${aud:,.0f} AUD")
lines, eur, aud = annual(orders, handling=True)
print(f" + EUR 2/parcel handling scenario: EUR {eur:,.0f} = ${aud:,.0f} AUD")
Here is the real output for a store with 3,000 EU orders a year and a mix of 55 per cent one-line, 30 per cent two-line, 12 per cent three-line and 3 per cent four-line baskets. That mix is an assumption we chose for illustration, not client data, so replace it with a pull from your own order history.

Three things stand out. A $60 AUD average order is hit hardest, at 8.1 per cent for a single line. The annual figure for 3,000 orders is 4,890 tariff lines, an average of 1.63 per order, which is $23,786 AUD at the €3 rate. And if the unofficial €2 per parcel handling scenario materialises on 1 November, the same store would pay about $33,514 AUD in total. That second number is a scenario, not a forecast, and we flag it as such wherever we show it to a client.
Reading the model into a pricing decision
If your EU average order value sits under $90 AUD, absorbing the duty entirely is hard to justify, because 5 to 11 per cent of revenue is more than most DTC brands net on a repeat order. Collecting at checkout is the default. If your average order sits above $200 AUD, one or two lines cost 2.4 to 4.9 per cent, and absorbing it into EU pricing with a small uplift is realistic. The middle band is where a threshold strategy earns its keep: a “duty-free over $180 AUD” message gives customers a reason to add a third item, and you can check in the model whether the extra line cost is covered by the extra margin.
What we advise against is a blanket price rise to hide the duty. It overcharges single-line buyers, undercharges four-line buyers, and teaches your customers that the price you advertised is not the price they pay.
Catalogue hygiene: where the duty is actually decided
Shopify calculates duties from each product’s HS code and country of origin. Its help page says that without an HS code, duties are calculated from the product description and category instead, and that if a product has no HS code, description or category the result is “likely to be inaccurate”, which can mean extra charges on delivery. The same page notes that countries can extend the six-digit code with their own digits, and that when a country-specific code exists it is the one used.
Shopify lets you set these in four places: when you buy a label, on the product page, in the bulk editor (columns for Harmonized system code and Country of origin), or by CSV from Settings, Taxes and duties. The CSV route is the right one for a catalogue of any size. It uses columns for Product Handle, Variant SKU, option names and values, Country of origin and HS code. You can also set a default country of origin that applies only to products without their own.
We start every EU build with an audit of that file. This script reads the duties CSV, flags missing codes, missing origins and codes shorter than six digits, and reports how many distinct headings and subheadings your catalogue spans.
#!/usr/bin/env python3
"""Audit a Shopify duties CSV for EU per-line exposure.
Usage: python3 hs_line_audit.py products.csv"""
import csv, sys, collections
rows = list(csv.DictReader(open(sys.argv[1], newline="", encoding="utf-8")))
missing_hs = [r["Variant SKU"] for r in rows if not r["HS code"].strip()]
missing_coo = [r["Variant SKU"] for r in rows if not r["Country of origin"].strip()]
short = [r["Variant SKU"] for r in rows if r["HS code"].strip() and len(r["HS code"].strip()) < 6]
def key(r, n):
return r["HS code"].strip()[:n]
heads = collections.defaultdict(set) # 4 digit heading -> handles
subs = collections.defaultdict(set) # 6 digit subheading -> handles
for r in rows:
if r["HS code"].strip():
heads[key(r, 4)].add(r["Handle"])
if len(r["HS code"].strip()) >= 6:
subs[key(r, 6)].add(r["Handle"])
print(f"variants: {len(rows)} products: {len({r['Handle'] for r in rows})}")
print(f"missing HS code : {len(missing_hs)} {missing_hs}")
print(f"missing origin : {len(missing_coo)} {missing_coo}")
print(f"code under 6 digits : {len(short)} {short}")
print(f"distinct headings (4-digit) : {len(heads)}")
print(f"distinct subheadings (6-digit) : {len(subs)}")
for h, hs in sorted(heads.items()):
if len(hs) > 1:
print(f" heading {h} spans {len(hs)} products: {sorted(hs)}")
Here is the real output on a twelve-variant sample catalogue we built for the purpose. It is synthetic, so the product names are illustrative, but the checks are the ones we run on live client files.

The sample shows the typical shape of a problem file. Two variants have no HS code, one of them a gift card that needs a deliberate decision rather than a blank. Four codes are four digits long, which is a heading, not a subheading, and will not give a reliable duty. A lip balm and a sunscreen share heading 3304 but sit on different subheadings, which is exactly the case where the carrier’s declaration decides whether you pay one line or two. In a real catalogue we usually find the missing-code problem concentrated in newer products and bundles, because they were created after the original import.
One more caution. If you have activated Managed Markets, Shopify’s help page says HS codes are assigned automatically and the code you entered may not be the one used. You can compare the two on each product under the Managed Markets codes option. That is worth a quick review, because the count of tariff lines is only as good as the codes behind it.
Lowering the line count without bending the rules
Merchants ask whether they can restructure products to reduce lines. Some changes are legitimate and some are not, and the difference is whether the classification stays truthful. We do not advise misclassifying goods to share a heading. Penalties for inaccurate customs data are real, and Shopify’s own help page warns that incorrect codes can cause border delays, seizure of products or denial of import. The legitimate levers are commercial, not creative.
| Lever | How it lowers line cost | Risk |
|---|---|---|
| Same-category bundles | Encourage multiples of one product type, which stay one line | None, if the bundle is truthfully the same category |
| Free-shipping or duty threshold | Lifts basket value so the flat fee is a smaller share | Margin on the extra items must cover the absorbed duty |
| Range design | Fewer one-off categories in the EU assortment | Lost range appeal in the EU market |
| Ship from an EU location | Orders shipped from a fulfilment location inside the EU are not cross-border imports | Inventory and 3PL cost; see our cross-border returns guide for the operational side |
| Raise EU prices on small baskets | Protects margin where the fee bites hardest | Can hurt conversion; test by market |
The EU-based fulfilment point deserves a clear statement. Shopify’s help page says orders shipped from regions where you have a fulfilment location are not affected by the duties-at-checkout settings. A brand with enough EU volume may find that a European 3PL changes the economics entirely, because the goods enter the EU in bulk and the per-parcel duty is replaced by an import cost on the pallet. That is a freight and compliance question to settle with a broker, not a theme setting.
The 1 November changes: product identifiers and the handling fee
There are two things to plan for on 1 November, and neither is as certain as the 1 July duty.
The first is the customs handling fee. The Council’s position, signed off on 3 September 2026 according to one trade report, includes a handling fee to be introduced no later than 1 November 2026, at a level the Commission has yet to set. The report says liability sits with the platform or distance seller as the deemed importer, not the consumer. Another source, dated 19 September 2026, says the legal basis is in the Customs Code but the amount needs a delegated act and that revenue allocation between member states is disputed. We model about €2 as a scenario because it is the figure in circulation, and we label it unofficial.
The second is product-level data on customs declarations. One trade source describes three identifiers per declared item: a mandatory seller product code (typically your SKU), a mandatory unique manufacturer or supplier reference, and a third identifier required only when available, such as a GTIN, EAN or UPC. The same source says shipments with missing or inaccurate data may be held or refused entry. This is a single secondary source, so confirm the final requirement with your carrier before you build anything against it. The preparatory work is cheap and useful either way: make sure every variant has a unique SKU, a barcode where one exists, and a supplier reference stored somewhere you can export.
In Shopify terms that means SKU and barcode fields filled on every variant, and a metafield for the supplier or manufacturer reference if you do not already carry one. Our team treats those three fields as part of the catalogue standard on any store that exports to the EU, because customs data and marketplace feeds both want the same identifiers.
How we do it at Insiteful
When an Australian merchant asks us to get an EU storefront ready, the duty work is a defined sequence rather than a settings tick. We start with the order history, not the theme. We pull twelve months of EU and prospective EU orders, count distinct product types per basket, and run the model above with the merchant’s own mix. That gives a dollar figure in AUD that the founder can react to before anyone discusses configuration.
Next we audit the duties CSV with the script in this article and fix the file with the merchant’s buyer or a customs broker. We never guess HS codes for a client. A broker confirms the classification, we load it through the Taxes and duties CSV import, and we set a default country of origin as a backstop only. Then we test checkout in the Shopify admin with real baskets from each category combination, comparing the duty line shown to the customer with the line count we expected.
The commercial decision comes last: collect at checkout, absorb, or absorb above a threshold. We build the EU market pricing, the cart messaging and any threshold banner to match, and we write the decision down so the next person to touch pricing knows why EU prices look the way they do. The checklist below is the version we hand to merchants. We rerun the audit when the 1 November rules and the delegated acts are published, because the numbers in this article will move.
Checklist before you sell into the EU
| # | Check | Pass condition |
|---|---|---|
| 1 | IOSS registration decided | Registered, or a documented reason why not |
| 2 | Basket mix modelled in AUD | Annual duty cost known for 1-line to 4-line baskets |
| 3 | HS code on every physical variant | Six digits or more, broker-confirmed |
| 4 | Country of origin on every variant | Set per product, default as backstop only |
| 5 | Duty collection method chosen | Checkout, absorbed or threshold, written down |
| 6 | Origin support confirmed in admin | Duties at checkout available for Australian origin |
| 7 | Test baskets run | Duty shown equals expected line count |
| 8 | SKU, barcode and supplier reference present | Ready for 1 November product-level data |
| 9 | Handling fee scenario priced | Margin survives an extra €2 per parcel |
Most catalogues we review fail items 3 and 8 on the first pass. Both are a few days of tidy-up work, and both are far cheaper than discovering them from a customer who was charged at the door.
A note on scope: this article is general information about ecommerce configuration, not tax or customs advice. Classification and liability for customs duty belong with a licensed customs broker or your accountant.
Want your EU launch priced and configured properly?
If you sell into Europe from Australia, or you are about to, we can model your EU basket mix, audit your HS codes and build the duty and pricing setup into your store. See how our build assessment works on the Insiteful process page and book yours.
Sources
- Council of the EU: Customs, Council agrees to levy customs duty on small parcels as of 1 July 2026 (12 Dec 2025)
- Shopify changelog: New €3 EU import customs duty arrives July 1 (26 Jun 2026)
- Shopify Help Center: Collecting international duties and import taxes at checkout
- Shopify Help Center: Adding HS codes to your products
- Sufio: The EU’s new €3 customs fee for non-EU Shopify stores (vendor guide)
- EAS: EU Customs and VAT overhaul, small parcel duty 2026 (vendor guide)
- VATCalc: EU customs handling fee, November 2026 (19 Sep 2026)
- Cleo Labs: EU Council sign-off on the customs overhaul and the unpriced second parcel fee
- Landmark Global: EU customs reform, B2C import rules for November 2026
- Exchange-Rates.org: AUD to EUR history, 2 October 2026