4
Ocean Carriers Monitored (MSC, Evergreen, COSCO, OOCL)
5 min
OOCL High-Frequency Polling Interval
2
Critical Dates Tracked Per Booking (ERD + Rail Cut-Off)
The Problem

Freight Forwarders Check Four Carrier Portals Multiple Times a Day — Missed Changes Cost Money

Ocean freight operations depend on two critical dates per booking: the Earliest Receiving Date, which determines when cargo can be delivered to the terminal, and the Rail Cut-Off Date, which sets the last moment for rail cargo to reach the port. These dates change frequently — and missing a change means missed cargo, rerouting costs, and client penalties. Freight forwarders managing dozens of active bookings across MSC, Evergreen, COSCO, and OOCL were logging into four separate carrier portals multiple times per day, copying dates into spreadsheets, and manually comparing to detect changes. There was no automated alerting system.
Our Solution

Four-Carrier Scraping Architecture with Change Detection and Instant Notifications

We built Vessel Tracking as a Django + React platform with four dedicated carrier scrapers. MSC requires authenticated headless browser access via Playwright: the scraper launches a headless Chromium browser with a randomised fake user agent, accepts the cookie consent banner, navigates the two-stage email/password login form, waits 10 seconds for session establishment, fills in the booking number, and extracts Rail Open and Rail Cut-Off dates from the gridCutOff table. Evergreen tracking runs through Shipmentlink via direct POST requests with session cookies — submitting the booking number with TYPE=BK and SEL parameters and extracting ERD and cut-off dates from specific table row/column positions via BeautifulSoup. COSCO exposes a public REST API (no auth required) — a single call with the booking number and a Unix millisecond timestamp returns JSON with cutOff and erd fields. OOCL routes through an internal microservice proxy that handles all OOCL-specific scraping and returns processed data to Django. The automated tracking engine marks each booking as in-progress during scraping to prevent duplicate updates, scrapes the carrier, uses python-dateutil to normalise varied carrier date format strings, copies current dates to old_ fields before overwriting, and resets is_read=False on the notification. The React dashboard renders both current and old dates side-by-side in the booking table, with Flatpickr date filter controls for ERD and Rail Cut-Off columns.
Architecture
Django 5 + DRF API. JWT authentication. Celery + django-crontab for scheduled carrier scraping (4-hour standard refresh, 5-minute OOCL fast refresh). Playwright + fake-useragent for MSC authenticated headless scraping. BeautifulSoup + lxml for Evergreen HTML parsing. requests for COSCO REST API and OOCL microservice proxy. python-dateutil for carrier date normalisation. PostgreSQL with new_entry concurrency lock. Threading for non-blocking immediate first scrape. React + Reactstrap + Redux + ApexCharts dashboard. react-select + Flatpickr for filtering.
The Result

One Dashboard Replaces Four Carrier Portals — Date Changes Caught Automatically, Every Time

Vessel Tracking eliminated the four-portal manual checking workflow entirely — replacing it with an automated system that notifies freight forwarders the moment any ERD or Rail Cut-Off date changes across any of the four carriers. Operations teams no longer need to log in anywhere manually to stay current on their bookings. The old-date preservation model — storing previous ERD and Rail Cut-Off values alongside current ones — gave teams instant change context directly in the booking list, without needing to open notifications separately. The moment a booking is added, an immediate background scrape fires so first data is available seconds after entry, not at the next scheduled cycle. OOCL's 5-minute fast-refresh cycle matched that carrier's higher change frequency without wasting resources on slower-moving carriers. The concurrency lock ensured no booking was ever double-scraped during simultaneous cycle runs. Freight forwarders went from multiple daily portal logins per carrier to a single dashboard view — with every schedule change surfaced automatically.
Want scalable architecture and measurable results like this?
Book an Architecture Audit
Build Something Like This
// free scoping call · senior engineers · no commitment

Project scope, timelines, and architecture options in one 45-minute session.

Start a Project
More Work

Related Projects

The Marble Group: Natural Stone Inventory Intelligence Platform for UK Stone Buyers
Django Docker PostgreSQL
The Marble Group: Natural Stone Inventory Intelligence Platform for UK Stone Buyers
One dashboard for 10 UK stone suppliers — automated price reconciliation, real-time stock alerts, instant PDF/Excel export. Replace 15+ hours of manual supplier research every week.
View Details
Django Node.js PostgreSQL
Farming Product Monitor: Real-Time Agricultural Price & Stock Intelligence for Pakistani Markets
Get instant Discord alerts on price and stock changes across Kissanghar.pk and Syngenta Pakistan. Full change history, stealth scraping, and full-catalogue auto-discovery built in.
View Details
Django Docker PostgreSQL
Global Freight Tracking API: Track 30+ Air & Sea Carriers — One Call, One Standard Response
One API call replaces 30+ carrier portal checks. Real-time AWB and container tracking from international air and sea carriers — standardised JSON response, including full audio CAPTCHA bypass.
View Details