# Fotmob API access **As of 2026-08-20, fotmob's data API needs no credentials.** There is nothing to refresh. If `fotmob_session.py` reports a failure, it is almost certainly an endpoint change, not an auth problem — read the failure detail it prints. ## History Fotmob used to gate `/api/*` behind an `x-mas` header and a Cloudflare Turnstile challenge, proven by two cookies: `turnstile_verified` and `g_state`. This doc previously told you to copy those two cookies into `.env` every few weeks. That gate is gone. Browsers no longer set `turnstile_verified` at all, and `g_state` turned out to be a Google Sign-In cookie unrelated to fotmob's API. Verified 2026-08-20: `/api/data/leagues`, `/api/data/fixtures`, `/api/data/matchDetails`, `/api/data/teams`, and `/api/data/allLeagues` all return 200 JSON with no cookies whatsoever. The `u:location` cookie is still sent, but it is a location *preference* (pins responses to IST/India formatting), not a credential. `FOTMOB_TURNSTILE_TOKEN` and `FOTMOB_G_STATE` are no longer read by any code and can be deleted from `.env`. ## Health check ``` .venv\Scripts\python.exe fotmob_session.py ``` - `[OK] Fotmob API reachable (no credentials required).` — all good. - `[FAIL] HTTP 404 ...` — the endpoint moved. Update `_HEALTH_URL` in `fotmob_session.py`, and check whether `scrape_luigi.py`'s `fixtures` / `matchDetails` paths moved too. - `[FAIL] HTTP 401/403 ...` — fotmob re-introduced an auth gate. Open in Chrome, DevTools (F12) → **Network** tab, click any `/api/data/...` request, and compare its **Request Headers** against `build_headers()`. Whatever is new is what you need to replicate. - `[FAIL] got HTML instead of JSON` — served a page rather than the API; same fix as 404. ## A note on diagnosing this The previous version of `check_alive()` returned `status_code == 200` and the caller logged "cookies STALE" for *any* failure. It spent weeks reporting a credential problem for what was actually a dead health-check endpoint (`/api/data/tls`, now 404). The current `check_status()` returns the real reason — trust what it says over any assumption that cookies expired.