Four frontend skills are on sale now. Pay once, download straight away with your licence key.

See the catalogue
AI Skill Up
Browse skills

Mixpanel HTTP API: the CORS error that looks like an outage

Posting JSON to Mixpanel's /track endpoint from a browser fails with a CORS error beside a healthy 200. The fix is one content type, plus two properties.

Posting straight to Mixpanel's /track endpoint keeps your bundle small and your pages fast. It also has a failure mode that wastes an afternoon: every event dies with a CORS error in the console, while the network tab shows a green 200 right beside it.

Why it happens

Sending application/json from the browser forces a preflight OPTIONS request. That preflight succeeds, which is the green 200, but it does not grant permission for the content-type header, so the browser refuses to send the real request. It looks like Mixpanel is down. It is the content type.

The fix

const body = new URLSearchParams({ data: JSON.stringify([event]) });
navigator.sendBeacon("https://api-eu.mixpanel.com/track?ip=1", body)
  || fetch("https://api-eu.mixpanel.com/track?ip=1", { method: "POST", body, keepalive: true });

Form-encoded bodies are on the browser's safe list, so no preflight is sent. Note the data parameter: sending raw JSON under a form content type fails too, because the endpoint reads data. Use the EU host only if your project lives in the EU data centre; a mismatch rejects every event.

The second surprise: Operating System is 'not set'

The SDK reads the user agent and sets $os, $browser, $device and screen size. The HTTP API does not. Parse the user agent yourself, carefully, because order matters: Edge and Opera both contain the string Chrome, every Chromium browser contains Safari, and iPadOS reports itself as a Mac unless you check for touch points.

Once events flow, decide what to send before sending everything: a small event plan for a landing page beats a firehose. And never let private query parameters ride along in the page URL, covered in keeping keys out of analytics.

Questions

Why does my Mixpanel /track request fail with CORS?

A JSON content type makes the browser send a preflight request, and the preflight response does not allow the content-type header. Send the payload form-encoded as data=... instead, which needs no preflight.

Why is Operating System 'not set' in Mixpanel?

The HTTP API does not derive device properties from the User-Agent header. The JavaScript SDK fills them in for you; if you post directly, send $os, $browser and $device yourself.

Why use the HTTP API instead of the SDK?

It adds no bundle weight and can be sent with sendBeacon, so tracking never blocks the page. The cost is that you set the properties the SDK would have set.

Or skip the afternoonand drop one in.

Every skill in the catalogue is a folder you drop into your skills directory. Each ships with its design rules, worked examples and a troubleshooting table, and downloads the moment you pay.