[GH-ISSUE #856] FotMob can't scrape UCL Data #182

Closed
opened 2026-03-02 15:56:27 +03:00 by kerem · 3 comments
Owner

Originally created by @mhassan2048 on GitHub (Jun 2, 2025).
Original GitHub issue: https://github.com/probberechts/soccerdata/issues/856

Describe the bug
A clear and concise description of what the bug is and the expected behavior.

Affected scrapers
This affects the following scrapers:

  • ClubElo
  • ESPN
  • FBref
  • FiveThirtyEight
  • X FotMob
  • Match History
  • SoFIFA
  • Understat
  • WhoScored

Code example
A minimal code example that fails. Use no_cache=True to make sure an invalid cached file does not cause the bug and make sure you have the latest version of soccerdata installed.

import soccerdata as sd

# Confirm what FotMob sees as available
fotmob = sd.FotMob(leagues="EUR-Champions League", seasons="2022/2023")

# Check which leagues and seasons it's trying to load
print("Selected leagues:", fotmob.leagues)
print("Selected seasons:", fotmob.seasons)

# Step 1: Read leagues (should work)
df_leagues = fotmob.read_leagues()
print("✅ Leagues fetched:\n", df_leagues)

# Step 2: Read seasons (this might be empty)
df_seasons = fotmob.read_seasons()
print("✅ Seasons fetched:\n", df_seasons)

# Step 3: Try reading schedule
df_schedule = fotmob.read_schedule()
print("✅ Schedule fetched:\n", df_schedule.head())

Error message

06/01/25 23:21:22] INFO     Saving cached data to /Users/mehedihassan/soccerdata/data/FotMob        [_common.py](file:///opt/anaconda3/lib/python3.12/site-packages/soccerdata/_common.py):[263](file:///opt/anaconda3/lib/python3.12/site-packages/soccerdata/_common.py#263)
Selected leagues: ['EUR-Champions League']
Selected seasons: ['2223']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[17], line 11
      8 print("Selected seasons:", fotmob.seasons)
     10 # Step 1: Read leagues (should work)
---> 11 df_leagues = fotmob.read_leagues()
     12 print("✅ Leagues fetched:\n", df_leagues)
     14 # Step 2: Read seasons (this might be empty)

File /opt/anaconda3/lib/python3.12/site-packages/soccerdata/fotmob.py:133, in FotMob.read_leagues(self)
    123             for dom_league in country["leagues"]:
    124                 leagues.append(
    125                     {
    126                         "region": country["ccode"],
   (...)
    130                     }
    131                 )
    132 df = (
--> 133     pd.DataFrame(leagues)
    134     .assign(league=lambda x: x.region + "-" + x.league)
    135     .pipe(self._translate_league)
    136     .set_index("league")
    137     .loc[self._selected_leagues.keys()]
    138     .sort_index()
    139 )
    140 return df[df.index.isin(self.leagues)]

File /opt/anaconda3/lib/python3.12/site-packages/pandas/core/indexing.py:1191, in _LocationIndexer.__getitem__(self, key)
   1189 maybe_callable = com.apply_if_callable(key, self.obj)
   1190 maybe_callable = self._check_deprecated_callable_usage(key, maybe_callable)
-> 1191 return self._getitem_axis(maybe_callable, axis=axis)

File /opt/anaconda3/lib/python3.12/site-packages/pandas/core/indexing.py:1420, in _LocIndexer._getitem_axis(self, key, axis)
   1417     if hasattr(key, "ndim") and key.ndim > 1:
   1418         raise ValueError("Cannot index with multidimensional key")
-> 1420     return self._getitem_iterable(key, axis=axis)
   1422 # nested tuple slicing
   1423 if is_nested_tuple(key, labels):

File /opt/anaconda3/lib/python3.12/site-packages/pandas/core/indexing.py:1360, in _LocIndexer._getitem_iterable(self, key, axis)
   1357 self._validate_key(key, axis)
   1359 # A collection of keys
-> 1360 keyarr, indexer = self._get_listlike_indexer(key, axis)
   1361 return self.obj._reindex_with_indexers(
   1362     {axis: [keyarr, indexer]}, copy=True, allow_dups=True
   1363 )

File /opt/anaconda3/lib/python3.12/site-packages/pandas/core/indexing.py:1558, in _LocIndexer._get_listlike_indexer(self, key, axis)
   1555 ax = self.obj._get_axis(axis)
   1556 axis_name = self.obj._get_axis_name(axis)
-> 1558 keyarr, indexer = ax._get_indexer_strict(key, axis_name)
   1560 return keyarr, indexer

File /opt/anaconda3/lib/python3.12/site-packages/pandas/core/indexes/base.py:6200, in Index._get_indexer_strict(self, key, axis_name)
   6197 else:
   6198     keyarr, indexer, new_indexer = self._reindex_non_unique(keyarr)
-> 6200 self._raise_if_missing(keyarr, indexer, axis_name)
   6202 keyarr = self.take(indexer)
   6203 if isinstance(key, Index):
   6204     # GH 42790 - Preserve name from an Index

File /opt/anaconda3/lib/python3.12/site-packages/pandas/core/indexes/base.py:6249, in Index._raise_if_missing(self, key, indexer, axis_name)
   6247 if nmissing:
   6248     if nmissing == len(indexer):
-> 6249         raise KeyError(f"None of [{key}] are in the [{axis_name}]")
   6251     not_found = list(ensure_index(key)[missing_mask.nonzero()[0]].unique())
   6252     raise KeyError(f"{not_found} not in index")

KeyError: "None of [Index(['EUR-Champions League'], dtype='object', name='league')] are in the [index]"

Additional context
FotMob is okay to scrape the top 5 leagues but not UCL. I tried to change the league_dict too

{
  "EUR-Champions League": {
    "WhoScored": "Europe - Champions League",
    "FotMob": "Champions League"
  },
  "POR-Liga Portugal": {
    "WhoScored": "Portugal - Liga Portugal"
  }
}

Contributor Action Plan

  • I can fix this issue and will submit a pull request.
  • I’m unsure how to fix this, but I'm willing to work on it with guidance.
  • X I’m not able to fix this issue.
Originally created by @mhassan2048 on GitHub (Jun 2, 2025). Original GitHub issue: https://github.com/probberechts/soccerdata/issues/856 **Describe the bug** A clear and concise description of what the bug is and the expected behavior. **Affected scrapers** This affects the following scrapers: - [ ] ClubElo - [ ] ESPN - [ ] FBref - [ ] FiveThirtyEight - X FotMob - [ ] Match History - [ ] SoFIFA - [ ] Understat - [ ] WhoScored **Code example** A minimal code example that fails. Use `no_cache=True` to make sure an invalid cached file does not cause the bug and make sure you have the latest version of soccerdata installed. ```python import soccerdata as sd # Confirm what FotMob sees as available fotmob = sd.FotMob(leagues="EUR-Champions League", seasons="2022/2023") # Check which leagues and seasons it's trying to load print("Selected leagues:", fotmob.leagues) print("Selected seasons:", fotmob.seasons) # Step 1: Read leagues (should work) df_leagues = fotmob.read_leagues() print("✅ Leagues fetched:\n", df_leagues) # Step 2: Read seasons (this might be empty) df_seasons = fotmob.read_seasons() print("✅ Seasons fetched:\n", df_seasons) # Step 3: Try reading schedule df_schedule = fotmob.read_schedule() print("✅ Schedule fetched:\n", df_schedule.head()) ``` **Error message** ``` 06/01/25 23:21:22] INFO Saving cached data to /Users/mehedihassan/soccerdata/data/FotMob [_common.py](file:///opt/anaconda3/lib/python3.12/site-packages/soccerdata/_common.py):[263](file:///opt/anaconda3/lib/python3.12/site-packages/soccerdata/_common.py#263) Selected leagues: ['EUR-Champions League'] Selected seasons: ['2223'] --------------------------------------------------------------------------- KeyError Traceback (most recent call last) Cell In[17], line 11 8 print("Selected seasons:", fotmob.seasons) 10 # Step 1: Read leagues (should work) ---> 11 df_leagues = fotmob.read_leagues() 12 print("✅ Leagues fetched:\n", df_leagues) 14 # Step 2: Read seasons (this might be empty) File /opt/anaconda3/lib/python3.12/site-packages/soccerdata/fotmob.py:133, in FotMob.read_leagues(self) 123 for dom_league in country["leagues"]: 124 leagues.append( 125 { 126 "region": country["ccode"], (...) 130 } 131 ) 132 df = ( --> 133 pd.DataFrame(leagues) 134 .assign(league=lambda x: x.region + "-" + x.league) 135 .pipe(self._translate_league) 136 .set_index("league") 137 .loc[self._selected_leagues.keys()] 138 .sort_index() 139 ) 140 return df[df.index.isin(self.leagues)] File /opt/anaconda3/lib/python3.12/site-packages/pandas/core/indexing.py:1191, in _LocationIndexer.__getitem__(self, key) 1189 maybe_callable = com.apply_if_callable(key, self.obj) 1190 maybe_callable = self._check_deprecated_callable_usage(key, maybe_callable) -> 1191 return self._getitem_axis(maybe_callable, axis=axis) File /opt/anaconda3/lib/python3.12/site-packages/pandas/core/indexing.py:1420, in _LocIndexer._getitem_axis(self, key, axis) 1417 if hasattr(key, "ndim") and key.ndim > 1: 1418 raise ValueError("Cannot index with multidimensional key") -> 1420 return self._getitem_iterable(key, axis=axis) 1422 # nested tuple slicing 1423 if is_nested_tuple(key, labels): File /opt/anaconda3/lib/python3.12/site-packages/pandas/core/indexing.py:1360, in _LocIndexer._getitem_iterable(self, key, axis) 1357 self._validate_key(key, axis) 1359 # A collection of keys -> 1360 keyarr, indexer = self._get_listlike_indexer(key, axis) 1361 return self.obj._reindex_with_indexers( 1362 {axis: [keyarr, indexer]}, copy=True, allow_dups=True 1363 ) File /opt/anaconda3/lib/python3.12/site-packages/pandas/core/indexing.py:1558, in _LocIndexer._get_listlike_indexer(self, key, axis) 1555 ax = self.obj._get_axis(axis) 1556 axis_name = self.obj._get_axis_name(axis) -> 1558 keyarr, indexer = ax._get_indexer_strict(key, axis_name) 1560 return keyarr, indexer File /opt/anaconda3/lib/python3.12/site-packages/pandas/core/indexes/base.py:6200, in Index._get_indexer_strict(self, key, axis_name) 6197 else: 6198 keyarr, indexer, new_indexer = self._reindex_non_unique(keyarr) -> 6200 self._raise_if_missing(keyarr, indexer, axis_name) 6202 keyarr = self.take(indexer) 6203 if isinstance(key, Index): 6204 # GH 42790 - Preserve name from an Index File /opt/anaconda3/lib/python3.12/site-packages/pandas/core/indexes/base.py:6249, in Index._raise_if_missing(self, key, indexer, axis_name) 6247 if nmissing: 6248 if nmissing == len(indexer): -> 6249 raise KeyError(f"None of [{key}] are in the [{axis_name}]") 6251 not_found = list(ensure_index(key)[missing_mask.nonzero()[0]].unique()) 6252 raise KeyError(f"{not_found} not in index") KeyError: "None of [Index(['EUR-Champions League'], dtype='object', name='league')] are in the [index]" ``` **Additional context** FotMob is okay to scrape the top 5 leagues but not UCL. I tried to change the league_dict too ``` { "EUR-Champions League": { "WhoScored": "Europe - Champions League", "FotMob": "Champions League" }, "POR-Liga Portugal": { "WhoScored": "Portugal - Liga Portugal" } } ``` **Contributor Action Plan** - [ ] I can fix this issue and will submit a pull request. - [ ] I’m unsure how to fix this, but I'm willing to work on it with guidance. - X I’m not able to fix this issue.
kerem 2026-03-02 15:56:27 +03:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@MartiONE commented on GitHub (Jun 8, 2025):

@mhassan2048 the correct league_dict entry is

"INT-Champions League": {
    "WhoScored": "Europe - Champions League",
    "FotMob": "INT-Champions League"
  }

Also change line 4 in your script to:
fotmob = sd.FotMob(leagues="INT-Champions League", seasons="2022/2023")

Champions league is missing from the Leagues supported, any reason for this @probberechts ? Or shall I just add it

<!-- gh-comment-id:2954247315 --> @MartiONE commented on GitHub (Jun 8, 2025): @mhassan2048 the correct `league_dict` entry is ``` "INT-Champions League": { "WhoScored": "Europe - Champions League", "FotMob": "INT-Champions League" } ``` Also change line 4 in your script to: `fotmob = sd.FotMob(leagues="INT-Champions League", seasons="2022/2023")` Champions league is missing from the Leagues supported, any reason for this @probberechts ? Or shall I just add it
Author
Owner

@probberechts commented on GitHub (Jun 8, 2025):

No, I don't want to add more leagues to the supported ones. It's too hard to maintain it. If a non-supported league works out of the box, your lucky. Otherwise, it's up to you to fix the code.

<!-- gh-comment-id:2954249881 --> @probberechts commented on GitHub (Jun 8, 2025): No, I don't want to add more leagues to the supported ones. It's too hard to maintain it. If a non-supported league works out of the box, your lucky. Otherwise, it's up to you to fix the code.
Author
Owner

@DDE1989 commented on GitHub (Nov 9, 2025):

@MartiONE do you happen to know how to pull current season (2025/2026) using FotMob? I am able to pull historical seasons, but havent found a way to get ongoing season for UCL.

<!-- gh-comment-id:3508724703 --> @DDE1989 commented on GitHub (Nov 9, 2025): @MartiONE do you happen to know how to pull current season (2025/2026) using FotMob? I am able to pull historical seasons, but havent found a way to get ongoing season for UCL.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/soccerdata#182
No description provided.