FotMob Scraper ⚽ Match Details, Stats, Lineups & Players avatar

FotMob Scraper ⚽ Match Details, Stats, Lineups & Players

Pricing

from $1.20 / 1,000 result records

Go to Apify Store
FotMob Scraper ⚽ Match Details, Stats, Lineups & Players

FotMob Scraper ⚽ Match Details, Stats, Lineups & Players

From $0.8/1K. Pull structured football data from FotMob: match details with scores, team stats, events, lineups, player ratings, H2H, league tables and fixtures, team squads, and player careers. Paste match URLs, pull fixtures by date, or scrape leagues, teams and players.

Pricing

from $1.20 / 1,000 result records

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

1

Bookmarked

2

Total users

1

Monthly active users

3 hours ago

Last modified

Share

FotMob Scraper: Match Details, Stats, Lineups & Players

FotMob Scraper turns FotMob into a clean football data API. Get full match details with scores, team stats, goals and cards, lineups with player ratings, shot-by-shot shotmaps with xG, head-to-head history, league tables and fixtures, team squads and player career histories. Paste match links, pull every fixture on a date, or scrape whole leagues, teams and players, then export to JSON, CSV or Excel, or pull the results straight into your app through the API.

Why This Scraper?

  • Six ways to find data. Matches by id, pasted FotMob links, fixtures on any date, whole leagues, teams or players. No need to build URLs by hand.
  • Full match depth, rival-beating. Every match record carries scores, team stats, events, lineups, flat player-stat rows, shotmaps, team form and player of the match - a superset of the best-known match-details scraper on the store.
  • League, team and player surfaces. League tables with fixtures and seasons, team squads with form, player careers with trophies and recent matches - surfaces a match-only scraper cannot reach.
  • Shot-level xG. The shotmap records every shot's coordinates, shooter, body part, situation and expected goals.
  • Built for schedules. Incremental mode returns only new and changed records on recurring runs, and a refused run fails loudly instead of returning an empty dataset.
  • Cheaper at scale. Results beyond the first 100 in a run bill at the lower bulk rate.

Use Cases

  • Who: sports betting and odds researchers - collect team stats, xG shotmaps, head-to-head records and form to build and backtest models.
  • Who: live score apps and dashboards - feed fixtures, scores, events and ratings into your own site, bot or alerting tool.
  • Who: fantasy sports and scouting teams - track player ratings, positions, squads and career moves across leagues.
  • Who: sports analytics and data science teams - build historical datasets of results, xG-bearing stats and lineups for machine learning.
  • Who: media and content teams - generate match previews, reports and league tables automatically.

Data You Get

Sample shape: values are illustrative placeholders, not from a live record.

FieldExample
type"match" (also "league", "team", "player")
matchId / id4506324
matchName"Aston Villa-vs-Manchester United_Sun, Oct 6, 2024, 13:00 UTC"
matchUrlFotMob link to the match
leagueId / leagueName47 / "Premier League"
round / roundName"7" / "7"
countryCode"ENG"
matchTimeUtc"2024-10-06T13:00:00.000Z"
started / finishedtrue / true
homeTeam / awayTeam{"id": 10252, "name": "Aston Villa", "score": 0}
venuename, city, country, capacity, surface
referee / attendance"Referee Name" / 42682
playerOfTheMatch{"playerId": 268375, "name": "Emiliano Martinez", "teamName": "Aston Villa"}
teamStats[]{group, title, key, home, away} - possession, xG, shots
events[]{type, minute, minuteLabel, isHome, playerId, playerName, homeScore, awayScore, card, goalType, assist, playersInvolved}
lineups{home, away: {teamId, teamName, formation, coach, starters[], subs[]}}
playerStats[]flat per-player rows with ratings, minutes, goals, saves, xG
shotmapevery shot: coordinates, shooter, shotType, situation, expectedGoals
h2hpast meetings between the two teams (when enabled)
leagueTable / fixturesleague records: full table, all fixtures, seasons
squadteam records: full player list
careerHistory / trophies / recentMatchesplayer records
source / scrapedAt"fotmob" / run timestamp

League records also carry seasons, stats and overview; team records carry form, fixtures and transfers; player records carry position, team, birth date and detailed information.

How to Use

  1. Pick a mode: matches (by id), urls (paste links), fixturesByDate (all matches on a date), league, team or player.
  2. Fill in the fields for that mode, and switch on the match details you need.
  3. Set Max items to control run size and cost, then click Start.
  4. Download the dataset as JSON, CSV or Excel, or read it through the API.

One match by id:

{
"mode": "matches",
"matchIds": ["4506324"],
"maxItems": 1
}

Every Premier League fixture on a date:

{
"mode": "fixturesByDate",
"date": "2026-08-29",
"daysAhead": 0,
"leagueIds": ["47"],
"maxItems": 50
}

League table plus fixtures:

{
"mode": "league",
"leagueIds": ["47"],
"season": "2026/2027"
}

Paste links (match, team, player, league):

{
"mode": "urls",
"urls": [
"https://www.fotmob.com/match/4506324",
"https://www.fotmob.com/teams/10252/overview/aston-villa",
"https://www.fotmob.com/players/268375/emiliano-martinez"
]
}

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/fotmob-scraper").call(run_input={"mode": "matches", "matchIds": ["4506324"]})
for match in client.dataset(run["defaultDatasetId"]).iterate_items():
print(match["matchName"], match["homeTeam"], match["awayTeam"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/fotmob-scraper').call({ mode: 'matches', matchIds: ['4506324'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

Resume and recurring updates

  • Resume (resumeFromRunId) continues one interrupted run: paste its run or dataset ID and the actor skips everything already collected there, so you don't pay twice.
  • Incremental mode (incrementalMode) is for scheduled runs over the same scope. Each record is classified NEW, UPDATED (with changedFields), UNCHANGED (suppressed and not billed unless emitUnchanged is on), REAPPEARED or EXPIRED (only after a run that scanned the whole scope, and only with emitExpired). stateKey names or shares the stored state. With incremental mode off, output is exactly as before.

Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

Input Parameters

ParameterTypeDefaultDescription
modestringmatchesmatches, urls, fixturesByDate, league, team, or player.
matchIdsarray["4506324"]Match ids or match URLs (matches mode).
urlsarraysampleFotMob match/team/player/league links (url mode).
datestring2026-08-29YYYY-MM-DD for fixtures mode.
daysAheadinteger0Extra days after date.
leagueIdsarray["47"]League ids (league mode, fixtures scoping).
seasonstring(current)Season label for league mode.
teamIdsarray["10252"]Team ids (team mode).
playerIdsarray["268375"]Player ids (player mode).
includePlayerStatsbooleantrueFlat per-player stat rows + top players.
includeEventsbooleantrueGoals, cards, subs + shotmap.
includeLineupsbooleantrueStarters, subs, formations, coach.
includeTeamStatsbooleantruePossession, shots, xG groups.
includeH2HbooleanfalseHead-to-head + league table snapshot.
includeRawDatabooleanfalseFull embedded page payload.
maxItemsinteger50Stop after this many records (0 = no limit).
maxConcurrencyinteger3Parallel page fetches (max 5).
requestDelaySecsnumber0.5Pause before each page fetch.
resumeFromRunIdstring(none)Continue one interrupted run.
incrementalModebooleanfalseReturn only new and changed records on scheduled runs.
stateKeystring(none)Name or share an incremental-mode state.
emitUnchangedbooleanfalseAlso return (and bill) unchanged records.
emitExpiredbooleanfalseAlso return (and bill) expired records.
ignoreFieldsForChangesarray(none)Fields that never mark a record UPDATED.
proxyobjectApify ProxyConnection settings.
mcpConnectorsarray(none)Optional: send a summary of each record to apps you authorized under Integrations.
notionParentPageUrlstring(none)Notion connector only: page under which records are created.
maxNotifyListingsinteger50Cap on items written to each connector per run.

Output Example

Sample shape: values are illustrative placeholders, not from a live record.

Match record for Aston Villa vs Manchester United (illustrative values):

{
"type": "match",
"id": 4506324,
"matchId": 4506324,
"matchName": "Aston Villa-vs-Manchester United_Sun, Oct 6, 2024, 13:00 UTC",
"matchUrl": "https://www.fotmob.com/match/4506324",
"leagueId": 47,
"leagueName": "Premier League",
"round": "7",
"roundName": "7",
"countryCode": "ENG",
"matchTimeUtc": "2024-10-06T13:00:00.000Z",
"started": true,
"finished": true,
"homeTeam": {"id": 10252, "name": "Aston Villa", "score": 0},
"awayTeam": {"id": 10260, "name": "Manchester United", "score": 0},
"venue": {"name": "Villa Park", "city": "Birmingham", "capacity": 42788},
"referee": "Robert Jones",
"attendance": 42682,
"playerOfTheMatch": {"playerId": 268375, "name": "Emiliano Martinez", "teamName": "Aston Villa"},
"teamStats": [{"group": "Top stats", "title": "Ball possession", "key": "BallPossesion", "home": 54, "away": 46}],
"events": [{"type": "Card", "minute": 3, "minuteLabel": "3", "isHome": false, "playerName": "Christian Eriksen", "card": "Yellow"}],
"lineups": {"home": {"teamName": "Aston Villa", "formation": "4-4-1-1", "coach": "Unai Emery"}},
"playerStats": [{"playerId": 268375, "playerName": "Emiliano Martinez", "rating_title": 8.14}],
"source": "fotmob",
"scrapedAt": "2024-10-06T00:00:00Z"
}

Plan Requirement

The default proxy setting works out of the box, and the actor rotates connections automatically when one is refused. For large or frequent runs, the residential proxy group gives more headroom; pick it under Connection. If your Apify plan does not include proxy access, the run fails with a clear message instead of returning an empty result; a paid plan with proxy access is required.

FAQ

How much does it cost?

You pay per result returned: the first 100 results in a run bill at the standard rate, and anything beyond bills at the lower bulk rate. The Pricing tab shows the current rates. Use Max items to cap the cost of any run.

This actor collects only publicly available football data. You are responsible for how you use it: follow FotMob's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Match results and statistics are generally facts, but logos, photos and shot data may be subject to third-party rights.

Can I get only new or changed matches on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new and updated records, and unchanged ones are not billed.

Why did a fixtures run return fewer matches than the full day?

Fixtures mode discovers matches through the tracked leagues' fixtures (leagueIds, default Premier League). Add more league ids to widen the day, and raise Max items so nothing is cut off.

Why did my run fail instead of returning an empty dataset?

If the site refuses every request, the run stops with a clear message so "no matches today" is never confused with "nothing could be read". Run it again in a few minutes. If only some targets could be read, you still get what was found.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

🔗 Want more sports data?

Pair this actor with these related scrapers from the same team:

⚽ BookMyShow Scraper
Scrape BookMyShow movies and live events by city, category or URL. Extract genres...
⚽ Eventim Scraper
Scrape CTS Eventim Germany and EU event catalogue: concerts, festivals, comedy, sports...
⚽ Globo Esporte Scraper
Scrape public sports content from ge.globo.com, including news, videos, matches and feed...
⚽ JioHotstar Scraper
Scrape the JioHotstar catalog by content type or URL. Extract shows, movies, episodes...
🥦 Lidl.es Products, Weekly Offers, Prices & Reviews Scraper
Scrape Lidl.es grocery and non-food products across weekly offers, tools, home, garden...
⚽ OneFootball Scraper
Scrape public OneFootball data including football news, upcoming fixtures, match results...

👉 Browse all abotapi scrapers

💬 Support & custom scrapers

  • 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com or message Telegram @abotapi.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.