UFC & MMA Stats Scraper — Fighters, Fights, Events & Rankings
Pricing
from $50.00 / 1,000 results
UFC & MMA Stats Scraper — Fighters, Fights, Events & Rankings
Build MMA betting models, fantasy tools and fight databases on clean data: bout results with method and round, 42 measured stats per fighter per fight, reach, stance and gym per athlete. 19 promotions — UFC, PFL, ONE, Bellator, plus defunct PRIDE and Strikeforce. UFC back to 1994.
Pricing
from $50.00 / 1,000 results
Rating
0.0
(0)
Developer
Muhamed Didovic
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
Pull complete MMA data from ESPN's public API: every bout with its winner, method, round and finish time, the full 42-stat striking and grappling breakdown for each fighter in each fight, fighter profiles with reach, stance and gym, and every event card with venue. Covers 19 promotions — UFC, PFL, ONE, Bellator, Cage Warriors, KSW, RIZIN and more, including defunct PRIDE, Strikeforce and WEC. UFC history runs back to 1994.

Why Use This Scraper
Most MMA scrapers give you the UFC and stop there. This one covers 19 promotions and reaches back to 1994, so a training set or a betting model is not capped at one organisation's calendar.
It also returns the real statistical line, not just results. Every bout carries 42 measured values per fighter — significant strikes split by head, body and leg across distance, clinch and ground positions; takedowns attempted, landed and their accuracy; guard passes and positional advances; reversals, submissions, knockdowns and time in control. That is the depth serious models need, and it comes from an API with no key, no login and no scraping challenge to defeat.
Overview
| Source | ESPN public MMA API |
| Promotions | 19 (see Supported Inputs) |
| History | UFC from 1994; other promotions vary |
| Modes | Fights, Fight stats, Fighters, Fighter career, Rankings, Events |
| Auth needed | None |
| Output | JSON, CSV, Excel, XML |
Supported Inputs
Promotions accepted in the promotions field:
| Slug | Promotion | Slug | Promotion |
|---|---|---|---|
ufc | Ultimate Fighting Championship | pancrase | Pancrase |
pfl | Professional Fighters League | m1 | M-1 Global |
bellator | Bellator | tfc | Titan FC |
ofc | ONE Championship | strikeforce | Strikeforce |
lfa | Legacy Fighting Alliance | wec | World Extreme Cagefighting |
cage-warriors | Cage Warriors | pride | PRIDE Fighting Championships |
ksw | Konfrontacja Sztuk Walki | xfc | Xtreme Fighting Championships |
rizin | Rizin Fight Federation | k1 | K-1 |
ifc | Invicta FC | dream | Dream |
ifl | International Fight League |
You can also target a run by year, by an explicit YYYYMMDD date range, by specific ESPN event IDs, or by specific fighter IDs.
Use Cases
Betting and prediction models. Per-fighter striking accuracy, takedown defence and control time across a fighter's whole history are the standard feature set for MMA modelling. Pull several seasons in one run.
Fantasy MMA. Finish method and round drive most scoring systems. Fights mode gives both for every bout on a card.
Sports media and stat pages. Event cards with venue, plus fighter bios with reach, stance and gym, populate a fight preview without manual entry.
Historical research. PRIDE, Strikeforce and WEC data lets you compare eras rather than only the current UFC roster.
Fighter scouting. Filter the roster by weight class, stance, reach or gym association.
How It Works
The actor talks to ESPN's core sports API. It lists events for each promotion and year you request, then walks each event down to its bouts, and each bout down to its two competitors, their athlete profiles and their statistical lines. Requests are spaced apart and run at low concurrency by default, because ESPN rate-limits bursts and will refuse traffic for several minutes if pushed too hard. Rows are pushed as they are produced, so a run that hits its result cap still returns everything gathered up to that point.
Input Configuration
| Field | Type | Default | Notes |
|---|---|---|---|
mode | select | fights | fights, fightStats, fighters, fighterCareer, rankings, events |
promotions | array | ["ufc"] | Any of the 19 slugs above |
years | array | current year | Several years per run |
fromDate / toDate | string | — | YYYYMMDD; overrides years |
eventIds | array | — | Restrict to specific ESPN event IDs |
fighterIds | array | — | Restrict Fighters mode to specific athletes |
searchQuery | string | — | Find a fighter by name or nickname; resolves in seconds |
stance | select | — | Orthodox, Southpaw, Switch, Open Stance, Sideways |
minWins / minLosses | integer | — | Filter by career record |
proxyConfiguration | proxy | off | Rotating IPs for long runs; ESPN throttles per address |
maxItems | integer | 1000 | Caps run size and cost |
concurrency | integer | 4 | Raise carefully — ESPN rate-limits |
throttleMs | integer | 120 | Minimum gap between requests |
Example — every 2024 and 2025 UFC bout:
{"mode": "fights","promotions": ["ufc"],"years": [2024, 2025],"maxItems": 2000}
Example — full striking breakdown for one event:
{"mode": "fightStats","promotions": ["ufc"],"eventIds": ["600039893"],"years": [2024]}
Output Overview
Each mode produces one row per entity: one per bout in fights, one per fighter per bout in fightStats (so a bout yields two rows), one per fighter in fighters and fighterCareer, one per ranked fighter in rankings, one per card in events. Every row is flat and one level deep, so it reads the same as JSON or as spreadsheet columns.
Output Samples
Fights
{"recordType": "fight","promotion": "ufc","promotionName": "Ultimate Fighting Championship","fightId": "401623977","eventId": "600039893","eventName": "UFC Fight Night: Ankalaev vs. Walker 2","date": "2024-01-13T21:00Z","weightClass": "Flyweight","scheduledRounds": 3,"roundLengthSeconds": 300,"fighter1Id": "4916248","fighter1Name": "Felipe Bunes","fighter2Id": "5120301","fighter2Name": "Joshua Van","winnerId": "5120301","winnerName": "Joshua Van","loserId": "4916248","loserName": "Felipe Bunes","isDraw": false,"isNoContest": false,"method": "KO/TKO","methodDetail": "Punches","methodTarget": "Head","endRound": 2,"endClock": "4:31","statusType": "STATUS_FINAL","url": "https://www.espn.com/mma/fightcenter/_/id/600039893/league/ufc"}
Fight stats (trimmed — 55 fields per row)
{"recordType": "fightStats","fightId": "401623977","eventName": "UFC Fight Night: Ankalaev vs. Walker 2","weightClass": "Flyweight","fighterId": "4916248","fighterName": "Felipe Bunes","opponentName": "Joshua Van","won": false,"knockDowns": 0,"totalStrikesAttempted": 101,"totalStrikesLanded": 57,"sigStrikesAttempted": 91,"sigStrikesLanded": 50,"sigDistanceHeadStrikesLanded": 28,"takedownsLanded": 0,"takedownAccuracy": 0,"submissions": 0,"timeInControl": 0}
Fighters
{"recordType": "fighter","fighterId": "2354359","fullName": "Jason Reinhardt","nickname": null,"weightClass": "Bantamweight","heightInches": 66,"displayHeight": "5' 6\"","weightPounds": 145,"reachInches": null,"stance": "Orthodox","association": null,"gender": "MALE","active": false,"record": "20-3-0","url": "https://www.espn.com/mma/fighter/_/id/2354359/jason-reinhardt"}
Events
{"recordType": "event","eventId": "600039893","name": "UFC Fight Night: Ankalaev vs. Walker 2","date": "2024-01-13T21:00Z","season": 2024,"venueName": "Meta APEX","venueCity": "Las Vegas","venueState": "NV","venueCountry": "USA","boutCount": 11}
Fighter career (computed from that fighter's own bouts)
{"recordType": "fighterCareer","fighterId": "5120301","fullName": "Joshua Van","nickname": "The Fearless","weightClass": "Flyweight","stance": "Orthodox","reachInches": 65,"association": "4oz Fight Club","record": "17-2-0","fightsFound": 20,"fightsWithStats": 12,"totalFightMinutes": 145.83,"sigStrikesLanded": 1230,"sigStrikesAttempted": 2144,"sigStrikesAbsorbed": 849,"sigStrikesLandedPerMin": 8.43,"sigStrikesAbsorbedPerMin": 5.82,"strikingAccuracy": 0.5737,"strikingDefense": 0.5826,"takedownsPer15Min": 0.82,"takedownAccuracy": 0.6154,"takedownDefense": 0.7568,"submissionsPer15Min": 0.21,"controlSeconds": 640}
Rankings
{"recordType": "ranking","rankingName": "Men's Pound for Pound Rankings","rankingType": "pound-for-pound","gender": "MALE","isChampionGroup": false,"rank": 1,"trend": "-","titleDefenses": 2,"hasAccolade": true,"fighterName": "Kamaru Usman","weightClass": "Welterweight"}
Key Output Fields
| Field | Description |
|---|---|
method / methodDetail / methodTarget | How the fight ended — "KO/TKO", "Submission", "Decision - Unanimous"; detail and target are populated for finishes only |
endRound / endClock | Round and clock at the finish; a decision reads as the final round at full time |
winnerId / loserId | Result, by fighter ID rather than by corner |
isDraw / isNoContest | Kept separate on purpose — a no contest is struck from official records, a draw is not |
weightClass | Contracted weight class for the bout |
sigStrikes* | Significant strikes, split by target (head/body/leg) and position (distance/clinch/ground) |
takedownsLanded / takedownAccuracy | Grappling volume and efficiency |
timeInControl | Control time, in seconds |
reachInches / stance / association | Fighter reach, stance and gym; null when ESPN has no value |
record | Career record summary, e.g. "20-3-0" |
sigStrikesLandedPerMin / AbsorbedPerMin | Career striking volume, per minute of cage time |
strikingAccuracy / strikingDefense | Landed ÷ attempted, and the inverse for strikes faced |
takedownAccuracy / takedownDefense | Grappling efficiency both ways |
fightsFound / fightsWithStats | How many bouts were seen versus how many had a stat line — every rate uses only the latter |
rank / trend / titleDefenses | Ranking position, movement, and title defences for champions |
FAQ
Do I need an API key or ESPN account? No. The source API is public.
Why are methodDetail and methodTarget empty on some rows? They describe the finishing blow. A fight that goes to the judges has no finishing strike, so both are null on decisions. That is correct, not missing data.
Why is reachInches sometimes null? ESPN stores unknown measurements as 0. Reporting a 0 would corrupt any average or filter, so unknowns are returned as null instead.
What is the difference between isDraw and isNoContest? A draw is an official result both fighters keep on their record. A no contest (an illegal blow, or a result overturned afterwards) is struck from the record entirely. Treating them as one value skews win-rate features, so they are separate booleans.
How far back does history go? UFC to 1994. Other promotions vary — PRIDE and Strikeforce cover their active years, PFL and LFA are recent. Ask for a year a promotion did not run and you get an empty result rather than an error.
Why is the default concurrency only 4? ESPN refuses traffic after a burst and stays cold for minutes. The conservative default finishes large runs faster than an aggressive one that gets throttled.
Can I get a single event? Yes — pass its ESPN ID in eventIds along with the year it took place.
Are rankings included? Yes — rankings mode returns 24 groups: every division's rankings and champions, plus men's and women's pound-for-pound, with rank, movement and title defences.
Where do the career rate metrics come from? ESPN publishes no career aggregate for MMA, so fighterCareer sums the fighter's own per-bout stat lines and derives the rates from those totals. Both the totals and the rates ship in the row, so any number can be recomputed or re-weighted. fightsWithStats tells you how many bouts actually carried a stat line — older and regional fights often do not, and those are excluded from every rate rather than counted as zeros.
Why is fighter search fast but an unfiltered fighter run slow? ESPN's roster index returns bare references with no names, so an unfiltered walk fetches every profile. A searchQuery goes through ESPN's search service instead and resolves to ids in one call.
Support
Issues and feature requests go to the actor's Issues tab on Apify Console.
Additional Services
Need a different site scraped, or this data pushed into your own pipeline? Get in touch through the Apify contact form on the actor page.
Explore More Scrapers
- MLB Stats Scraper — baseball teams, players, scores and standings
- Tennis Scraper — Flashscore, SofaScore and TennisExplorer data
🤖 For AI Agents & LLM Apps
This actor is a clean data source for agent pipelines. Every row is flat, typed and one level deep, so it drops straight into a vector store, a dataframe or a tool-call result without reshaping.
Call it from an agent with the Apify MCP server, or directly:
{"mode": "fights","promotions": ["ufc"],"years": [2025],"maxItems": 500}
Field names are stable and self-describing (winnerName, method, endRound, sigStrikesLanded), which keeps prompt overhead low — an LLM can read a row without a schema doc. recordType on every row lets an agent route mixed datasets without inspecting keys.
⚠️ Disclaimer
This actor collects publicly available data from ESPN's public API. It does not access private data, bypass authentication, or defeat access controls. You are responsible for using the collected data in line with ESPN's terms, applicable law, and any restrictions on redistribution. This actor is not affiliated with, endorsed by, or connected to ESPN, the UFC, or any promotion named above. All trademarks belong to their respective owners.
SEO Keywords
UFC scraper, MMA scraper, UFC stats API, MMA stats API, UFC fighter data, UFC fight results scraper, MMA fight statistics, UFC event scraper, fighter profile scraper, significant strikes data, takedown statistics, MMA betting data, fantasy MMA data, PFL scraper, Bellator scraper, ONE Championship data, PRIDE FC historical data, Strikeforce results, Cage Warriors data, KSW scraper, RIZIN data, Invicta FC scraper, MMA historical database, combat sports data, UFC API no key, ESPN MMA API, MMA machine learning dataset, fight card scraper