You’re trying to quantify how congested Hong Kong (HKHKG) is right now, but “right now” data for port congestion isn’t the same as live AIS wait times. By the end of this post, you’ll be able to query IMF PortWatch–derived congestion for Hong Kong via a single API call, interpret the 7‑day average vs 90‑day baseline methodology, and integrate the response into your own dashboards or alerting.
What this dataset measures for Hong Kong—and what it doesn’t
FreightPulse port congestion for Hong Kong is derived from IMF PortWatch and UN Global Platform AIS data. It is updated daily but lagged by roughly 6–7 days. That means you should treat it as a stable, near-real-time indicator of port throughput rather than a live feed of anchorage wait times or queue lengths.
Key points specific to this feed:
- It’s IMF PortWatch, lagged ~6–7 days, updated daily.
- It is not live AIS vessel waiting time data.
- The congestion level is based on the 7‑day average port calls compared to a 90‑day baseline for the same port.
- Returned values include a categorical congestion label (e.g., “moderate”), the “as_of” date for the last valid tick, and metrics with the recent average, baseline average, and ratio_vs_baseline.
Because the indicator focuses on port call counts, use it to understand directional throughput pressure at Hong Kong, not to estimate minutes-to-berth for a specific vessel.
How to access Hong Kong port congestion programmatically
The congestion endpoint for Hong Kong uses the port code HKHKG. Authentication supports an API key passed as a header; requests without a key are rate-limited at the IP level.
- Auth: header X-API-Key: YOUR_API_KEY. Guest without key: 100 requests/day per IP.
- Envelope: {"success":true,"data":{...}}
- Port congestion is IMF PortWatch, lagged ~6–7 days, 7‑day avg vs 90‑day baseline — not live AIS.
You can retrieve the latest lagged congestion series for Hong Kong with a single GET:
curl -H "X-API-Key: YOUR_API_KEY" "https://freightpulsehq.com/api/v1/port-congestion?port=HKHKG"
Official example response for HKHKG
Below is the official JSON response example for Hong Kong. Use this as your integration reference for field names and nesting:
{
"success": true,
"data": {
"results": [
{
"port": "Hong Kong",
"locode": "HK HKG",
"country": "Hong Kong SAR",
"congestion": "moderate",
"as_of": "2026-10-30",
"metrics": {
"recent_avg_portcalls_per_day": 33.3,
"baseline_avg_portcalls_per_day": 38.1,
"ratio_vs_baseline": 0.87
}
}
],
"global_summary": {
"ports_high_congestion": 0,
"ports_moderate": 1,
"ports_low": 0
},
"meta": {
"source": "IMF PortWatch (portwatch.imf.org) - UN Global Platform AIS data",
"data_lag_days": "~6-7 (daily updates, not real-time)",
"methodology": "congestion level is an approximation: last 7 days' avg port calls vs 90-day baseline for the same port. Does not measure vessel wait/anchorage time."
}
},
"meta": {
"request_id": "3a1b401a-4212-402a-829d-f1e7d20e8699"
}
}
Fields you’ll actually use:
- data.results[0].congestion — categorical congestion label for Hong Kong.
- data.results[0].as_of — the effective date for the data (lagged; YYYY-MM-DD).
- data.results[0].metrics.recent_avg_portcalls_per_day — 7‑day average port calls.
- data.results[0].metrics.baseline_avg_portcalls_per_day — 90‑day baseline average.
- data.results[0].metrics.ratio_vs_baseline — dimensionless ratio (recent/baseline).
Interpreting the 7‑day vs 90‑day baseline for Hong Kong
The methodology compares recent throughput (last 7 days of port calls per day) to the prior 90‑day baseline for the same port. A ratio_vs_baseline below 1.0 indicates throughput below baseline; above 1.0 indicates throughput above baseline. The categorical congestion string (e.g., “moderate”) maps to thresholds derived from this ratio and other business logic internal to the feed.
Practical tips for interpretation:
- Use ratio_vs_baseline for numeric alerting. For example, alert when ratio dips below a threshold you calibrate for your operations.
- Use the categorical congestion label for user-friendly UI cues.
- The as_of date is lagged ~6–7 days. Build your UI copy and SLAs around this characteristic.
Copy-paste JavaScript example
This example requests Hong Kong congestion, extracts the categorical label, the as_of date, and key metrics, then prints a concise line you can reuse in logs or alerts. It mirrors the official curl and JSON structure exactly.
async function fetchHongKongCongestion() {
const url = "https://freightpulsehq.com/api/v1/port-congestion?port=HKHKG";
const resp = await fetch(url, {
headers: { "X-API-Key": "YOUR_API_KEY" }
});
if (!resp.ok) {
throw new Error(`HTTP ${resp.status} - ${resp.statusText}`);
}
const body = await resp.json();
// Envelope is {"success": true, "data": {...}}
if (!body.success || !body.data || !Array.isArray(body.data.results)) {
throw new Error("Unexpected response shape");
}
const hk = body.data.results[0];
if (!hk) {
throw new Error("No results for Hong Kong (HKHKG)");
}
const port = hk.port; // "Hong Kong"
const locode = hk.locode; // "HK HKG"
const asOf = hk.as_of; // e.g., "2026-10-30" (lagged ~6-7 days)
const congestion = hk.congestion; // e.g., "moderate"
const metrics = hk.metrics || {};
const recent = metrics.recent_avg_portcalls_per_day; // number, port calls/day
const baseline = metrics.baseline_avg_portcalls_per_day; // number, port calls/day
const ratio = metrics.ratio_vs_baseline; // number, dimensionless
console.log(`[${asOf}] ${port} (${locode}) congestion=${congestion}; ratio=${ratio}; recent=${recent}/day vs baseline=${baseline}/day`);
}
fetchHongKongCongestion().catch(err => {
console.error("Failed to load Hong Kong congestion:", err);
});
Integration notes that save time
- Authentication and limits:
- Header X-API-Key: YOUR_API_KEY.
- Guests without a key are limited to 100 requests/day per IP. Add caching to avoid exhausting this bucket.
- Envelope and stability:
- Responses wrap data in {"success": true, "data": {...}}. Validate both before dereferencing fields.
- Use defensive checks around data.results[0] in case the port is temporarily unavailable.
- Timestamps and timezone:
- as_of uses an ISO date string (YYYY-MM-DD). Treat it as UTC date boundaries for daily ticks.
- Because of the ~6–7 day lag, “today” on your calendar will not match the latest as_of date.
- Caching:
- The feed updates daily, not intra-day. Cache per port for 24 hours unless your product requires earlier refreshes.
- Record the as_of value in your cache key or metadata to avoid showing mixed ticks across components.
- Units and dimensions:
- recent_avg_portcalls_per_day and baseline_avg_portcalls_per_day are counts/day.
- ratio_vs_baseline is dimensionless (recent ÷ baseline).
- No currency fields are present; do not conflate congestion with freight rates.
- Holidays and “non-trading days” analog:
- Port calls are daily observations; the 7‑day smoothing reduces single-day holiday effects.
- Expect minor seasonal patterns in the 90‑day baseline; ratio_vs_baseline normalizes for this.
Common pitfalls when using Hong Kong congestion
- Misreading it as live queue times: The metric does not estimate vessel waiting/anchorage time; it is a throughput proxy from port calls.
- Alerting on raw port calls instead of ratio: Differences in port scale can make raw counts misleading; use ratio_vs_baseline for comparable alerts over time.
- Ignoring the lag: Align your copy and SLAs with the ~6–7 day lag to avoid “why is this a week old?” tickets.
- Over-polling: It’s a daily tick. Reduce polling to conserve quota and improve reliability.
Minimal Python example
If you prefer Python, this snippet mirrors the same endpoint and fields, returning a compact dict ready for templating or storage:
import requests
def get_hk_congestion():
url = "https://freightpulsehq.com/api/v1/port-congestion?port=HKHKG"
headers = {
"X-API-Key": "YOUR_API_KEY"
}
r = requests.get(url, headers=headers, timeout=20)
r.raise_for_status()
body = r.json()
# Envelope validation
if not body.get("success") or "data" not in body:
raise ValueError("Unexpected response: missing 'success' or 'data'")
results = body["data"].get("results", [])
if not results:
raise ValueError("No results for Hong Kong (HKHKG)")
hk = results[0]
metrics = hk.get("metrics", {})
return {
"port": hk.get("port"),
"locode": hk.get("locode"),
"country": hk.get("country"),
"as_of": hk.get("as_of"), # ISO date (UTC), lagged ~6-7 days
"congestion": hk.get("congestion"),
"recent_avg_portcalls_per_day": metrics.get("recent_avg_portcalls_per_day"),
"baseline_avg_portcalls_per_day": metrics.get("baseline_avg_portcalls_per_day"),
"ratio_vs_baseline": metrics.get("ratio_vs_baseline")
}
if __name__ == "__main__":
try:
data = get_hk_congestion()
print(f"[{data['as_of']}] {data['port']} congestion={data['congestion']} (ratio={data['ratio_vs_baseline']})")
except Exception as e:
print("Error:", e)
Operationalizing Hong Kong congestion in your stack
Data refresh and SLAs
Schedule a daily job to refresh Hong Kong congestion. Store the as_of date with the payload and render it in your UI subtitle, e.g., “Hong Kong congestion: moderate (as of 2026‑10‑30; IMF PortWatch; ~6–7 day lag).” This prevents confusion between the period of validity and your fetch time.
Alert thresholds
Select a ratio_vs_baseline threshold that’s meaningful to your workflows. For example, if your downstream milestones are sensitive to dips in throughput, alert when ratio falls below a chosen value for N consecutive days. Because the input is already a 7‑day average, a 2–3 day persistence requirement can filter noise without missing real shifts.
UI semantics
Use the congestion label for badges (low, moderate, high) and attach a tooltip that explains the methodology in one sentence. Include the data source and lag in a help modal so stakeholders understand why the date is not “today.”
Caching and fallbacks
Cache the entire response envelope and expose a last_good_tick. If the next fetch fails, continue serving the cached payload with a soft warning in logs. Because updates are daily, stale writes for a few hours will not materially impact decision-making.
What to include (and exclude) in your product copy
- Include:
- “IMF PortWatch (UN Global Platform AIS), updated daily, ~6–7 day lag.”
- “7‑day average vs 90‑day baseline; not a measure of vessel waiting time.”
- The as_of date clearly next to the congestion label.
- Exclude:
- Any implication that this is live AIS wait times.
- Freight rate quotes as “today’s price” in the same view; keep pricing separate.
Reference: Official curl for HKHKG
This is the copy‑paste request you can use in CI scripts, cron jobs, or Postman collections:
Where to go next
For complete parameter notes, response envelopes, and integration patterns across endpoints, see the Documentation. Keep Hong Kong as your initial focus while you wire up caching, error handling, and UI messaging that explains the lag and methodology.
FAQ
Is the Hong Kong congestion value real-time?
No. It’s updated daily with a ~6–7 day lag from IMF PortWatch. It is not a live AIS queue metric.
Which fields should I store for alerting?
Store as_of, congestion, and metrics.ratio_vs_baseline. Consider also keeping recent_avg_portcalls_per_day and baseline_avg_portcalls_per_day for debugging and historical context.
Do I need an API key?
You can call without a key, but guests are limited to 100 requests/day per IP. For production, set X-API-Key: YOUR_API_KEY.
What timezone is as_of in?
The as_of field is a date (YYYY-MM-DD). Treat it as UTC date boundaries for consistency across systems.
Can I use this to quote prices or ETAs?
No. This dataset does not include fares or live wait times. Do not present it as today’s price or as a live ETA predictor.
If you need stable, daily congestion visibility for Hong Kong that you can ship into production quickly, create your key and start querying today: Register.