What PostHog traffic looks like
PostHog's endpoint path tells you what a request is before you open it: events, queued batches, or feature-flag config.
- Endpoint pattern
- PostHog Cloud sends to
us.i.posthog.comoreu.i.posthog.com(older setups useapp.posthog.comor bare/e,/capture,/batchpaths);/eand/capturecarry events,/batchcarries queued arrays, and/decideor/flagsare config calls that return feature flags (frequent, but not tracking events) - Transport
- JSON or form-encoded
data=<base64 JSON>, optionally gzip-compressed by the SDK - Key parameters
eventthe name: auto-instrumentation uses dollar-prefixed names ($pageview,$pageleave,$autocapture,$identify) ·properties.distinct_idthe identity key, plus$session_idand$window_id·properties.tokenthe project API key (phc_…) ·$elementson$autocapture: a chain describing the clicked DOM path, the reason autocapture payloads are an order of magnitude larger than custom events- First-party variants
- Self-hosted and reverse-proxied deployments change the hostname entirely, which matters for detection (below)
A typical capture call, as Event Watcher shows it:
{
"event": "$pageview",
"properties": {
"distinct_id": "018f3c…",
"token": "phc_a1b2…",
"$session_id": "018f3c…",
"$current_url": "https://example.dk/pricing"
}
}
Debugging PostHog with Event Watcher
- Classifies each PostHog request by endpoint type (capture, decide/flags, script load) so config chatter doesn't read as event volume.
- The parser decodes the base64 form data and unpacks
/batcharrays into individual events with name,distinct_id, and full properties. - Because
$autocaptureevents all share one name, the Grouped view pivoted by Event Name plus the decoded$elementsdata is the practical way to see what actually got clicked. - Detection is URL-pattern based: a self-hosted instance or a first-party reverse proxy (a setup PostHog itself encourages for ad-blocker resilience) won't match the
posthog.compatterns, so events on such sites surface as raw requests rather than under the PostHog name.
PostHog and consent
Analytics consentThe extension checks PostHog against the analytics consent category. PostHog offers opt_out_capturing() and a cookieless/memory persistence mode, but there is no consent-mode-style degraded ping: a /e request before an analytics grant is a genuine pre-consent event, flagged and counted.
The subtle case: /decide fires on SDK init before consent. It is a config fetch, not an event, but it does transmit the distinct_id, which is worth knowing when writing up an audit.
Common debugging scenarios
- Event volume looks huge. Pivot Grouped view by Event Name to check how much is
$autocaptureand$pageleavebefore assuming custom instrumentation is double-firing. - Flags behave differently than expected. Find the
/decide//flagsresponses in the stream to confirm the calls happen, and when, relative to your first$pageview. - Identity splits across sessions. Compare
distinct_idbefore and after the$identifyevent in the stream. - EU project, US traffic. Verify hits target
eu.i.posthog.comand no stray snippet still points at the US host. - Nothing detected on a site you know runs PostHog. Look for a first-party proxy. The requests will still be in the stream as uncategorized calls with the familiar base64
datashape.