api.simkl.com — you can call it directly from a browser with fetch or XMLHttpRequest, from any origin.
Do not set
User-Agent from browser code. It is a forbidden header name — the browser refuses to let you set it and sends its own. The User-Agent requirement in Headers and required parameters applies to server-side and native clients; identify your browser app with the app-name and app-version URL parameters instead.Setting Content-Type: application/json on a GET has a cost too: it turns a simple request into a preflighted one for no benefit. Send it only on requests that actually have a JSON body.Authenticated calls from a browser
Authorization is named explicitly in the allowed request headers, so a bearer token works cross-origin:
OPTIONS first and Simkl answers it with 204 and an empty body. You do not need to do anything about it; just expect two requests in your network tab rather than one, and note that only the real request counts against your rate limit.
The preflight is cached for 24 hours (Access-Control-Max-Age: 86400), so the extra round-trip happens once per browser session per endpoint shape, not on every call.
Headers you can read
Browsers hide response headers from JavaScript unless the server opts them in. Simkl exposes seven:fetch from another origin; that is the browser’s rule, not Simkl’s.
Errors carry CORS headers too, including the ones answered at the edge before the request reaches Simkl’s application servers. A
401, 403 or 429 is readable from JavaScript exactly like a 200, so you can branch on error in the body rather than guessing from a network failure.An opaque “network error” with no status in a browser is almost always something else — an ad blocker, an extension, or the request never leaving the machine.