File size: 2,198 Bytes
2bf5989
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 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
  <https://www.fotmob.com/> 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.