← all builds

Headless Delivery Check

playwrightscrapinglogistics
Download .md

A sanitised reference implementation. Drop it into Claude Code, point it at your own tracking page, adapt the selectors. Generic on purpose: no carrier specifics, no real tracking numbers.

The problem

Plenty of the status you need has no API. It exists only on a page that renders in the browser with JavaScript, sometimes behind a bot check. You cannot fetch it with a plain HTTP request; the HTML that arrives is an empty shell and the real content paints later.

This layer drives a real browser headlessly, lets the page render, reads the status, and writes it back to wherever you track things. No API required.

tracking refs ──> [headless browser: load, wait for render] ──> read status ──> write back
                         one fresh session per ref                       to your sheet/DB

Minimal reference implementation

# delivery_check.py — reference only. Swap in your own URL pattern + selectors + store.
from playwright.sync_api import sync_playwright

def check_one(ref, base_url, status_selector):
    """One ref, one fresh context. Return the rendered status text or None."""
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        ctx = browser.new_context()        # fresh context: no cached state bleeds across refs
        page = ctx.new_page()
        try:
            page.goto(base_url.format(ref=ref), wait_until="domcontentloaded")
            page.wait_for_selector(status_selector, timeout=15000)   # wait for the JS paint
            return page.inner_text(status_selector).strip()
        except Exception:
            return None                     # treat unreadable as unknown, never as delivered
        finally:
            browser.close()                 # close fully so the next ref starts clean

def run(refs, base_url, status_selector, write_back):
    for ref in refs:
        status = check_one(ref, base_url, status_selector)
        write_back(ref, status)             # update your sheet / DB row for this ref

Why it works

Adapt it

Built for my own logistics flow, runs every couple of days; this is the generalised version. Take it, point it at your own tracking page, tell me where it breaks.