universal-parcel-scraper 0.4.0-main.319 → 0.5.0-main.321

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,7 +15,7 @@ The engine behind [Peek](https://peektracker.com) ([GitHub](https://github.com/p
15
15
  <!-- GENERATED:summary -->
16
16
  **3,500+ carriers** through **85 dedicated adapters** and **5 universal fallbacks**
17
17
 
18
- <sub>105 catalog entries · 58 countries represented</sub>
18
+ <sub>106 catalog entries · 58 countries represented</sub>
19
19
  <!-- /GENERATED:summary -->
20
20
 
21
21
  [Try it](#try-it) · [Ways to run it](#ways-to-run-it) · [Benchmark](#benchmark) · [Carriers](carriers/) · [Add a carrier](CONTRIBUTING.md)
package/data/catalog.json CHANGED
@@ -193,7 +193,12 @@
193
193
  ]
194
194
  }
195
195
  ],
196
- "detectionRules": []
196
+ "detectionRules": [
197
+ {
198
+ "pattern": "^DOFR\\d{13}HD$",
199
+ "confidence": "high"
200
+ }
201
+ ]
197
202
  },
198
203
  "sunyou": {
199
204
  "displayName": "SunYou",
@@ -463,7 +468,8 @@
463
468
  "timezone": "UTC",
464
469
  "tracking": {
465
470
  "mode": "automatic",
466
- "adapter": "dhl-ecommerce"
471
+ "adapter": "dhl-ecommerce",
472
+ "recognitionRank": 23
467
473
  },
468
474
  "canaryUrl": "https://www.dhl.com/ch-en/home/tracking.html",
469
475
  "trackingUrlTemplate": "https://www.dhl.com/ch-en/home/tracking.html?tracking-id={trackingNumber}&submit=1",
@@ -1968,7 +1974,8 @@
1968
1974
  "timezone": "Europe/Helsinki",
1969
1975
  "tracking": {
1970
1976
  "mode": "automatic",
1971
- "adapter": "posti"
1977
+ "adapter": "posti",
1978
+ "recognitionRank": 27
1972
1979
  },
1973
1980
  "canaryUrl": "https://www.posti.fi/en/tracking",
1974
1981
  "trackingUrlTemplate": "https://www.posti.fi/en/tracking/{trackingNumber}",
@@ -1980,7 +1987,14 @@
1980
1987
  "path": "^/(?:[a-z]{2}/)?tracking/([^/?#]+)(?:/[0-9]+)?/?$"
1981
1988
  }
1982
1989
  ],
1983
- "detectionRules": []
1990
+ "detectionRules": [
1991
+ {
1992
+ "pattern": "^[A-Z]{2}\\d{9}FI$",
1993
+ "confidence": "low",
1994
+ "checksum": "s10",
1995
+ "preferred": true
1996
+ }
1997
+ ]
1984
1998
  },
1985
1999
  "correos-express": {
1986
2000
  "displayName": "Correos Express",
@@ -3969,5 +3983,30 @@
3969
3983
  }
3970
3984
  ],
3971
3985
  "detectionRules": []
3986
+ },
3987
+ "omgo": {
3988
+ "displayName": "OMGO",
3989
+ "color": "#8e8e93",
3990
+ "aliases": [
3991
+ "OMGO Express"
3992
+ ],
3993
+ "countries": [
3994
+ "CN"
3995
+ ],
3996
+ "selectable": true,
3997
+ "timezone": "UTC",
3998
+ "tracking": {
3999
+ "mode": "automatic",
4000
+ "adapter": "universal"
4001
+ },
4002
+ "canaryUrl": "https://omgoexpress.cn/",
4003
+ "trackingUrlTemplate": "https://omgoexpress.cn/",
4004
+ "linkRules": [],
4005
+ "detectionRules": [
4006
+ {
4007
+ "pattern": "^OMGO\\d{13}$",
4008
+ "confidence": "high"
4009
+ }
4010
+ ]
3972
4011
  }
3973
4012
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "catalog": 105,
2
+ "catalog": 106,
3
3
  "activeAdapters": 85,
4
4
  "countries": 58,
5
5
  "referenceCarriers": 100,
@@ -142,6 +142,7 @@
142
142
  "asked": [
143
143
  "tnt",
144
144
  "correos-express",
145
+ "dhl-ecommerce",
145
146
  "canada-post"
146
147
  ]
147
148
  },
@@ -1124,6 +1125,7 @@
1124
1125
  "asked": [
1125
1126
  "tnt",
1126
1127
  "correos-express",
1128
+ "dhl-ecommerce",
1127
1129
  "canada-post"
1128
1130
  ]
1129
1131
  },
@@ -1140,6 +1142,7 @@
1140
1142
  "asked": [
1141
1143
  "tnt",
1142
1144
  "correos-express",
1145
+ "dhl-ecommerce",
1143
1146
  "canada-post"
1144
1147
  ]
1145
1148
  },
@@ -1622,6 +1625,7 @@
1622
1625
  "asked": [
1623
1626
  "tnt",
1624
1627
  "correos-express",
1628
+ "dhl-ecommerce",
1625
1629
  "canada-post"
1626
1630
  ]
1627
1631
  },
@@ -1638,6 +1642,7 @@
1638
1642
  "asked": [
1639
1643
  "tnt",
1640
1644
  "correos-express",
1645
+ "dhl-ecommerce",
1641
1646
  "canada-post"
1642
1647
  ]
1643
1648
  },
@@ -1731,6 +1736,9 @@
1731
1736
  "confidence": "low",
1732
1737
  "candidates": [
1733
1738
  "dhl-ecommerce"
1739
+ ],
1740
+ "asked": [
1741
+ "dhl-ecommerce"
1734
1742
  ]
1735
1743
  },
1736
1744
  {
@@ -1746,6 +1754,7 @@
1746
1754
  "asked": [
1747
1755
  "tnt",
1748
1756
  "correos-express",
1757
+ "dhl-ecommerce",
1749
1758
  "canada-post"
1750
1759
  ]
1751
1760
  },
@@ -1922,6 +1931,7 @@
1922
1931
  "asked": [
1923
1932
  "tnt",
1924
1933
  "correos-express",
1934
+ "dhl-ecommerce",
1925
1935
  "canada-post"
1926
1936
  ]
1927
1937
  },
@@ -2345,6 +2355,9 @@
2345
2355
  "confidence": "low",
2346
2356
  "candidates": [
2347
2357
  "dhl-ecommerce"
2358
+ ],
2359
+ "asked": [
2360
+ "dhl-ecommerce"
2348
2361
  ]
2349
2362
  },
2350
2363
  {
@@ -2438,6 +2451,7 @@
2438
2451
  "asked": [
2439
2452
  "tnt",
2440
2453
  "correos-express",
2454
+ "dhl-ecommerce",
2441
2455
  "canada-post"
2442
2456
  ]
2443
2457
  },
@@ -2454,6 +2468,7 @@
2454
2468
  "asked": [
2455
2469
  "tnt",
2456
2470
  "correos-express",
2471
+ "dhl-ecommerce",
2457
2472
  "canada-post"
2458
2473
  ]
2459
2474
  },
@@ -2594,6 +2609,7 @@
2594
2609
  "asked": [
2595
2610
  "tnt",
2596
2611
  "correos-express",
2612
+ "dhl-ecommerce",
2597
2613
  "canada-post"
2598
2614
  ]
2599
2615
  },
@@ -2970,6 +2986,7 @@
2970
2986
  "asked": [
2971
2987
  "tnt",
2972
2988
  "correos-express",
2989
+ "dhl-ecommerce",
2973
2990
  "canada-post"
2974
2991
  ]
2975
2992
  },
@@ -3101,6 +3118,9 @@
3101
3118
  "confidence": "low",
3102
3119
  "candidates": [
3103
3120
  "dhl-ecommerce"
3121
+ ],
3122
+ "asked": [
3123
+ "dhl-ecommerce"
3104
3124
  ]
3105
3125
  },
3106
3126
  {
@@ -3112,7 +3132,8 @@
3112
3132
  "colis-prive"
3113
3133
  ],
3114
3134
  "asked": [
3115
- "colis-prive"
3135
+ "colis-prive",
3136
+ "dhl-ecommerce"
3116
3137
  ]
3117
3138
  },
3118
3139
  {
@@ -3281,6 +3302,9 @@
3281
3302
  "confidence": "high",
3282
3303
  "candidates": [
3283
3304
  "intl-post"
3305
+ ],
3306
+ "asked": [
3307
+ "chronopost"
3284
3308
  ]
3285
3309
  },
3286
3310
  {
@@ -3428,6 +3452,9 @@
3428
3452
  "confidence": "high",
3429
3453
  "candidates": [
3430
3454
  "intl-post"
3455
+ ],
3456
+ "asked": [
3457
+ "chronopost"
3431
3458
  ]
3432
3459
  },
3433
3460
  {
@@ -3473,6 +3500,29 @@
3473
3500
  "spring-gds"
3474
3501
  ]
3475
3502
  },
3503
+ {
3504
+ "input": "CP123456785FI",
3505
+ "carrier": "intl-post",
3506
+ "confidence": "high",
3507
+ "candidates": [
3508
+ "intl-post"
3509
+ ],
3510
+ "asked": [
3511
+ "posti",
3512
+ "chronopost"
3513
+ ]
3514
+ },
3515
+ {
3516
+ "input": "CP123456789FI",
3517
+ "carrier": "unknown",
3518
+ "confidence": "low",
3519
+ "candidates": [
3520
+ "chronopost"
3521
+ ],
3522
+ "asked": [
3523
+ "chronopost"
3524
+ ]
3525
+ },
3476
3526
  {
3477
3527
  "input": "CP123456789PL",
3478
3528
  "carrier": "unknown",
@@ -3490,6 +3540,9 @@
3490
3540
  "confidence": "high",
3491
3541
  "candidates": [
3492
3542
  "intl-post"
3543
+ ],
3544
+ "asked": [
3545
+ "chronopost"
3493
3546
  ]
3494
3547
  },
3495
3548
  {
@@ -3613,6 +3666,26 @@
3613
3666
  "confidence": "none",
3614
3667
  "candidates": []
3615
3668
  },
3669
+ {
3670
+ "input": "DOFR0000000000001HD",
3671
+ "carrier": "aliexpress",
3672
+ "confidence": "high",
3673
+ "candidates": [
3674
+ "aliexpress"
3675
+ ]
3676
+ },
3677
+ {
3678
+ "input": "DOFR0000000000001HU",
3679
+ "carrier": "unknown",
3680
+ "confidence": "none",
3681
+ "candidates": []
3682
+ },
3683
+ {
3684
+ "input": "DOFR000000000001HD",
3685
+ "carrier": "unknown",
3686
+ "confidence": "none",
3687
+ "candidates": []
3688
+ },
3616
3689
  {
3617
3690
  "input": "DQ0DK20000034530118220Z",
3618
3691
  "carrier": "correos-spain",
@@ -4157,6 +4230,9 @@
4157
4230
  "confidence": "high",
4158
4231
  "candidates": [
4159
4232
  "intl-post"
4233
+ ],
4234
+ "asked": [
4235
+ "chronopost"
4160
4236
  ]
4161
4237
  },
4162
4238
  {
@@ -4184,6 +4260,9 @@
4184
4260
  "confidence": "high",
4185
4261
  "candidates": [
4186
4262
  "intl-post"
4263
+ ],
4264
+ "asked": [
4265
+ "chronopost"
4187
4266
  ]
4188
4267
  },
4189
4268
  {
@@ -4200,6 +4279,9 @@
4200
4279
  "confidence": "high",
4201
4280
  "candidates": [
4202
4281
  "intl-post"
4282
+ ],
4283
+ "asked": [
4284
+ "chronopost"
4203
4285
  ]
4204
4286
  },
4205
4287
  {
@@ -4216,6 +4298,9 @@
4216
4298
  "confidence": "high",
4217
4299
  "candidates": [
4218
4300
  "intl-post"
4301
+ ],
4302
+ "asked": [
4303
+ "chronopost"
4219
4304
  ]
4220
4305
  },
4221
4306
  {
@@ -4312,6 +4397,9 @@
4312
4397
  "confidence": "high",
4313
4398
  "candidates": [
4314
4399
  "intl-post"
4400
+ ],
4401
+ "asked": [
4402
+ "chronopost"
4315
4403
  ]
4316
4404
  },
4317
4405
  {
@@ -4462,6 +4550,28 @@
4462
4550
  "ninja-van"
4463
4551
  ]
4464
4552
  },
4553
+ {
4554
+ "input": "OMGO0000000000001",
4555
+ "carrier": "omgo",
4556
+ "confidence": "high",
4557
+ "candidates": [
4558
+ "omgo"
4559
+ ]
4560
+ },
4561
+ {
4562
+ "input": "OMGO000000000001",
4563
+ "carrier": "unknown",
4564
+ "confidence": "none",
4565
+ "candidates": []
4566
+ },
4567
+ {
4568
+ "input": "OMGO0000000050001",
4569
+ "carrier": "omgo",
4570
+ "confidence": "high",
4571
+ "candidates": [
4572
+ "omgo"
4573
+ ]
4574
+ },
4465
4575
  {
4466
4576
  "input": "PHAS9C0419962810128017D",
4467
4577
  "carrier": "correos-spain",
@@ -4597,6 +4707,9 @@
4597
4707
  "confidence": "high",
4598
4708
  "candidates": [
4599
4709
  "intl-post"
4710
+ ],
4711
+ "asked": [
4712
+ "chronopost"
4600
4713
  ]
4601
4714
  },
4602
4715
  {
@@ -4998,6 +5111,9 @@
4998
5111
  "confidence": "high",
4999
5112
  "candidates": [
5000
5113
  "intl-post"
5114
+ ],
5115
+ "asked": [
5116
+ "chronopost"
5001
5117
  ]
5002
5118
  },
5003
5119
  {
@@ -278,7 +278,10 @@ var ue = {
278
278
  domains: ["global.cainiao.com"],
279
279
  params: ["mailNoList"]
280
280
  }],
281
- detectionRules: []
281
+ detectionRules: [{
282
+ pattern: "^DOFR\\d{13}HD$",
283
+ confidence: "high"
284
+ }]
282
285
  },
283
286
  sunyou: {
284
287
  displayName: "SunYou",
@@ -476,7 +479,8 @@ var ue = {
476
479
  timezone: "UTC",
477
480
  tracking: {
478
481
  mode: "automatic",
479
- adapter: "dhl-ecommerce"
482
+ adapter: "dhl-ecommerce",
483
+ recognitionRank: 23
480
484
  },
481
485
  canaryUrl: "https://www.dhl.com/ch-en/home/tracking.html",
482
486
  trackingUrlTemplate: "https://www.dhl.com/ch-en/home/tracking.html?tracking-id={trackingNumber}&submit=1",
@@ -1592,7 +1596,8 @@ var ue = {
1592
1596
  timezone: "Europe/Helsinki",
1593
1597
  tracking: {
1594
1598
  mode: "automatic",
1595
- adapter: "posti"
1599
+ adapter: "posti",
1600
+ recognitionRank: 27
1596
1601
  },
1597
1602
  canaryUrl: "https://www.posti.fi/en/tracking",
1598
1603
  trackingUrlTemplate: "https://www.posti.fi/en/tracking/{trackingNumber}",
@@ -1600,7 +1605,12 @@ var ue = {
1600
1605
  domains: ["posti.fi"],
1601
1606
  path: "^/(?:[a-z]{2}/)?tracking/([^/?#]+)(?:/[0-9]+)?/?$"
1602
1607
  }],
1603
- detectionRules: []
1608
+ detectionRules: [{
1609
+ pattern: "^[A-Z]{2}\\d{9}FI$",
1610
+ confidence: "low",
1611
+ checksum: "s10",
1612
+ preferred: !0
1613
+ }]
1604
1614
  },
1605
1615
  "correos-express": {
1606
1616
  displayName: "Correos Express",
@@ -3059,8 +3069,27 @@ var ue = {
3059
3069
  params: ["itemId"]
3060
3070
  }],
3061
3071
  detectionRules: []
3072
+ },
3073
+ omgo: {
3074
+ displayName: "OMGO",
3075
+ color: "#8e8e93",
3076
+ aliases: ["OMGO Express"],
3077
+ countries: ["CN"],
3078
+ selectable: !0,
3079
+ timezone: "UTC",
3080
+ tracking: {
3081
+ mode: "automatic",
3082
+ adapter: "universal"
3083
+ },
3084
+ canaryUrl: "https://omgoexpress.cn/",
3085
+ trackingUrlTemplate: "https://omgoexpress.cn/",
3086
+ linkRules: [],
3087
+ detectionRules: [{
3088
+ pattern: "^OMGO\\d{13}$",
3089
+ confidence: "high"
3090
+ }]
3062
3091
  }
3063
- }, de = /* @__PURE__ */ "swiss-post.swiss-post-cargo.quickpac.planzer.aliexpress.sunyou.hermes.spring-gds.postlogistics.dachser.dhl.dhl-ecommerce.ups.amazon-logistics.amazon-shipping.fedex.gls-ch.dpd.dpd-fr.mondial-relay.relais-colis.la-poste.chronopost.gls-fr.colis-prive.geodis.colisweb.c-chez-vous.heppner.ciblex.paack.asendia.shipup.india-post.hermes-de.gls-de.delivengo.intl-post.unknown.royal-mail.parcelforce.evri.inpost.an-post.bpost.austrian-post.postnord.posti.correos-express.seur.mrw.nacex.ctt.ctt-express.poste-italiane.brt.ecoscooting.tipsa.ukrposhta.usps.canada-post.purolator.canpar.ontrac.speedx.uniuni.landmark-global.old-dominion.spee-dee.gofo.estafeta.correios-br.correos-chile.yunexpress.four-px.blue-dart.delhivery.nz-post.singapore-post.japan-post.sf-express.sto.yunda.yto.zto.jd-logistics.yamato.korea-post.thailand-post.dtdc.australia-post.hongkong-post.pos-malaysia.ninja-van.china-post.packeta.poczta-polska.bring-posten.aramex.tnt.correos-spain.yanwen.the-courier-guy.j-and-t.ems".split("."), fe = [
3092
+ }, de = /* @__PURE__ */ "swiss-post.swiss-post-cargo.quickpac.planzer.aliexpress.sunyou.hermes.spring-gds.postlogistics.dachser.dhl.dhl-ecommerce.ups.amazon-logistics.amazon-shipping.fedex.gls-ch.dpd.dpd-fr.mondial-relay.relais-colis.la-poste.chronopost.gls-fr.colis-prive.geodis.colisweb.c-chez-vous.heppner.ciblex.paack.asendia.shipup.india-post.hermes-de.gls-de.delivengo.intl-post.unknown.royal-mail.parcelforce.evri.inpost.an-post.bpost.austrian-post.postnord.posti.correos-express.seur.mrw.nacex.ctt.ctt-express.poste-italiane.brt.ecoscooting.tipsa.ukrposhta.usps.canada-post.purolator.canpar.ontrac.speedx.uniuni.landmark-global.old-dominion.spee-dee.gofo.estafeta.correios-br.correos-chile.yunexpress.four-px.blue-dart.delhivery.nz-post.singapore-post.japan-post.sf-express.sto.yunda.yto.zto.jd-logistics.yamato.korea-post.thailand-post.dtdc.australia-post.hongkong-post.pos-malaysia.ninja-van.china-post.packeta.poczta-polska.bring-posten.aramex.tnt.correos-spain.yanwen.the-courier-guy.j-and-t.ems.omgo".split("."), fe = [
3064
3093
  "pending",
3065
3094
  "registered",
3066
3095
  "accepted",
@@ -3313,7 +3342,8 @@ var We = [
3313
3342
  /\b1G[A-Z0-9]{10}\b/gi,
3314
3343
  /\b[A-Z]{2}\s*\d(?:[\s.-]?\d){8}\s*[A-Z]{2}\b/gi,
3315
3344
  /\b(?:JJD|JVGL)[A-Z0-9]{8,}\b/gi,
3316
- /\b\d(?:[\s.-]?\d){9,19}\b/g
3345
+ /\b\d(?:[\s.-]?\d){9,19}\b/g,
3346
+ /\b[A-Z0-9]{4,40}\b/gi
3317
3347
  ];
3318
3348
  function Ge(e) {
3319
3349
  for (let t of We) {
@@ -7404,6 +7434,7 @@ var Lo = {
7404
7434
  "colis-prive": 30,
7405
7435
  "correos-express": 36,
7406
7436
  "ctt-express": 35,
7437
+ "dhl-ecommerce": 23,
7407
7438
  dpd: 70,
7408
7439
  "gls-ch": 60,
7409
7440
  "gls-de": 50,
@@ -7414,6 +7445,7 @@ var Lo = {
7414
7445
  "ninja-van": 28,
7415
7446
  "nz-post": 32,
7416
7447
  "poczta-polska": 31,
7448
+ posti: 27,
7417
7449
  postlogistics: 26,
7418
7450
  "relais-colis": 25,
7419
7451
  seur: 43,
@@ -7423,20 +7455,26 @@ var Lo = {
7423
7455
  uniuni: 33
7424
7456
  }, Ro = 5;
7425
7457
  function zo(e, t = {}) {
7426
- let n = b(e);
7427
- if (n.confidence !== "low") return [];
7428
- let r = new Set(n.preferred.filter((e) => Lo[e] === void 0).map((e) => Io(e)).filter(Boolean)), i = (e) => [
7458
+ let n = b(e), r = n.carrier === "intl-post";
7459
+ if (n.confidence !== "low" && !r) return [];
7460
+ let i = g(e), a = r ? Object.entries(_).flatMap(([t, n]) => {
7461
+ let r = n.detectionRules.find((t) => t.confidence === "low" && (!t.checksum || t.checksum === "s10") && new RegExp(t.pattern).test(i) && (!t.rawPattern || new RegExp(t.rawPattern).test(e.trim().toUpperCase())));
7462
+ return r ? [{
7463
+ carrier: t,
7464
+ preferred: r.preferred === !0
7465
+ }] : [];
7466
+ }) : [], o = r ? a.map(({ carrier: e }) => e) : n.candidates, s = r ? a.filter((e) => e.preferred).map(({ carrier: e }) => e) : n.preferred, c = new Set(s.filter((e) => Lo[e] === void 0).map((e) => Io(e)).filter(Boolean)), l = (e) => [
7429
7467
  +(e === t.hint),
7430
- +!!n.preferred.includes(e),
7468
+ +!!s.includes(e),
7431
7469
  Lo[e] ?? 0
7432
7470
  ];
7433
- return n.candidates.filter((e) => Lo[e] !== void 0 && we.has(e) && xe(e) !== "universal" && !r.has(Io(e)) && !t.skip?.(e)).map((e) => ({
7471
+ return o.filter((e) => Lo[e] !== void 0 && we.has(e) && xe(e) !== "universal" && !c.has(Io(e)) && !t.skip?.(e)).map((e) => ({
7434
7472
  carrier: e,
7435
- score: i(e)
7473
+ score: l(e)
7436
7474
  })).sort((e, t) => t.score[0] - e.score[0] || t.score[1] - e.score[1] || t.score[2] - e.score[2]).map(({ carrier: t }) => ({
7437
7475
  carrier: t,
7438
7476
  needsInput: Ce(t, e)[0]?.field ?? null,
7439
- preferred: n.preferred.includes(t)
7477
+ preferred: s.includes(t)
7440
7478
  }));
7441
7479
  }
7442
7480
  //#endregion
@@ -55,5 +55,11 @@
55
55
  ]
56
56
  }
57
57
  ],
58
- "detection": []
58
+ "detection": [
59
+ {
60
+ "id": "aliexpress-1",
61
+ "pattern": "^DOFR\\d{13}HD$",
62
+ "confidence": "high"
63
+ }
64
+ ]
59
65
  }
@@ -1,6 +1,28 @@
1
1
  {
2
2
  "carrier": "aliexpress",
3
3
  "records": [
4
+ {
5
+ "number": "DOFR0000000000001HD",
6
+ "role": "shipment",
7
+ "evidence": "synthetic",
8
+ "derivedFrom": "observed_request",
9
+ "expect": { "carrier": "aliexpress", "confidence": "high" },
10
+ "note": "Synthetic Cainiao shipment-number shape."
11
+ },
12
+ {
13
+ "number": "DOFR000000000001HD",
14
+ "role": "negative",
15
+ "evidence": "synthetic",
16
+ "derivedFrom": "invented",
17
+ "expect": { "carrier": "unknown", "confidence": "none", "not": ["aliexpress"] }
18
+ },
19
+ {
20
+ "number": "DOFR0000000000001HU",
21
+ "role": "negative",
22
+ "evidence": "synthetic",
23
+ "derivedFrom": "invented",
24
+ "expect": { "carrier": "unknown", "confidence": "none", "not": ["aliexpress"] }
25
+ },
4
26
  {
5
27
  "number": "CNG00798678939847",
6
28
  "role": "shipment",
@@ -1,20 +1,12 @@
1
1
  /**
2
- * DHL eCommerce, through the public recipient endpoint the global tracking
3
- * page calls (`www.dhl.com/utapi`).
4
- *
5
- * The endpoint answers every direct server request with an Akamai crypto
6
- * proof-of-work challenge (HTTP 428) that plain HTTP cannot solve (verified
7
- * 2026-09-10: cookie replay and visiting the page first both still return
8
- * 428), and browser clearance is not transferable back to Node. The lookup
9
- * therefore has a single step: a local Chromium session loads the tracking
10
- * page, the site solves its own challenge and calls the API in that session,
11
- * and the response to the exact requested URL is parsed.
2
+ * DHL eCommerce, through its anonymous Americas Webtrack API first, then
3
+ * the global tracking page's UTAPI for shipments outside Webtrack's scope.
12
4
  *
13
5
  * DHL may answer with a customer-confirmation id instead of the queried
14
6
  * alias, so only one eCommerce shipment from that exact request URL is
15
7
  * accepted, and the id itself is never retained.
16
8
  */
17
- import type { AdapterFactory, TrackingContext } from '../../core/adapter/index.js';
9
+ import { type AdapterFactory, type Recognition, type TrackingContext } from '../../core/adapter/index.js';
18
10
  import { ChallengeError, type CarrierErrorOptions } from '../../core/errors/index.js';
19
11
  import type { CarrierResult } from '../../core/result/index.js';
20
12
  import { type StepRecorder } from '../../core/telemetry/index.js';
@@ -24,6 +16,11 @@ export declare function dhlEcommerceTrackingUrl(number: string): string;
24
16
  /** Only call for the response to the exact requested UTAPI URL. DHL can return
25
17
  * a customer-confirmation id which differs from every queried parcel alias. */
26
18
  export declare function parseDHLEcommerceResponse(payload: unknown): CarrierResult;
19
+ /** Webtrack scopes the read to the requested alias and returns that alias on
20
+ * each package, as its own client requires. An alias can differ from all of
21
+ * the package's carrier identifiers, so accept it only on one identified,
22
+ * unambiguous package. Never accept a bare query echo or a fabricated shell. */
23
+ export declare function parseDHLEcommerceWebtrackResponse(payload: unknown, trackingNumber: string): CarrierResult;
27
24
  /**
28
25
  * The tracking page answered with a challenge status instead of the tracking
29
26
  * application. The name is part of the host's error metadata contract: it
@@ -37,6 +34,8 @@ export declare class DHLEcommerceSessionError extends ChallengeError {
37
34
  export interface DHLEcommerceTrackerOptions extends Omit<UniversalBrowserOptions, 'signal'> {
38
35
  budgetMs?: number;
39
36
  recorder?: StepRecorder;
37
+ fetcher?: typeof fetch;
38
+ userAgent?: string;
40
39
  }
41
40
  export declare class DHLEcommerceTracker {
42
41
  readonly options: DHLEcommerceTrackerOptions;
@@ -45,6 +44,9 @@ export declare class DHLEcommerceTracker {
45
44
  constructor(options?: DHLEcommerceTrackerOptions);
46
45
  /** One browser at a time per instance: a batch must not spawn a Chromium per parcel. */
47
46
  fetch(trackingNumber: string, context?: TrackingContext): Promise<CarrierResult>;
47
+ /** Recognition never starts the global page or spends a browser budget. */
48
+ recognize(trackingNumber: string, context?: TrackingContext): Promise<Recognition>;
49
+ private direct;
48
50
  private browser;
49
51
  }
50
52
  export declare const adapter: AdapterFactory;