You need a reliable way to check current congestion conditions at Laem Chabang (THLCH) so you can plan port calls, routing, and schedule buffers. By the end of this guide, you will be able to query a production endpoint, parse the response in Python, and interpret the congestion signals that matter for transportation operations.
What this API actually measures (and what it does not)
FreightPulse port congestion is calculated from IMF PortWatch, which aggregates UN Global Platform AIS data. The metric is lagged by roughly 6–7 days and updated daily. It compares the recent 7-day average port calls to a 90-day baseline for the same port. It does not measure vessel anchorage or berth waiting time directly and is not a live AIS wait-time feed.
This distinction matters: use it to benchmark whether activity is running hotter or cooler than normal, not to infer hour-by-hour dwell or queue length. If you need reactive decisions within a single day, build buffers or pair this signal with your own AIS stream and terminal-side updates.
Endpoint, authentication, and envelope
To query congestion for Laem Chabang (THLCH), call the GET endpoint below. Authentication is via the X-API-Key header. If you do not set a key, you are treated as a guest and are limited to 100 requests per day per IP.
- HTTP method: GET
- Path: /api/v1/port-congestion
- Param: port=THLCH
- Auth: header X-API-Key: YOUR_API_KEY (leave blank to use the guest limit)
Responses use a consistent envelope:
- success: boolean indicating whether the request succeeded
- data: the actual results payload
Within data, you will consume fields such as congestion, metrics.ratio_vs_baseline, and as_of for decision-making.
Copy-paste cURL for Laem Chabang (THLCH)
Use this exact command to pull congestion for THLCH:
curl -H "X-API-Key: YOUR_API_KEY" "https://freightpulsehq.com/api/v1/port-congestion?port=THLCH"
Official sample response and how to read it
Below is the official example response. Copy it as-is when you need a fixture for tests or documentation. After the JSON, you will find notes on the fields you will use in your application.
{
"success": true,
"data": {
"results": [
{
"port": "Laem Chabang",
"locode": "TH LCH",
"country": "Thailand",
"congestion": "moderate",
"as_of": "2026-10-16",
"metrics": {
"recent_avg_portcalls_per_day": 21.1,
"baseline_avg_portcalls_per_day": 19.2,
"ratio_vs_baseline": 1.1
}
}
],
"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": "edf3c0fa-d495-4d63-a937-73cb2c2be69a"
}
}
How to use this data:
- congestion: a categorical label (e.g., low, moderate, high). Use this for simple thresholding in alerts.
- metrics.ratio_vs_baseline: real-valued multiplier of current activity vs the 90-day baseline. Greater than 1 implies above-baseline activity; less than 1 implies below-baseline.
- as_of: the date stamp for which the lagged estimate applies. Treat as a daily UTC date; it is not intraday.
- metrics.recent_avg_portcalls_per_day and metrics.baseline_avg_portcalls_per_day: underlying counts you can chart or audit.
- global_summary: optional context across all tracked ports; not required if you only need THLCH.
Python: query THLCH and extract decision fields
The snippet below fetches congestion for Laem Chabang, validates the envelope, and pulls congestion, ratio_vs_baseline, and as_of. It also includes basic time-aware caching guidance in comments.
import os
import time
import requests
API_URL = "https://freightpulsehq.com/api/v1/port-congestion"
PORT_CODE = "THLCH"
API_KEY = os.getenv("FREIGHTPULSE_API_KEY", "YOUR_API_KEY")
def fetch_thlch_congestion(session: requests.Session) -> dict:
"""
Returns a dict with keys: congestion, ratio_vs_baseline, as_of.
Raises an exception if the envelope indicates failure or fields are missing.
"""
headers = {"X-API-Key": API_KEY}
params = {"port": PORT_CODE}
resp = session.get(API_URL, headers=headers, params=params, timeout=20)
resp.raise_for_status()
payload = resp.json()
if not isinstance(payload, dict) or not payload.get("success"):
raise RuntimeError("API indicated failure or unexpected envelope")
data = payload.get("data", {})
results = data.get("results", [])
if not results:
raise ValueError("No results for THLCH")
item = results[0]
metrics = item.get("metrics", {})
out = {
"congestion": item.get("congestion"),
"ratio_vs_baseline": metrics.get("ratio_vs_baseline"),
"as_of": item.get("as_of"),
# Optional extras you might log:
"recent_avg_portcalls_per_day": metrics.get("recent_avg_portcalls_per_day"),
"baseline_avg_portcalls_per_day": metrics.get("baseline_avg_portcalls_per_day"),
"port": item.get("port"),
"locode": item.get("locode"),
"country": item.get("country"),
}
# Basic validation
if out["congestion"] is None or out["ratio_vs_baseline"] is None or out["as_of"] is None:
raise ValueError("Missing key fields in response")
return out
if __name__ == "__main__":
# Simple client with keep-alive
with requests.Session() as s:
# If your scheduler runs more than once per day, cache for 12–24h.
# The dataset updates daily and is lagged ~6–7 days, so high-frequency polling
# brings little benefit and may exhaust the guest limit.
last_fetch = 0
cache_ttl_seconds = 12 * 3600 # 12 hours
if time.time() - last_fetch > cache_ttl_seconds:
result = fetch_thlch_congestion(s)
last_fetch = time.time()
# Example usage: raise alert when moderate or ratio exceeds threshold
ratio = result["ratio_vs_baseline"]
label = result["congestion"]
as_of = result["as_of"]
print(f"[THLCH] as_of={as_of} congestion={label} ratio_vs_baseline={ratio}")
Interpreting congestion for transportation decisions
Because the underlying series reflects relative port-call activity, your application logic should align with shipment, vessel, and terminal timelines, not minute-by-minute triggers. A common pattern:
- Use congestion to set a buffer policy per port. For example, when ratio_vs_baseline ≥ 1.05 or congestion = moderate/high, add extra dwell assumptions in schedule simulations.
- Flag lanes entering or exiting Laem Chabang for manual review when the signal moves up a category between daily runs.
- When building ETAs, apply the as_of date to avoid mixing lagged congestion with real-time AIS speed and weather; clearly label dashboards with the lag.
Do not quote a freight-rates USD fare as today’s price based on this API. Congestion is not a price feed, and its lag means it should not be treated as a same-day market signal.
Practical implementation details that save time
Dates, timezone, and cadence
as_of is a daily date stamp. Treat it as UTC for consistency across services. The series updates daily and is typically lagged about 6–7 days from the current calendar date.
Caching and request frequency
Cache responses for 12–24 hours unless you are performing backfills or recalculating historical dashboards. This avoids hitting the 100 requests/day per IP guest limit if you are unauthenticated and reduces load without losing fidelity.
Pagination and filtering
For a single port like THLCH, you should receive one result under data.results. If you later request multiple ports (when available), be prepared to iterate results. This endpoint, as used here, does not require pagination for a single code.
Units and interpretation
- metrics.recent_avg_portcalls_per_day and metrics.baseline_avg_portcalls_per_day are counts per day (vessels/day), averaged over the stated windows.
- metrics.ratio_vs_baseline is unitless (e.g., 1.1 means recent activity is 10% above baseline).
Error handling and envelopes
Always check success before reading data. Validate that data.results is present and non-empty. In transport orchestration pipelines, fail closed (defer to the last known good value) rather than blocking critical path ETAs.
Embedding THLCH congestion into your transportation workflow
Here is a concrete approach to integrate Laem Chabang congestion into voyage planning, NVOCC milestone tracking, or inland cutoff scheduling:
- Nightly scheduler or Airflow task calls GET /api/v1/port-congestion?port=THLCH with your API key.
- Extract as_of, congestion, and ratio_vs_baseline. Store as a daily snapshot keyed by port and date.
- On each routing run, read the latest snapshot for THLCH and apply a buffer policy (e.g., add 4–12 hours of terminal slack when congestion is moderate and ratio_vs_baseline ≥ 1.05; tune to your service schedule and commodity sensitivity).
- Expose category changes to an alert queue for trade lanes touching Laem Chabang in the next 14 days.
- Label dashboards clearly that the series is IMF PortWatch and lagged, so operations teams interpret it correctly alongside live AIS or terminal data.
Security, quotas, and environments
- Authentication: X-API-Key header. Keep the key outside source control (e.g., environment variables or a secrets manager).
- Guest usage: 100 requests/day per IP without a key. For scheduled jobs and multi-environment deployments, register for a key to avoid hitting guest limits.
- Transport: HTTPS only. Use a short client timeout (10–20s) and retry on transient network failures with exponential backoff.
Validation checklist for Laem Chabang (THLCH)
- Endpoint path and port param are correct: /api/v1/port-congestion?port=THLCH
- Auth header present: X-API-Key with your value, or accept guest limits.
- Envelope enforced: success true before reading data.
- Fields extracted: congestion, metrics.ratio_vs_baseline, as_of.
- Lag-aware logic: avoid intraday updates dictating hour-level schedule changes.
- Caching in place: 12–24 hours for production jobs.
Operational notes specific to Laem Chabang
Laem Chabang is a major Thai container gateway, so short-lived demand surges or vessel bunching can shift ratio_vs_baseline notably even if the category remains moderate. Combine this signal with your carrier service loops and yard capacity assumptions. If you see ratio_vs_baseline rising week-over-week, prep contingency truck slots and re-check cutoffs with terminals or carriers. Conversely, when the ratio softens toward 1.0, you can dial back conservative buffers to reclaim schedule reliability.
FAQ
Is this congestion live AIS wait time?
No. It is based on IMF PortWatch, using a 7-day average of port calls compared with a 90-day baseline, and is lagged by about 6–7 days. It does not report anchorage or berth wait times.
What does ratio_vs_baseline mean for Laem Chabang?
A value above 1 indicates above-baseline recent port-call intensity; below 1 indicates lighter-than-baseline activity. Use it to adjust buffers or highlight lanes for review.
How often should I poll the endpoint?
Daily is sufficient. Cache for 12–24 hours. Polling more often generally does not change the value within the day.
Do I need an API key?
You can call the endpoint without a key under a guest limit of 100 requests per day per IP. For production or multiple environments, use an API key via the X-API-Key header.
Can I infer today’s freight rates from congestion?
No. Do not quote a freight-rates USD fare as today’s price based on this signal. Congestion is not a pricing feed and is lagged.
Ready to integrate congestion for Laem Chabang into your transportation workflows? Create an account and get your API key here: Register. For full parameter references and additional notes, see the Documentation.